Version 2.6.0-dev.3.0

Merge commit 'cff2b10a28b2d92249ed23033fe43a8f8b5e7862' into dev
diff --git a/.packages b/.packages
index 435b8d5..281eb23 100644
--- a/.packages
+++ b/.packages
@@ -29,6 +29,7 @@
 csslib:third_party/pkg/csslib/lib
 dart2js_info:third_party/pkg/dart2js_info/lib
 dart2js_tools:pkg/dart2js_tools/lib
+dart2native:pkg/dart2native/lib
 dart_internal:pkg/dart_internal/lib
 dart_style:third_party/pkg_tested/dart_style/lib
 dartdoc:third_party/pkg/dartdoc/lib
diff --git a/BUILD.gn b/BUILD.gn
index 5fd2b63..1aff52e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -86,6 +86,12 @@
   ]
 }
 
+group("create_sdk_nnbd") {
+  public_deps = [
+    "sdk_nnbd:create_sdk_nnbd",
+  ]
+}
+
 if (defined(dart_host_sdk_toolchain) &&
     dart_host_sdk_toolchain != host_toolchain) {
   group("create_host_sdk") {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6efa0d..ee267aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,8 +31,10 @@
 
 #### Linter
 
-The Linter was updated to `0.1.97+1`, which includes:
+The Linter was updated to `0.1.98`, which includes:
 
+* fixed null raw expression accesses in use_to_and_as_if_applicable
+* internal migration to using analyzer `InheritanceManager3`
 * internal migration away from using analyzer `resolutionMap`
 * various fixes and improvements to anticipate support for extension-methods
 * new lint: `camel_case_extensions`
diff --git a/DEPS b/DEPS
index dc46d63..7d7529e 100644
--- a/DEPS
+++ b/DEPS
@@ -82,7 +82,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_tag": "1.2.8",  # Please see the note above before updating.
+  "dart_style_tag": "1.3.0",  # Please see the note above before updating.
 
   "dartdoc_rev" : "6934accd88c29a73cae26d0c4def3323efc2119c",
   "fixnum_tag": "0.10.9",
@@ -99,7 +99,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.97+1",
+  "linter_tag": "0.1.98",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.0.3",
diff --git a/pkg/analysis_server/analysis_options.yaml b/pkg/analysis_server/analysis_options.yaml
index 295dd33..ed8c3c5 100644
--- a/pkg/analysis_server/analysis_options.yaml
+++ b/pkg/analysis_server/analysis_options.yaml
@@ -1,16 +1,37 @@
+include: package:pedantic/analysis_options.1.8.0.yaml
 analyzer:
   # This currently finds ~1,200 implicit-casts issues when enabled.
   # strong-mode:
   #   implicit-casts: false
   exclude:
     - test/mock_packages/**
+  errors:
+    # Ignoring "style" lint rules from pedantic for now. There are pre-existing
+    # violations that need to be cleaned up. Each one can be cleaned up and
+    # enabled according to the value provided.
+    avoid_init_to_null: ignore
+    avoid_return_types_on_setters: ignore
+    curly_braces_in_flow_control_structures: ignore
+    empty_catches: ignore
+    prefer_iterable_wheretype: ignore
+    prefer_contains: ignore
+    # TODO(srawlins): At the time of writing, 2400 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-doc-comments`, but not worth the churn
+    # today.
+    slash_for_doc_comments: ignore
+    # TODO(srawlins): At the time of writing, 20 violations in lib/. The fix
+    # is not mechanical; each violation probably needs to be scrutinized.
+    unawaited_futures: ignore
+    # TODO(srawlins): At the time of writing, 1100 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-optional-const`, but not worth the
+    # churn today.
+    unnecessary_const: ignore
+    # TODO(srawlins): At the time of writing, 2500 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-optional-new`, but not worth the churn
+    # today.
+    unnecessary_new: ignore
 
 linter:
   rules:
-    - empty_constructor_bodies # pedantic
     - empty_statements
-    - prefer_equal_for_default_values # pedantic
-    - prefer_is_empty # pedantic
-    - prefer_is_not_empty # pedantic
     - unnecessary_brace_in_string_interps
-    - valid_regexps # pedantic
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 5a67460..b1173da 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
@@ -6,7 +6,10 @@
 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/info_builder.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -16,6 +19,7 @@
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:path/path.dart' as path;
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
@@ -29,6 +33,16 @@
 
   final DartFixListener listener;
 
+  /// The root of the included paths.
+  ///
+  /// The included paths may contain absolute and relative paths, non-canonical
+  /// paths, and directory and file paths. The "root" is the deepest directory
+  /// which all included paths share.
+  ///
+  /// If instrumentation files are written to [outputDir], they will be written
+  /// as if in a directory structure rooted at [includedRoot].
+  final String includedRoot;
+
   final String outputDir;
 
   InstrumentationListener instrumentationListener;
@@ -40,7 +54,10 @@
   /// If this occurs, then don't update any code.
   bool _packageIsNNBD = true;
 
-  NonNullableFix(this.listener, this.outputDir) {
+  NonNullableFix(this.listener, this.outputDir,
+      {List<String> included = const []})
+      : this.includedRoot =
+            _getIncludedRoot(included, listener.server.resourceProvider) {
     instrumentationListener =
         outputDir == null ? null : InstrumentationListener();
     migration = new NullabilityMigration(
@@ -61,7 +78,7 @@
       if (!outputFolder.exists) {
         outputFolder.create();
       }
-      _generateOutput(outputFolder);
+      await _generateOutput(provider, outputFolder);
     }
   }
 
@@ -196,20 +213,58 @@
   }
 
   /// 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>
-''');
+  void _generateOutput(OverlayResourceProvider provider, Folder folder) async {
+    List<LibraryInfo> libraryInfos = await InfoBuilder(listener.server)
+        .explainMigration(instrumentationListener.data, listener);
+    listener.addDetail('libraryInfos has ${libraryInfos.length} libs');
+    for (LibraryInfo info in libraryInfos) {
+      var pathContext = provider.pathContext;
+      var libraryPath =
+          pathContext.setExtension(info.units.first.path, '.html');
+      // TODO(srawlins): Choose a better scheme than the double underscores,
+      // likely with actual directories, which need to be individually created.
+      var relativePath = pathContext
+          .relative(libraryPath, from: includedRoot)
+          .replaceAll('/', '__');
+      File output = folder.getChildAssumingFile(relativePath);
+      String rendered = InstrumentationRenderer(info).render();
+      output.writeAsStringSync(rendered);
+    }
   }
 
   static void task(DartFixRegistrar registrar, DartFixListener listener,
       EditDartfixParams params) {
-    registrar.registerCodeTask(new NonNullableFix(listener, params.outputDir));
+    registrar.registerCodeTask(new NonNullableFix(listener, params.outputDir,
+        included: params.included));
+  }
+
+  /// Get the "root" of all [included] paths. See [includedRoot] for its
+  /// definition.
+  static String _getIncludedRoot(
+      List<String> included, OverlayResourceProvider provider) {
+    path.Context context = provider.pathContext;
+    // This step looks like it may be expensive (`getResource`, splitting up
+    // all of the paths, comparing parts, joining one path back together). In
+    // practice, this should be cheap because typically only one path is given
+    // to dartfix.
+    List<String> rootParts = included
+        .map((p) => context.absolute(context.canonicalize(p)))
+        .map((p) => provider.getResource(p) is File ? context.dirname(p) : p)
+        .map((p) => context.split(p))
+        .reduce((value, parts) {
+      List<String> shorterPath = value.length < parts.length ? value : parts;
+      int length = shorterPath.length;
+      for (int i = 0; i < length; i++) {
+        if (value[i] != parts[i]) {
+          // [value] and [parts] are the same, only up to part [i].
+          return value.sublist(0, i);
+        }
+      }
+      // [value] and [parts] are the same up to the full length of the shorter
+      // of the two, so just return that.
+      return shorterPath;
+    });
+    return context.joinAll(rootParts);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
new file mode 100644
index 0000000..acd9c24
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+/// A builder used to build the migration information for a library.
+class InfoBuilder {
+  /// The analysis session used to get information about libraries.
+  AnalysisServer server;
+
+  /// Initialize a newly created builder.
+  InfoBuilder(this.server);
+
+  /// Return the migration information for all of the libraries that were
+  /// migrated.
+  Future<List<LibraryInfo>> explainMigration(
+      InstrumentationInformation info, DartFixListener listener) async {
+    Map<Source, SourceInformation> sourceInfo = info.sourceInformation;
+    List<LibraryInfo> libraries = [];
+    for (Source source in sourceInfo.keys) {
+      String filePath = source.fullName;
+      AnalysisSession session =
+          server.getAnalysisDriver(filePath).currentSession;
+      if (!session.getFile(filePath).isPart) {
+        ParsedLibraryResult result = await session.getParsedLibrary(filePath);
+        libraries
+            .add(_explainLibrary(result, info, sourceInfo[source], listener));
+      }
+    }
+    return libraries;
+  }
+
+  /// Return the migration information for the given library.
+  LibraryInfo _explainLibrary(
+      ParsedLibraryResult result,
+      InstrumentationInformation info,
+      SourceInformation sourceInfo,
+      DartFixListener listener) {
+    List<UnitInfo> units = [];
+    for (ParsedUnitResult unit in result.units) {
+      SourceFileEdit edit = listener.sourceChange.getFileEdit(unit.path);
+      units.add(_explainUnit(unit, edit));
+    }
+    return LibraryInfo(units);
+  }
+
+  /// Return the migration information for the given unit.
+  UnitInfo _explainUnit(ParsedUnitResult result, SourceFileEdit fileEdit) {
+    List<RegionInfo> regions = [];
+    String content = result.content;
+    // [fileEdit] is null when a file has no edits.
+    if (fileEdit == null) {
+      return UnitInfo(result.path, content, regions);
+    }
+    List<SourceEdit> edits = fileEdit.edits;
+    edits.sort((first, second) => first.offset.compareTo(second.offset));
+    // Compute the deltas for the regions that will be computed as we apply the
+    // edits. We need the deltas because the offsets to the regions are relative
+    // to the edited source, but the edits are being applied in reverse order so
+    // the offset in the pre-edited source will not match the offset in the
+    // post-edited source. The deltas compensate for that difference.
+    List<int> deltas = [];
+    int previousDelta = 0;
+    for (SourceEdit edit in edits) {
+      deltas.add(previousDelta);
+      previousDelta += (edit.replacement.length - edit.length);
+    }
+    // Apply edits in reverse order and build the regions.
+    int index = edits.length - 1;
+    for (SourceEdit edit in edits.reversed) {
+      int offset = edit.offset;
+      int length = edit.length;
+      String replacement = edit.replacement;
+      int end = offset + length;
+      int delta = deltas[index--];
+      // Insert the replacement text without deleting the replaced text.
+      content = content.replaceRange(end, end, replacement);
+      if (length > 0) {
+        // TODO(brianwilkerson) Create a sensible explanation.
+        regions.add(RegionInfo(offset + delta, length, 'removed'));
+      }
+      // TODO(brianwilkerson) Create a sensible explanation.
+      regions.add(RegionInfo(end + delta, replacement.length, 'added'));
+    }
+    regions.sort((first, second) => first.offset.compareTo(second.offset));
+    return UnitInfo(result.path, content, regions);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index 0fec5d3..5b14508 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -14,32 +14,45 @@
     int previousIndex = 0;
     Map<String, dynamic> mustacheContext = {'units': <Map<String, dynamic>>[]};
     for (var compilationUnit in info.units) {
-      StringBuffer buffer = StringBuffer();
+      // List of Mustache context for both unmodified and modified regions:
+      //
+      // * 'modified': Whether this region represents modified source, or
+      //   unmodified.
+      // * 'content': The textual content of this region.
+      // * 'explanation': The textual explanation of why the content in this
+      //   region was modified. It will appear in a "tooltip" on hover.
+      //   TODO(srawlins): Support some sort of HTML explanation, with
+      //   hyperlinks to anchors in other source code.
+      List<Map> regions = [];
       for (var region in compilationUnit.regions) {
         if (region.offset > previousIndex) {
           // Display a region of unmodified content.
-          buffer.write(
-              compilationUnit.content.substring(previousIndex, region.offset));
+          regions.add({
+            'modified': false,
+            'content':
+                compilationUnit.content.substring(previousIndex, region.offset)
+          });
           previousIndex = region.offset + region.length;
         }
-        buffer.write(_regionWithTooltip(region, compilationUnit.content));
+        regions.add({
+          'modified': true,
+          'content': compilationUnit.content
+              .substring(region.offset, region.offset + region.length),
+          'explanation': region.explanation,
+        });
       }
       if (previousIndex < compilationUnit.content.length) {
         // Last region of unmodified content.
-        buffer.write(compilationUnit.content.substring(previousIndex));
+        regions.add({
+          'modified': false,
+          'content': compilationUnit.content.substring(previousIndex)
+        });
       }
       mustacheContext['units']
-          .add({'path': compilationUnit.path, 'content': buffer.toString()});
+          .add({'path': compilationUnit.path, 'regions': regions});
     }
     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.
@@ -47,35 +60,58 @@
 <html>
   <head>
     <title>Non-nullable fix instrumentation report</title>
+    <script src="highlight.pack.js"></script>
+    <link rel="stylesheet" href="styles/androidstudio.css">
     <style>
+body {
+  font-family: sans-serif;
+  padding: 1em;
+}
+
 h2 {
   font-size: 1em;
   font-weight: bold;
 }
 
-div.content {
+.content {
   font-family: monospace;
-  whitespace: pre;
+  white-space: pre;
+}
+
+.content.highlighting {
+  position: relative;
+}
+
+.regions {
+  position: absolute;
+  top: 0.5em;
+  /* The content of the regions is not visible; the user instead will see the
+   * highlighted copy of the content. */
+  visibility: hidden;
 }
 
 .region {
   /* Green means this region was added. */
-  color: green;
+  background-color: #ccffcc;
+  color: #003300;
+  cursor: default;
   display: inline-block;
   position: relative;
+  visibility: visible;
 }
 
 .region .tooltip {
   background-color: #EEE;
   border: solid 2px #999;
   color: #333;
+  cursor: auto;
   left: 50%;
-  margin-left: -50px;
+  margin-left: -100px;
   padding: 1px;
   position: absolute;
-  top: 120%;
+  top: 100%;
   visibility: hidden;
-  width: 100px;
+  width: 200px;
   z-index: 1;
 }
 
@@ -86,13 +122,31 @@
   </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>
-''');
+    <p><em>Well-written introduction to this report.</em></p>'''
+    '    {{# units }}'
+    '      <h2>{{{ path }}}</h2>'
+    '      <div class="content highlighting">'
+    '{{! These regions are written out, unmodified, as they need to be found }}'
+    '{{! in one simple text string for highlight.js to hightlight them. }}'
+    '{{# regions }}'
+    '{{ content }}'
+    '{{/ regions }}'
+    '      <div class="regions">'
+    '{{! The regions are then printed again, overlaying the first copy of the }}'
+    '{{! content, to provide tooltips for modified regions. }}'
+    '{{# regions }}'
+    '{{^ modified }}{{ content }}{{/ modified }}'
+    '{{# modified }}<span class="region">{{ content }}'
+    '<span class="tooltip">{{explanation}}</span></span>{{/ modified }}'
+    '{{/ regions }}'
+    '</div></div>'
+    '    {{/ units }}'
+    '    <script lang="javascript">'
+    'document.addEventListener("DOMContentLoaded", (event) => {'
+    '  document.querySelectorAll(".highlighting").forEach((block) => {'
+    '    hljs.highlightBlock(block);'
+    '  });'
+    '});'
+    '    </script>'
+    '  </body>'
+    '</html>');
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index f82c19c..e9a48d3 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -207,8 +207,9 @@
     } else if (node is Declaration) {
       if (errors.isNotEmpty) {
         if (_complete_classDeclaration() ||
-            _complete_functionDeclaration() ||
-            _complete_variableDeclaration()) {
+            _complete_variableDeclaration() ||
+            _complete_simpleSemicolon() ||
+            _complete_functionDeclaration()) {
           return completion;
         }
       }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index e0b741a..ed8d65b 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -40,7 +40,7 @@
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/sdk_ext.dart';
-import 'package:path/path.dart' as pathPackage;
+import 'package:path/path.dart' as path;
 
 final String kCustomCss = '''
 .lead, .page-title+.markdown-body>p:first-child {
@@ -170,7 +170,7 @@
       : super(site, 'completion', 'Code Completion',
             description: 'Latency statistics for code completion.');
 
-  pathPackage.Context get pathContext;
+  path.Context get pathContext;
 
   List<CompletionPerformance> get performanceItems;
 
@@ -245,22 +245,22 @@
 
   @override
   Future<void> generateContent(Map<String, String> params) async {
-    String path = params['file'];
-    if (path == null) {
+    String filePath = params['file'];
+    if (filePath == null) {
       p('No file path provided.');
       return;
     }
-    AnalysisDriver driver = server.getAnalysisDriver(path);
+    AnalysisDriver driver = server.getAnalysisDriver(filePath);
     if (driver == null) {
-      p('The file <code>${escape(path)}</code> is not being analyzed.',
+      p('The file <code>${escape(filePath)}</code> is not being analyzed.',
           raw: true);
       return;
     }
-    ResolvedUnitResult result = await driver.getResult(path);
+    ResolvedUnitResult result = await driver.getResult(filePath);
     if (result == null) {
       p(
           'An AST could not be produced for the file '
-          '<code>${escape(path)}</code>.',
+          '<code>${escape(filePath)}</code>.',
           raw: true);
       return;
     }
@@ -372,7 +372,7 @@
       .firstWhere((handler) => handler is CompletionDomainHandler);
 
   @override
-  pathPackage.Context get pathContext =>
+  path.Context get pathContext =>
       completionDomain.server.resourceProvider.pathContext;
 
   @override
@@ -440,7 +440,7 @@
         buf.writeln(
             '<a class="tabnav-tab selected">${escape(f.shortName)}</a>');
       } else {
-        String p = '$path?context=${Uri.encodeQueryComponent(f.path)}';
+        String p = '${this.path}?context=${Uri.encodeQueryComponent(f.path)}';
         buf.writeln(
             '<a href="$p" class="tabnav-tab">${escape(f.shortName)}</a>');
       }
@@ -790,22 +790,22 @@
 
   @override
   Future<void> generateContent(Map<String, String> params) async {
-    String path = params['file'];
-    if (path == null) {
+    String filePath = params['file'];
+    if (filePath == null) {
       p('No file path provided.');
       return;
     }
-    AnalysisDriver driver = server.getAnalysisDriver(path);
+    AnalysisDriver driver = server.getAnalysisDriver(filePath);
     if (driver == null) {
-      p('The file <code>${escape(path)}</code> is not being analyzed.',
+      p('The file <code>${escape(filePath)}</code> is not being analyzed.',
           raw: true);
       return;
     }
-    ResolvedUnitResult result = await driver.getResult(path);
+    ResolvedUnitResult result = await driver.getResult(filePath);
     if (result == null) {
       p(
           'An element model could not be produced for the file '
-          '<code>${escape(path)}</code>.',
+          '<code>${escape(filePath)}</code>.',
           raw: true);
       return;
     }
@@ -994,7 +994,7 @@
   LspCompletionPage(DiagnosticsSite site, this.server) : super(site);
 
   @override
-  pathPackage.Context get pathContext => server.resourceProvider.pathContext;
+  path.Context get pathContext => server.resourceProvider.pathContext;
 
   @override
   List<CompletionPerformance> get performanceItems =>
@@ -1098,7 +1098,7 @@
         Map<String, List<int>> responseTimes =
             PluginManager.pluginResponseTimes[plugin];
 
-        List<String> components = pathPackage.split(id);
+        List<String> components = path.split(id);
         int length = components.length;
         String name;
         if (length == 0) {
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 0990d68..31b2358 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -28,5 +28,6 @@
   analysis_tool: any
   html: any
   http: any
+  pedantic: ^1.8.0
   test_reflective_loader: any
   test: any
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index cabaf02..261ada4 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/edit/edit_dartfix.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:linter/src/rules.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -21,7 +22,6 @@
 @reflectiveTest
 class EditDartfixDomainHandlerTest extends AbstractAnalysisTest {
   int requestId = 30;
-  String libPath;
 
   String get nextRequestId => (++requestId).toString();
 
@@ -78,7 +78,6 @@
   void setUp() {
     super.setUp();
     registerLintRules();
-    libPath = resourceProvider.convertPath('/project/lib');
     testFile = resourceProvider.convertPath('/project/lib/fileToBeFixed.dart');
   }
 
@@ -193,12 +192,7 @@
   }
 
   test_dartfix_nonNullable() async {
-    // Add analysis options to enable non-nullable analysis
-    newFile('/project/analysis_options.yaml', content: '''
-analyzer:
-  enable-experiment:
-    - non-nullable
-''');
+    createAnalysisOptionsFile(experiments: ['non-nullable']);
     addTestFile('''
 int f(int i) => 0;
 int g(int i) => f(i);
@@ -293,12 +287,7 @@
   }
 
   test_dartfix_nonNullable_outputDir() async {
-    // Add analysis options to enable non-nullable analysis
-    newFile('/project/analysis_options.yaml', content: '''
-analyzer:
-  enable-experiment:
-    - non-nullable
-''');
+    createAnalysisOptionsFile(experiments: ['non-nullable']);
     addTestFile('''
 int f(int i) => 0;
 int g(int i) => f(i);
@@ -311,7 +300,10 @@
     await performFix(
         includedFixes: ['non-nullable'], outputDir: outputDir.path);
     expect(outputDir.exists, true);
-    expect(outputDir.getChildren(), isNotEmpty);
+    // TODO(https://github.com/dart-lang/sdk/issues/38574): Fix Windows.
+    if (path.style != path.Style.windows) {
+      expect(outputDir.getChildren(), isNotEmpty);
+    }
   }
 
   test_dartfix_partFile() async {
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
index 8695f99..30e390f 100644
--- a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
@@ -17,18 +17,6 @@
 
 @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;',
@@ -39,8 +27,40 @@
           [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>'));
+    expect(output, contains('<h2>/lib/a.dart</h2>'));
+    expect(output, contains('<h2>/lib/part1.dart</h2>'));
+    expect(output, contains('<h2>/lib/part2.dart</h2>'));
+  }
+
+  test_outputContainsEscapedHtml() async {
+    LibraryInfo info = LibraryInfo([
+      UnitInfo('/lib/a.dart', 'List<String>? a = null;',
+          [RegionInfo(12, 1, 'null was assigned')]),
+    ]);
+    String output = InstrumentationRenderer(info).render();
+    expect(
+        output,
+        contains('List&lt;String&gt;<span class="region">?'
+            '<span class="tooltip">null was assigned</span></span> a = null;'));
+  }
+
+  test_outputContainsEscapedHtml_ampersand() async {
+    LibraryInfo info = LibraryInfo([
+      UnitInfo('/lib/a.dart', 'bool a = true && false;', []),
+    ]);
+    String output = InstrumentationRenderer(info).render();
+    expect(output, contains('bool a = true &amp;&amp; false;'));
+  }
+
+  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;'));
   }
 }
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 083de60..7ec4aee 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
@@ -1712,6 +1712,33 @@
     assertNotSuggested('x');
   }
 
+  test_classReference_in_comment() async {
+    addTestSource(r'''
+class Abc { }
+class Abcd { }
+
+// A^
+class Foo {  }
+''');
+    await computeSuggestions();
+    assertNotSuggested('Abc');
+    assertNotSuggested('Abcd');
+  }
+
+  /// see: https://github.com/dart-lang/sdk/issues/36037
+  @failingTest
+  test_classReference_in_comment_eof() async {
+    addTestSource(r'''
+class Abc { }
+class Abcd { }
+
+// A^
+''');
+    await computeSuggestions();
+    assertNotSuggested('Abc');
+    assertNotSuggested('Abcd');
+  }
+
   test_Combinator_hide() async {
     // SimpleIdentifier  HideCombinator  ImportDirective
     addSource('/home/test/lib/ab.dart', '''
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index 7907820e..1558593 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1365,6 +1365,23 @@
 ''');
   }
 
+  test_expressionBody() async {
+    await _prepareCompletion(
+        '=> 1',
+        '''
+class Thing extends Object {
+  int foo() => 1
+}
+''',
+        atEnd: true);
+    _assertHasChange('Add a semicolon and newline', '''
+class Thing extends Object {
+  int foo() => 1;
+  
+}
+''');
+  }
+
   test_noCloseParen() async {
     await _prepareCompletion(
         'ing(3',
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index b06f849..b1cc002 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -124,7 +124,7 @@
 ''');
     _createRefactoring('test');
     // check conditions
-    _assertInitialConditions_fatal(
+    await _assertInitialConditions_fatal(
         'Only explicit getters can be converted to methods.');
   }
 
diff --git a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
index d8fe817..d426b34 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
@@ -129,7 +129,7 @@
     ExecutableElement element = findElement('test', ElementKind.GETTER);
     _createRefactoringForElement(element);
     // check conditions
-    _assertInitialConditions_fatal(
+    await _assertInitialConditions_fatal(
         'Only class methods or top-level functions can be converted to getters.');
   }
 
@@ -142,7 +142,7 @@
 ''');
     _createRefactoring('test');
     // check conditions
-    _assertInitialConditions_fatal(
+    await _assertInitialConditions_fatal(
         'Only methods without parameters can be converted to getters.');
   }
 
@@ -156,7 +156,7 @@
     ExecutableElement element = findElementsByName(testUnit, 'test').single;
     _createRefactoringForElement(element);
     // check conditions
-    _assertInitialConditions_fatal(
+    await _assertInitialConditions_fatal(
         'Only top-level functions can be converted to getters.');
   }
 
@@ -168,7 +168,7 @@
 ''');
     _createRefactoring('test');
     // check conditions
-    _assertInitialConditions_fatal(
+    await _assertInitialConditions_fatal(
         'Only class methods or top-level functions can be converted to getters.');
   }
 
@@ -178,7 +178,8 @@
 ''');
     _createRefactoring('test');
     // check conditions
-    _assertInitialConditions_fatal('Cannot convert function returning void.');
+    await _assertInitialConditions_fatal(
+        'Cannot convert function returning void.');
   }
 
   Future _assertInitialConditions_fatal(String message) async {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
index 4d8e897..df07bfc 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
@@ -123,7 +123,7 @@
 ''');
     _createRefactoringForString('abc');
     // check conditions
-    _assertInitialConditions_fatal_selection();
+    await _assertInitialConditions_fatal_selection();
   }
 
   test_checkInitialConditions_notPartOfFunction() async {
diff --git a/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
new file mode 100644
index 0000000..8f6487f
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
@@ -0,0 +1,168 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../analysis_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonNullableFixTest);
+  });
+}
+
+@reflectiveTest
+class NonNullableFixTest extends AbstractAnalysisTest {
+  int requestId = 30;
+
+  path.Context context;
+
+  DartFixListener listener;
+
+  String get nextRequestId => (++requestId).toString();
+
+  Future<EditDartfixResult> performFix(
+      {List<String> included, String outputDir}) async {
+    final id = nextRequestId;
+    final params = EditDartfixParams(included);
+    params.includedFixes = ['non-nullable'];
+    params.outputDir = outputDir;
+    Request request = Request(id, 'edit.dartfix', params.toJson());
+    Response response = await EditDartFix(server, request).compute();
+    expect(response.id, id);
+    expect(response.error, isNull);
+    return EditDartfixResult.fromResponse(response);
+  }
+
+  @override
+  Future<void> setUp() async {
+    context = path.style == path.Style.windows
+        // On Windows, ensure that the current drive matches
+        // the drive inserted by MemoryResourceProvider.convertPath
+        // so that packages are mapped to the correct drive
+        ? path.Context(current: 'C:\\project')
+        : path.Context(current: '/project');
+    resourceProvider = MemoryResourceProvider(context: context);
+    super.setUp();
+    newFile('/project/bin/bin.dart', content: 'var x = 1;');
+    newFile('/project/lib/lib1.dart', content: 'var x = 1;');
+    newFile('/project/lib/lib2.dart', content: 'var x = 1;');
+    newFile('/project/lib/src/lib3.dart', content: 'var x = 1;');
+    newFile('/project/test/test.dart', content: 'var x = 1;');
+    newFile('/project2/bin/bin.dart', content: 'var x = 1;');
+    newFile('/project2/lib/lib1.dart', content: 'var x = 1;');
+    newFile('/project2/lib/lib2.dart', content: 'var x = 1;');
+    newFile('/project2/lib/src/lib3.dart', content: 'var x = 1;');
+    newFile('/project2/test/test.dart', content: 'var x = 1;');
+    // Compute the analysis results.
+    server.setAnalysisRoots(
+        '0', [resourceProvider.pathContext.dirname(testFile)], [], {});
+    await server
+        .getAnalysisDriver(testFile)
+        .currentSession
+        .getResolvedUnit(testFile);
+    listener = DartFixListener(server);
+  }
+
+  test_included_multipleRelativeDirectories() async {
+    NonNullableFix fix =
+        NonNullableFix(listener, '.', included: ['lib', 'test']);
+    expect(fix.includedRoot, equals(convertPath('/project')));
+  }
+
+  test_included_multipleRelativeDirectories_nonCanonical() async {
+    NonNullableFix fix = NonNullableFix(listener, '.',
+        included: ['../project2/lib', '../project2/lib/src']);
+    expect(fix.includedRoot, equals(convertPath('/project2/lib')));
+  }
+
+  test_included_multipleRelativeDirectories_nonCanonical_atFilesystemRoot() async {
+    NonNullableFix fix = NonNullableFix(listener, '.',
+        included: ['../project2/lib', '../project/lib']);
+    expect(fix.includedRoot, equals(convertPath('/')));
+  }
+
+  test_included_multipleRelativeDirectories_subAndSuperDirectories() async {
+    NonNullableFix fix = NonNullableFix(listener, '.', included: ['lib', '.']);
+    expect(fix.includedRoot, equals(convertPath('/project')));
+  }
+
+  test_included_multipleRelativeFiles() async {
+    NonNullableFix fix = NonNullableFix(listener, '.',
+        included: ['lib/lib1.dart', 'test/test.dart']);
+    expect(fix.includedRoot, equals(convertPath('/project')));
+  }
+
+  test_included_multipleRelativeFiles_sameDirectory() async {
+    NonNullableFix fix = NonNullableFix(listener, '.',
+        included: ['lib/lib1.dart', 'lib/lib2.dart']);
+    expect(fix.includedRoot, equals(convertPath('/project/lib')));
+  }
+
+  test_included_multipleRelativeFilesAndDirectories() async {
+    NonNullableFix fix = NonNullableFix(listener, '.',
+        included: ['lib/lib1.dart', 'lib/src', '../project/lib/src/lib3.dart']);
+    expect(fix.includedRoot, equals(convertPath('/project/lib')));
+  }
+
+  test_included_singleAbsoluteDirectory() async {
+    NonNullableFix fix = NonNullableFix(listener, '.', included: ['/project']);
+    expect(fix.includedRoot, equals(convertPath('/project')));
+  }
+
+  test_included_singleAbsoluteFile() async {
+    NonNullableFix fix =
+        NonNullableFix(listener, '.', included: ['/project/bin/bin.dart']);
+    expect(fix.includedRoot, equals(convertPath('/project/bin')));
+  }
+
+  test_included_singleRelativeDirectory() async {
+    NonNullableFix fix = NonNullableFix(listener, '.', included: ['.']);
+    expect(fix.includedRoot, equals(convertPath('/project')));
+  }
+
+  test_outputDirContainsFilesRootedAtProjectPath() async {
+    createProject();
+    Folder outputDir = getFolder('/outputDir');
+    await performFix(included: [projectPath], outputDir: outputDir.path);
+    expect(outputDir.exists, true);
+    expect(outputDir.getChildAssumingFile('bin__bin.html').exists, isTrue);
+    expect(outputDir.getChildAssumingFile('lib__lib1.html').exists, isTrue);
+    expect(outputDir.getChildAssumingFile('lib__lib2.html').exists, isTrue);
+    expect(
+        outputDir.getChildAssumingFile('lib__src__lib3.html').exists, isTrue);
+    expect(outputDir.getChildAssumingFile('test__test.html').exists, isTrue);
+  }
+
+  test_outputDirContainsFilesRootedInASubdirectory() async {
+    createProject();
+    Folder outputDir = getFolder('/outputDir');
+    await performFix(
+        included: [context.join(projectPath, 'lib')],
+        outputDir: outputDir.path);
+    expect(outputDir.exists, true);
+    expect(outputDir.getChildAssumingFile('lib1.html').exists, isTrue);
+    expect(outputDir.getChildAssumingFile('lib2.html').exists, isTrue);
+    expect(outputDir.getChildAssumingFile('src__lib3.html').exists, isTrue);
+  }
+
+  test_outputDirContainsFilesRootedInParentOfSingleFile() async {
+    createProject();
+    Folder outputDir = getFolder('/outputDir');
+    await performFix(
+        included: [context.join(projectPath, 'lib', 'lib2.dart')],
+        outputDir: outputDir.path);
+    expect(outputDir.exists, true);
+    expect(outputDir.getChildAssumingFile('lib2.html').exists, isTrue);
+  }
+}
diff --git a/pkg/analysis_server/test/src/edit/fix/test_all.dart b/pkg/analysis_server/test/src/edit/fix/test_all.dart
new file mode 100644
index 0000000..1bf972c
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/fix/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 'non_nullable_fix_test.dart' as non_nullable_fix;
+
+main() {
+  defineReflectiveSuite(() {
+    non_nullable_fix.main();
+  }, name: 'fix');
+}
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
new file mode 100644
index 0000000..f300740
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -0,0 +1,81 @@
+// 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:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/info_builder.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../analysis_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InfoBuilderTest);
+  });
+}
+
+@reflectiveTest
+class InfoBuilderTest extends AbstractAnalysisTest {
+  /// The information produced by the InfoBuilder, or `null` if [buildInfo] has
+  /// not yet completed.
+  List<LibraryInfo> infos;
+
+  /// Use the InfoBuilder to build information. The information will be stored
+  /// in [infos].
+  Future<void> buildInfo() async {
+    // Compute the analysis results.
+    server.setAnalysisRoots(
+        '0', [resourceProvider.pathContext.dirname(testFile)], [], {});
+    ResolvedUnitResult result = await server
+        .getAnalysisDriver(testFile)
+        .currentSession
+        .getResolvedUnit(testFile);
+    // Run the migration engine.
+    DartFixListener listener = DartFixListener(server);
+    InstrumentationListener instrumentationListener = InstrumentationListener();
+    NullabilityMigration migration = new NullabilityMigration(
+        new NullabilityMigrationAdapter(listener),
+        permissive: false,
+        instrumentation: instrumentationListener);
+    migration.prepareInput(result);
+    migration.processInput(result);
+    migration.finish();
+    // Build the migration info.
+    InfoBuilder builder = InfoBuilder(server);
+    InstrumentationInformation info = instrumentationListener.data;
+    infos = await builder.explainMigration(info, listener);
+  }
+
+  test_parameter_nullableFromInvocation() async {
+    addTestFile('''
+void f(String s) {}
+void g() {
+  f(null);
+}
+''');
+    await buildInfo();
+    expect(infos, hasLength(1));
+    List<UnitInfo> units = infos[0].units;
+    expect(units, hasLength(1));
+    UnitInfo unit = units[0];
+    expect(unit.path, testFile);
+    expect(unit.content, '''
+void f(String? s) {}
+void g() {
+  f(null);
+}
+''');
+    List<RegionInfo> regions = unit.regions;
+    expect(regions, hasLength(1));
+    RegionInfo region = regions[0];
+    expect(region.offset, 13);
+    expect(region.length, 1);
+  }
+}
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
new file mode 100644
index 0000000..b7ddf83
--- /dev/null
+++ b/pkg/analysis_server/test/src/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 'info_builder_test.dart' as info_builder;
+
+main() {
+  defineReflectiveSuite(() {
+    info_builder.main();
+  }, name: 'nnbd_migration');
+}
diff --git a/pkg/analysis_server/test/src/edit/test_all.dart b/pkg/analysis_server/test/src/edit/test_all.dart
new file mode 100644
index 0000000..9e41ed2
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/test_all.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix/test_all.dart' as fix;
+import 'nnbd_migration/test_all.dart' as nnbd_migration;
+
+main() {
+  defineReflectiveSuite(() {
+    fix.main();
+    nnbd_migration.main();
+  }, name: 'edit');
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index d3aaded..da0dd43 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -284,7 +284,7 @@
 import 'package:flutter/material.dart';
 /*caret*/main() {}
 ''');
-    assertNoAssist();
+    await assertNoAssist();
   }
 
   test_notStatelessWidget() async {
@@ -295,7 +295,7 @@
   MyWidget() : super('');
 }
 ''');
-    assertNoAssist();
+    await assertNoAssist();
   }
 
   test_notWidget() async {
@@ -304,7 +304,7 @@
 import 'package:flutter/material.dart';
 class /*caret*/MyWidget {}
 ''');
-    assertNoAssist();
+    await assertNoAssist();
   }
 
   test_simple() async {
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index a45add5..39637af 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -7,6 +7,7 @@
 import 'computer/test_all.dart' as computer;
 import 'domain_abstract_test.dart' as domain_abstract;
 import 'domains/test_all.dart' as domains;
+import 'edit/test_all.dart' as edit;
 import 'flutter/test_all.dart' as flutter;
 import 'lsp/test_all.dart' as lsp;
 import 'plugin/test_all.dart' as plugin;
@@ -22,6 +23,7 @@
     computer.main();
     domain_abstract.main();
     domains.main();
+    edit.main();
     flutter.main();
     lsp.main();
     plugin.main();
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 04cd0e5..274f08e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.38.4
+* Bug fixes: #33300, #38484, #38505.
+
 ## 0.38.3
 * Deprecated the following codes from `StaticWarningCode`.  Please use the
   corresponding error codes from `CompileTimeErrorCode` instead:
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 1c02e60..46298e7 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -1,13 +1,37 @@
+include: package:pedantic/analysis_options.1.8.0.yaml
 analyzer:
   # This currently finds ~4,500 implicit-casts issues when enabled.
   # strong-mode:
   #   implicit-casts: false
+  errors:
+    # Ignoring "style" lint rules from pedantic for now. There are pre-existing
+    # violations that need to be cleaned up. Each one can be cleaned up and
+    # enabled according to the value provided.
+    avoid_init_to_null: ignore
+    avoid_return_types_on_setters: ignore
+    curly_braces_in_flow_control_structures: ignore
+    empty_catches: ignore
+    prefer_iterable_wheretype: ignore
+    prefer_contains: ignore
+    # TODO(srawlins): Fix existing violations!
+    no_duplicate_case_values: ignore
+    # TODO(srawlins): At the time of writing, 230 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-named-default-separator`.
+    prefer_equal_for_default_values: ignore
+    # TODO(srawlins): At the time of writing, 2600 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-doc-comments`, but not worth the churn
+    # today.
+    slash_for_doc_comments: ignore
+    # TODO(srawlins): At the time of writing, 970 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-optional-const`, but not worth the
+    # churn today.
+    unnecessary_const: ignore
+    # TODO(srawlins): At the time of writing, 3200 violations in lib/. The fix
+    # is mechanical, via `dartfmt --fix-optional-new`, but not worth the churn
+    # today.
+    unnecessary_new: ignore
 
 linter:
   rules:
-    - empty_constructor_bodies # pedantic
     - empty_statements
-    - prefer_is_empty # pedantic
-    - prefer_is_not_empty # pedantic
     - unnecessary_brace_in_string_interps
-    - valid_regexps # pedantic
diff --git a/pkg/analyzer/lib/dart/analysis/features.dart b/pkg/analyzer/lib/dart/analysis/features.dart
index 575c7de..561a4db 100644
--- a/pkg/analyzer/lib/dart/analysis/features.dart
+++ b/pkg/analyzer/lib/dart/analysis/features.dart
@@ -32,6 +32,9 @@
   /// Feature information for the triple-shift operator.
   static const triple_shift = ExperimentalFeatures.triple_shift;
 
+  /// Feature information for variance.
+  static const variance = ExperimentalFeatures.variance;
+
   /// If the feature may be enabled or disabled on the command line, the
   /// experimental flag that may be used to enable it.  Otherwise `null`.
   ///
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 0dfe3fa..72e7f56 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -196,6 +196,7 @@
   CompileTimeErrorCode.INVALID_URI,
   CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
   CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION,
+  CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
   CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
   CompileTimeErrorCode.LABEL_UNDEFINED,
   CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
@@ -303,6 +304,7 @@
   CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
   CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
   CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
+  CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
   CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
   CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER,
   CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
@@ -556,6 +558,7 @@
   ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES,
   ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS,
   ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
+  ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS,
   ParserErrorCode.MULTIPLE_WITH_CLAUSES,
   ParserErrorCode.NAMED_FUNCTION_EXPRESSION,
   ParserErrorCode.NAMED_FUNCTION_TYPE,
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 86d5b66..6efad5a 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
 import 'package:meta/meta.dart';
 
 export 'package:analyzer/src/dart/ast/constant_evaluator.dart';
@@ -2482,1164 +2481,6 @@
 }
 
 /**
- * An object that will clone any AST structure that it visits. The cloner will
- * clone the structure, replacing the specified ASTNode with a new ASTNode,
- * mapping the old token stream to a new token stream, and preserving resolution
- * results.
- */
-@deprecated
-class IncrementalAstCloner implements AstVisitor<AstNode> {
-  /**
-   * The node to be replaced during the cloning process.
-   */
-  final AstNode _oldNode;
-
-  /**
-   * The replacement node used during the cloning process.
-   */
-  final AstNode _newNode;
-
-  /**
-   * A mapping of old tokens to new tokens used during the cloning process.
-   */
-  final TokenMap _tokenMap;
-
-  /**
-   * Construct a new instance that will replace the [oldNode] with the [newNode]
-   * in the process of cloning an existing AST structure. The [tokenMap] is a
-   * mapping of old tokens to new tokens.
-   */
-  IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap);
-
-  @override
-  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
-      astFactory.adjacentStrings(_cloneNodeList(node.strings));
-
-  @override
-  Annotation visitAnnotation(Annotation node) {
-    Annotation copy = astFactory.annotation(
-        _mapToken(node.atSign),
-        _cloneNode(node.name),
-        _mapToken(node.period),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.arguments));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ArgumentList visitArgumentList(ArgumentList node) => astFactory.argumentList(
-      _mapToken(node.leftParenthesis),
-      _cloneNodeList(node.arguments),
-      _mapToken(node.rightParenthesis));
-
-  @override
-  AsExpression visitAsExpression(AsExpression node) {
-    AsExpression copy = astFactory.asExpression(_cloneNode(node.expression),
-        _mapToken(node.asOperator), _cloneNode(node.type));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitAssertInitializer(AssertInitializer node) =>
-      astFactory.assertInitializer(
-          _mapToken(node.assertKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.condition),
-          _mapToken(node.comma),
-          _cloneNode(node.message),
-          _mapToken(node.rightParenthesis));
-
-  @override
-  AstNode visitAssertStatement(AssertStatement node) =>
-      astFactory.assertStatement(
-          _mapToken(node.assertKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.condition),
-          _mapToken(node.comma),
-          _cloneNode(node.message),
-          _mapToken(node.rightParenthesis),
-          _mapToken(node.semicolon));
-
-  @override
-  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
-    AssignmentExpression copy = astFactory.assignmentExpression(
-        _cloneNode(node.leftHandSide),
-        _mapToken(node.operator),
-        _cloneNode(node.rightHandSide));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
-      astFactory.awaitExpression(
-          _mapToken(node.awaitKeyword), _cloneNode(node.expression));
-
-  @override
-  BinaryExpression visitBinaryExpression(BinaryExpression node) {
-    BinaryExpression copy = astFactory.binaryExpression(
-        _cloneNode(node.leftOperand),
-        _mapToken(node.operator),
-        _cloneNode(node.rightOperand));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Block visitBlock(Block node) => astFactory.block(_mapToken(node.leftBracket),
-      _cloneNodeList(node.statements), _mapToken(node.rightBracket));
-
-  @override
-  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
-      astFactory.blockFunctionBody(_mapToken(node.keyword),
-          _mapToken(node.star), _cloneNode(node.block));
-
-  @override
-  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
-    BooleanLiteral copy =
-        astFactory.booleanLiteral(_mapToken(node.literal), node.value);
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  BreakStatement visitBreakStatement(BreakStatement node) =>
-      astFactory.breakStatement(_mapToken(node.breakKeyword),
-          _cloneNode(node.label), _mapToken(node.semicolon));
-
-  @override
-  CascadeExpression visitCascadeExpression(CascadeExpression node) {
-    CascadeExpression copy = astFactory.cascadeExpression(
-        _cloneNode(node.target), _cloneNodeList(node.cascadeSections));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  CatchClause visitCatchClause(CatchClause node) => astFactory.catchClause(
-      _mapToken(node.onKeyword),
-      _cloneNode(node.exceptionType),
-      _mapToken(node.catchKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.exceptionParameter),
-      _mapToken(node.comma),
-      _cloneNode(node.stackTraceParameter),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.body));
-
-  @override
-  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
-    ClassDeclaration copy = astFactory.classDeclaration(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.abstractKeyword),
-        _mapToken(node.classKeyword),
-        _cloneNode(node.name),
-        _cloneNode(node.typeParameters),
-        _cloneNode(node.extendsClause),
-        _cloneNode(node.withClause),
-        _cloneNode(node.implementsClause),
-        _mapToken(node.leftBracket),
-        _cloneNodeList(node.members),
-        _mapToken(node.rightBracket));
-    copy.nativeClause = _cloneNode(node.nativeClause);
-    return copy;
-  }
-
-  @override
-  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) =>
-      astFactory.classTypeAlias(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.typedefKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _mapToken(node.equals),
-          _mapToken(node.abstractKeyword),
-          _cloneNode(node.superclass),
-          _cloneNode(node.withClause),
-          _cloneNode(node.implementsClause),
-          _mapToken(node.semicolon));
-
-  @override
-  Comment visitComment(Comment node) {
-    if (node.isDocumentation) {
-      return astFactory.documentationComment(
-          _mapTokens(node.tokens), _cloneNodeList(node.references));
-    } else if (node.isBlock) {
-      return astFactory.blockComment(_mapTokens(node.tokens));
-    }
-    return astFactory.endOfLineComment(_mapTokens(node.tokens));
-  }
-
-  @override
-  CommentReference visitCommentReference(CommentReference node) =>
-      astFactory.commentReference(
-          _mapToken(node.newKeyword), _cloneNode(node.identifier));
-
-  @override
-  CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    CompilationUnitImpl copy = astFactory.compilationUnit(
-        beginToken: _mapToken(node.beginToken),
-        scriptTag: _cloneNode(node.scriptTag),
-        directives: _cloneNodeList(node.directives),
-        declarations: _cloneNodeList(node.declarations),
-        endToken: _mapToken(node.endToken),
-        featureSet: node.featureSet);
-    copy.lineInfo = node.lineInfo;
-    copy.declaredElement = node.declaredElement;
-    return copy;
-  }
-
-  @override
-  ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
-    ConditionalExpression copy = astFactory.conditionalExpression(
-        _cloneNode(node.condition),
-        _mapToken(node.question),
-        _cloneNode(node.thenExpression),
-        _mapToken(node.colon),
-        _cloneNode(node.elseExpression));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Configuration visitConfiguration(Configuration node) =>
-      astFactory.configuration(
-          _mapToken(node.ifKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.name),
-          _mapToken(node.equalToken),
-          _cloneNode(node.value),
-          _mapToken(node.rightParenthesis),
-          _cloneNode(node.uri));
-
-  @override
-  ConstructorDeclaration visitConstructorDeclaration(
-      ConstructorDeclaration node) {
-    ConstructorDeclarationImpl copy = astFactory.constructorDeclaration(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.externalKeyword),
-        _mapToken(node.constKeyword),
-        _mapToken(node.factoryKeyword),
-        _cloneNode(node.returnType),
-        _mapToken(node.period),
-        _cloneNode(node.name),
-        _cloneNode(node.parameters),
-        _mapToken(node.separator),
-        _cloneNodeList(node.initializers),
-        _cloneNode(node.redirectedConstructor),
-        _cloneNode(node.body));
-    copy.declaredElement = node.declaredElement;
-    return copy;
-  }
-
-  @override
-  ConstructorFieldInitializer visitConstructorFieldInitializer(
-          ConstructorFieldInitializer node) =>
-      astFactory.constructorFieldInitializer(
-          _mapToken(node.thisKeyword),
-          _mapToken(node.period),
-          _cloneNode(node.fieldName),
-          _mapToken(node.equals),
-          _cloneNode(node.expression));
-
-  @override
-  ConstructorName visitConstructorName(ConstructorName node) {
-    ConstructorName copy = astFactory.constructorName(
-        _cloneNode(node.type), _mapToken(node.period), _cloneNode(node.name));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  ContinueStatement visitContinueStatement(ContinueStatement node) =>
-      astFactory.continueStatement(_mapToken(node.continueKeyword),
-          _cloneNode(node.label), _mapToken(node.semicolon));
-
-  @override
-  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
-      astFactory.declaredIdentifier(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _cloneNode(node.identifier));
-
-  @override
-  DefaultFormalParameter visitDefaultFormalParameter(
-          DefaultFormalParameter node) =>
-      astFactory.defaultFormalParameter(_cloneNode(node.parameter), node.kind,
-          _mapToken(node.separator), _cloneNode(node.defaultValue));
-
-  @override
-  DoStatement visitDoStatement(DoStatement node) => astFactory.doStatement(
-      _mapToken(node.doKeyword),
-      _cloneNode(node.body),
-      _mapToken(node.whileKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.rightParenthesis),
-      _mapToken(node.semicolon));
-
-  @override
-  DottedName visitDottedName(DottedName node) =>
-      astFactory.dottedName(_cloneNodeList(node.components));
-
-  @override
-  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) {
-    DoubleLiteral copy =
-        astFactory.doubleLiteral(_mapToken(node.literal), node.value);
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
-      astFactory.emptyFunctionBody(_mapToken(node.semicolon));
-
-  @override
-  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
-      astFactory.emptyStatement(_mapToken(node.semicolon));
-
-  @override
-  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      astFactory.enumConstantDeclaration(_cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata), _cloneNode(node.name));
-
-  @override
-  AstNode visitEnumDeclaration(EnumDeclaration node) =>
-      astFactory.enumDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.enumKeyword),
-          _cloneNode(node.name),
-          _mapToken(node.leftBracket),
-          _cloneNodeList(node.constants),
-          _mapToken(node.rightBracket));
-
-  @override
-  ExportDirective visitExportDirective(ExportDirective node) {
-    ExportDirective copy = astFactory.exportDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.keyword),
-        _cloneNode(node.uri),
-        _cloneNodeList(node.configurations),
-        _cloneNodeList(node.combinators),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ExpressionFunctionBody visitExpressionFunctionBody(
-          ExpressionFunctionBody node) =>
-      astFactory.expressionFunctionBody(
-          _mapToken(node.keyword),
-          _mapToken(node.functionDefinition),
-          _cloneNode(node.expression),
-          _mapToken(node.semicolon));
-
-  @override
-  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
-      astFactory.expressionStatement(
-          _cloneNode(node.expression), _mapToken(node.semicolon));
-
-  @override
-  ExtendsClause visitExtendsClause(ExtendsClause node) =>
-      astFactory.extendsClause(
-          _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
-
-  @override
-  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
-      astFactory.extensionDeclaration(
-          comment: _cloneNode(node.documentationComment),
-          metadata: _cloneNodeList(node.metadata),
-          extensionKeyword: _mapToken(node.extensionKeyword),
-          name: _cloneNode(node.name),
-          typeParameters: _cloneNode(node.typeParameters),
-          onKeyword: _mapToken(node.onKeyword),
-          extendedType: _cloneNode(node.extendedType),
-          leftBracket: _mapToken(node.leftBracket),
-          members: _cloneNodeList(node.members),
-          rightBracket: _mapToken(node.rightBracket));
-
-  @override
-  ExtensionOverride visitExtensionOverride(ExtensionOverride node) =>
-      astFactory.extensionOverride(
-          extensionName: _cloneNode(node.extensionName),
-          typeArguments: _cloneNode(node.typeArguments),
-          argumentList: _cloneNode(node.argumentList));
-
-  @override
-  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
-      astFactory.fieldDeclaration2(
-          comment: _cloneNode(node.documentationComment),
-          metadata: _cloneNodeList(node.metadata),
-          covariantKeyword: _mapToken(node.covariantKeyword),
-          staticKeyword: _mapToken(node.staticKeyword),
-          fieldList: _cloneNode(node.fields),
-          semicolon: _mapToken(node.semicolon));
-
-  @override
-  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
-      astFactory.fieldFormalParameter2(
-          comment: _cloneNode(node.documentationComment),
-          metadata: _cloneNodeList(node.metadata),
-          covariantKeyword: _mapToken(node.covariantKeyword),
-          keyword: _mapToken(node.keyword),
-          type: _cloneNode(node.type),
-          thisKeyword: _mapToken(node.thisKeyword),
-          period: _mapToken(node.period),
-          identifier: _cloneNode(node.identifier),
-          typeParameters: _cloneNode(node.typeParameters),
-          parameters: _cloneNode(node.parameters));
-
-  @override
-  ForEachPartsWithDeclaration visitForEachPartsWithDeclaration(
-          ForEachPartsWithDeclaration node) =>
-      astFactory.forEachPartsWithDeclaration(
-          loopVariable: _cloneNode(node.loopVariable),
-          inKeyword: _mapToken(node.inKeyword),
-          iterable: _cloneNode(node.iterable));
-
-  @override
-  ForEachPartsWithIdentifier visitForEachPartsWithIdentifier(
-          ForEachPartsWithIdentifier node) =>
-      astFactory.forEachPartsWithIdentifier(
-          identifier: _cloneNode(node.identifier),
-          inKeyword: _mapToken(node.inKeyword),
-          iterable: _cloneNode(node.iterable));
-
-  @override
-  ForElement visitForElement(ForElement node) => astFactory.forElement(
-      awaitKeyword: _mapToken(node.awaitKeyword),
-      forKeyword: _mapToken(node.forKeyword),
-      leftParenthesis: _mapToken(node.leftParenthesis),
-      forLoopParts: _cloneNode(node.forLoopParts),
-      rightParenthesis: _mapToken(node.rightParenthesis),
-      body: _cloneNode(node.body));
-
-  @override
-  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
-      astFactory.formalParameterList(
-          _mapToken(node.leftParenthesis),
-          _cloneNodeList(node.parameters),
-          _mapToken(node.leftDelimiter),
-          _mapToken(node.rightDelimiter),
-          _mapToken(node.rightParenthesis));
-
-  @override
-  ForPartsWithDeclarations visitForPartsWithDeclarations(
-          ForPartsWithDeclarations node) =>
-      astFactory.forPartsWithDeclarations(
-          variables: _cloneNode(node.variables),
-          leftSeparator: _mapToken(node.leftSeparator),
-          condition: _cloneNode(node.condition),
-          rightSeparator: _mapToken(node.rightSeparator),
-          updaters: _cloneNodeList(node.updaters));
-
-  @override
-  ForPartsWithExpression visitForPartsWithExpression(
-          ForPartsWithExpression node) =>
-      astFactory.forPartsWithExpression(
-          initialization: _cloneNode(node.initialization),
-          leftSeparator: _mapToken(node.leftSeparator),
-          condition: _cloneNode(node.condition),
-          rightSeparator: _mapToken(node.rightSeparator),
-          updaters: _cloneNodeList(node.updaters));
-
-  @override
-  ForStatement visitForStatement(ForStatement node) => astFactory.forStatement(
-      awaitKeyword: _mapToken(node.awaitKeyword),
-      forKeyword: _mapToken(node.forKeyword),
-      leftParenthesis: _mapToken(node.leftParenthesis),
-      forLoopParts: _cloneNode(node.forLoopParts),
-      rightParenthesis: _mapToken(node.rightParenthesis),
-      body: _cloneNode(node.body));
-
-  @override
-  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
-      astFactory.functionDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.externalKeyword),
-          _cloneNode(node.returnType),
-          _mapToken(node.propertyKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.functionExpression));
-
-  @override
-  FunctionDeclarationStatement visitFunctionDeclarationStatement(
-          FunctionDeclarationStatement node) =>
-      astFactory
-          .functionDeclarationStatement(_cloneNode(node.functionDeclaration));
-
-  @override
-  FunctionExpression visitFunctionExpression(FunctionExpression node) {
-    FunctionExpressionImpl copy = astFactory.functionExpression(
-        _cloneNode(node.typeParameters),
-        _cloneNode(node.parameters),
-        _cloneNode(node.body));
-    copy.declaredElement = node.declaredElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  FunctionExpressionInvocation visitFunctionExpressionInvocation(
-      FunctionExpressionInvocation node) {
-    FunctionExpressionInvocation copy = astFactory.functionExpressionInvocation(
-        _cloneNode(node.function),
-        _cloneNode(node.typeArguments),
-        _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
-      astFactory.functionTypeAlias(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.typedefKeyword),
-          _cloneNode(node.returnType),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters),
-          _mapToken(node.semicolon));
-
-  @override
-  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
-          FunctionTypedFormalParameter node) =>
-      astFactory.functionTypedFormalParameter2(
-          comment: _cloneNode(node.documentationComment),
-          metadata: _cloneNodeList(node.metadata),
-          covariantKeyword: _mapToken(node.covariantKeyword),
-          returnType: _cloneNode(node.returnType),
-          identifier: _cloneNode(node.identifier),
-          typeParameters: _cloneNode(node.typeParameters),
-          parameters: _cloneNode(node.parameters),
-          question: _mapToken(node.question));
-
-  @override
-  AstNode visitGenericFunctionType(GenericFunctionType node) =>
-      astFactory.genericFunctionType(
-          _cloneNode(node.returnType),
-          _mapToken(node.functionKeyword),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters),
-          question: _mapToken(node.question));
-
-  @override
-  AstNode visitGenericTypeAlias(GenericTypeAlias node) =>
-      astFactory.genericTypeAlias(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.typedefKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _mapToken(node.equals),
-          _cloneNode(node.functionType),
-          _mapToken(node.semicolon));
-
-  @override
-  HideCombinator visitHideCombinator(HideCombinator node) =>
-      astFactory.hideCombinator(
-          _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
-
-  @override
-  IfElement visitIfElement(IfElement node) => astFactory.ifElement(
-      ifKeyword: _mapToken(node.ifKeyword),
-      leftParenthesis: _mapToken(node.leftParenthesis),
-      condition: _cloneNode(node.condition),
-      rightParenthesis: _mapToken(node.rightParenthesis),
-      thenElement: _cloneNode(node.thenElement),
-      elseKeyword: _mapToken(node.elseKeyword),
-      elseElement: _cloneNode(node.elseElement));
-
-  @override
-  IfStatement visitIfStatement(IfStatement node) => astFactory.ifStatement(
-      _mapToken(node.ifKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.thenStatement),
-      _mapToken(node.elseKeyword),
-      _cloneNode(node.elseStatement));
-
-  @override
-  ImplementsClause visitImplementsClause(ImplementsClause node) =>
-      astFactory.implementsClause(
-          _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
-
-  @override
-  ImportDirective visitImportDirective(ImportDirective node) {
-    ImportDirective copy = astFactory.importDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.keyword),
-        _cloneNode(node.uri),
-        _cloneNodeList(node.configurations),
-        _mapToken(node.deferredKeyword),
-        _mapToken(node.asKeyword),
-        _cloneNode(node.prefix),
-        _cloneNodeList(node.combinators),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  IndexExpression visitIndexExpression(IndexExpression node) {
-    Token period = _mapToken(node.period);
-    IndexExpression copy;
-    if (period == null) {
-      copy = astFactory.indexExpressionForTarget(
-          _cloneNode(node.target),
-          _mapToken(node.leftBracket),
-          _cloneNode(node.index),
-          _mapToken(node.rightBracket));
-    } else {
-      copy = astFactory.indexExpressionForCascade(
-          period,
-          _mapToken(node.leftBracket),
-          _cloneNode(node.index),
-          _mapToken(node.rightBracket));
-    }
-    copy.auxiliaryElements = node.auxiliaryElements;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  InstanceCreationExpression visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    InstanceCreationExpression copy = astFactory.instanceCreationExpression(
-        _mapToken(node.keyword),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  IntegerLiteral visitIntegerLiteral(IntegerLiteral node) {
-    IntegerLiteral copy =
-        astFactory.integerLiteral(_mapToken(node.literal), node.value);
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  InterpolationExpression visitInterpolationExpression(
-          InterpolationExpression node) =>
-      astFactory.interpolationExpression(_mapToken(node.leftBracket),
-          _cloneNode(node.expression), _mapToken(node.rightBracket));
-
-  @override
-  InterpolationString visitInterpolationString(InterpolationString node) =>
-      astFactory.interpolationString(_mapToken(node.contents), node.value);
-
-  @override
-  IsExpression visitIsExpression(IsExpression node) {
-    IsExpression copy = astFactory.isExpression(
-        _cloneNode(node.expression),
-        _mapToken(node.isOperator),
-        _mapToken(node.notOperator),
-        _cloneNode(node.type));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Label visitLabel(Label node) =>
-      astFactory.label(_cloneNode(node.label), _mapToken(node.colon));
-
-  @override
-  LabeledStatement visitLabeledStatement(LabeledStatement node) =>
-      astFactory.labeledStatement(
-          _cloneNodeList(node.labels), _cloneNode(node.statement));
-
-  @override
-  LibraryDirective visitLibraryDirective(LibraryDirective node) {
-    LibraryDirective copy = astFactory.libraryDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.libraryKeyword),
-        _cloneNode(node.name),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
-    LibraryIdentifier copy =
-        astFactory.libraryIdentifier(_cloneNodeList(node.components));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ListLiteral visitListLiteral(ListLiteral node) {
-    ListLiteral copy = astFactory.listLiteral(
-        _mapToken(node.constKeyword),
-        _cloneNode(node.typeArguments),
-        _mapToken(node.leftBracket),
-        _cloneNodeList(node.elements),
-        _mapToken(node.rightBracket));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
-      astFactory.mapLiteralEntry(_cloneNode(node.key),
-          _mapToken(node.separator), _cloneNode(node.value));
-
-  @override
-  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
-      astFactory.methodDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.externalKeyword),
-          _mapToken(node.modifierKeyword),
-          _cloneNode(node.returnType),
-          _mapToken(node.propertyKeyword),
-          _mapToken(node.operatorKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters),
-          _cloneNode(node.body));
-
-  @override
-  MethodInvocation visitMethodInvocation(MethodInvocation node) {
-    MethodInvocation copy = astFactory.methodInvocation(
-        _cloneNode(node.target),
-        _mapToken(node.operator),
-        _cloneNode(node.methodName),
-        _cloneNode(node.typeArguments),
-        _cloneNode(node.argumentList));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitMixinDeclaration(MixinDeclaration node) =>
-      astFactory.mixinDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.mixinKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.onClause),
-          _cloneNode(node.implementsClause),
-          _mapToken(node.leftBracket),
-          _cloneNodeList(node.members),
-          _mapToken(node.rightBracket));
-
-  @override
-  NamedExpression visitNamedExpression(NamedExpression node) {
-    NamedExpression copy = astFactory.namedExpression(
-        _cloneNode(node.name), _cloneNode(node.expression));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitNativeClause(NativeClause node) => astFactory.nativeClause(
-      _mapToken(node.nativeKeyword), _cloneNode(node.name));
-
-  @override
-  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
-      astFactory.nativeFunctionBody(_mapToken(node.nativeKeyword),
-          _cloneNode(node.stringLiteral), _mapToken(node.semicolon));
-
-  @override
-  NullLiteral visitNullLiteral(NullLiteral node) {
-    NullLiteral copy = astFactory.nullLiteral(_mapToken(node.literal));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitOnClause(OnClause node) => astFactory.onClause(
-      _mapToken(node.onKeyword), _cloneNodeList(node.superclassConstraints));
-
-  @override
-  ParenthesizedExpression visitParenthesizedExpression(
-      ParenthesizedExpression node) {
-    ParenthesizedExpression copy = astFactory.parenthesizedExpression(
-        _mapToken(node.leftParenthesis),
-        _cloneNode(node.expression),
-        _mapToken(node.rightParenthesis));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PartDirective visitPartDirective(PartDirective node) {
-    PartDirective copy = astFactory.partDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.partKeyword),
-        _cloneNode(node.uri),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  PartOfDirective visitPartOfDirective(PartOfDirective node) {
-    PartOfDirective copy = astFactory.partOfDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.partKeyword),
-        _mapToken(node.ofKeyword),
-        _cloneNode(node.uri),
-        _cloneNode(node.libraryName),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  PostfixExpression visitPostfixExpression(PostfixExpression node) {
-    PostfixExpression copy = astFactory.postfixExpression(
-        _cloneNode(node.operand), _mapToken(node.operator));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
-    PrefixedIdentifier copy = astFactory.prefixedIdentifier(
-        _cloneNode(node.prefix),
-        _mapToken(node.period),
-        _cloneNode(node.identifier));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PrefixExpression visitPrefixExpression(PrefixExpression node) {
-    PrefixExpression copy = astFactory.prefixExpression(
-        _mapToken(node.operator), _cloneNode(node.operand));
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PropertyAccess visitPropertyAccess(PropertyAccess node) {
-    PropertyAccess copy = astFactory.propertyAccess(_cloneNode(node.target),
-        _mapToken(node.operator), _cloneNode(node.propertyName));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation copy =
-        astFactory.redirectingConstructorInvocation(
-            _mapToken(node.thisKeyword),
-            _mapToken(node.period),
-            _cloneNode(node.constructorName),
-            _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  RethrowExpression visitRethrowExpression(RethrowExpression node) {
-    RethrowExpression copy =
-        astFactory.rethrowExpression(_mapToken(node.rethrowKeyword));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ReturnStatement visitReturnStatement(ReturnStatement node) =>
-      astFactory.returnStatement(_mapToken(node.returnKeyword),
-          _cloneNode(node.expression), _mapToken(node.semicolon));
-
-  @override
-  ScriptTag visitScriptTag(ScriptTag node) =>
-      astFactory.scriptTag(_mapToken(node.scriptTag));
-
-  @override
-  SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) {
-    SetOrMapLiteral copy = astFactory.setOrMapLiteral(
-        constKeyword: _mapToken(node.constKeyword),
-        typeArguments: _cloneNode(node.typeArguments),
-        leftBracket: _mapToken(node.leftBracket),
-        elements: _cloneNodeList(node.elements),
-        rightBracket: _mapToken(node.rightBracket));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory
-      .showCombinator(_mapToken(node.keyword), _cloneNodeList(node.shownNames));
-
-  @override
-  SimpleFormalParameter visitSimpleFormalParameter(
-          SimpleFormalParameter node) =>
-      astFactory.simpleFormalParameter2(
-          comment: _cloneNode(node.documentationComment),
-          metadata: _cloneNodeList(node.metadata),
-          covariantKeyword: _mapToken(node.covariantKeyword),
-          keyword: _mapToken(node.keyword),
-          type: _cloneNode(node.type),
-          identifier: _cloneNode(node.identifier));
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
-    Token mappedToken = _mapToken(node.token);
-    if (mappedToken == null) {
-      // This only happens for SimpleIdentifiers created by the parser as part
-      // of scanning documentation comments (the tokens for those identifiers
-      // are not in the original token stream and hence do not get copied).
-      // This extra check can be removed if the scanner is changed to scan
-      // documentation comments for the parser.
-      mappedToken = node.token;
-    }
-    SimpleIdentifier copy = astFactory.simpleIdentifier(mappedToken,
-        isDeclaration: node.inDeclarationContext());
-    copy.auxiliaryElements = node.auxiliaryElements;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) {
-    SimpleStringLiteral copy =
-        astFactory.simpleStringLiteral(_mapToken(node.literal), node.value);
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SpreadElement visitSpreadElement(SpreadElement node) =>
-      astFactory.spreadElement(
-          spreadOperator: _mapToken(node.spreadOperator),
-          expression: _cloneNode(node.expression));
-
-  @override
-  StringInterpolation visitStringInterpolation(StringInterpolation node) {
-    StringInterpolation copy =
-        astFactory.stringInterpolation(_cloneNodeList(node.elements));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SuperConstructorInvocation visitSuperConstructorInvocation(
-      SuperConstructorInvocation node) {
-    SuperConstructorInvocation copy = astFactory.superConstructorInvocation(
-        _mapToken(node.superKeyword),
-        _mapToken(node.period),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  SuperExpression visitSuperExpression(SuperExpression node) {
-    SuperExpression copy =
-        astFactory.superExpression(_mapToken(node.superKeyword));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SwitchCase visitSwitchCase(SwitchCase node) => astFactory.switchCase(
-      _cloneNodeList(node.labels),
-      _mapToken(node.keyword),
-      _cloneNode(node.expression),
-      _mapToken(node.colon),
-      _cloneNodeList(node.statements));
-
-  @override
-  SwitchDefault visitSwitchDefault(SwitchDefault node) =>
-      astFactory.switchDefault(
-          _cloneNodeList(node.labels),
-          _mapToken(node.keyword),
-          _mapToken(node.colon),
-          _cloneNodeList(node.statements));
-
-  @override
-  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
-      astFactory.switchStatement(
-          _mapToken(node.switchKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.expression),
-          _mapToken(node.rightParenthesis),
-          _mapToken(node.leftBracket),
-          _cloneNodeList(node.members),
-          _mapToken(node.rightBracket));
-
-  @override
-  AstNode visitSymbolLiteral(SymbolLiteral node) {
-    SymbolLiteral copy = astFactory.symbolLiteral(
-        _mapToken(node.poundSign), _mapTokens(node.components));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ThisExpression visitThisExpression(ThisExpression node) {
-    ThisExpression copy =
-        astFactory.thisExpression(_mapToken(node.thisKeyword));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ThrowExpression visitThrowExpression(ThrowExpression node) {
-    ThrowExpression copy = astFactory.throwExpression(
-        _mapToken(node.throwKeyword), _cloneNode(node.expression));
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
-          TopLevelVariableDeclaration node) =>
-      astFactory.topLevelVariableDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _cloneNode(node.variables),
-          _mapToken(node.semicolon));
-
-  @override
-  TryStatement visitTryStatement(TryStatement node) => astFactory.tryStatement(
-      _mapToken(node.tryKeyword),
-      _cloneNode(node.body),
-      _cloneNodeList(node.catchClauses),
-      _mapToken(node.finallyKeyword),
-      _cloneNode(node.finallyBlock));
-
-  @override
-  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
-      astFactory.typeArgumentList(_mapToken(node.leftBracket),
-          _cloneNodeList(node.arguments), _mapToken(node.rightBracket));
-
-  @override
-  TypeName visitTypeName(TypeName node) {
-    TypeName copy = astFactory.typeName(
-        _cloneNode(node.name), _cloneNode(node.typeArguments),
-        question: _mapToken(node.question));
-    copy.type = node.type;
-    return copy;
-  }
-
-  @override
-  TypeParameter visitTypeParameter(TypeParameter node) =>
-      astFactory.typeParameter(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _cloneNode(node.name),
-          _mapToken(node.extendsKeyword),
-          _cloneNode(node.bound));
-
-  @override
-  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
-      astFactory.typeParameterList(_mapToken(node.leftBracket),
-          _cloneNodeList(node.typeParameters), _mapToken(node.rightBracket));
-
-  @override
-  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
-      astFactory.variableDeclaration(_cloneNode(node.name),
-          _mapToken(node.equals), _cloneNode(node.initializer));
-
-  @override
-  VariableDeclarationList visitVariableDeclarationList(
-          VariableDeclarationList node) =>
-      astFactory.variableDeclarationList(
-          null,
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _cloneNodeList(node.variables));
-
-  @override
-  VariableDeclarationStatement visitVariableDeclarationStatement(
-          VariableDeclarationStatement node) =>
-      astFactory.variableDeclarationStatement(
-          _cloneNode(node.variables), _mapToken(node.semicolon));
-
-  @override
-  WhileStatement visitWhileStatement(WhileStatement node) =>
-      astFactory.whileStatement(
-          _mapToken(node.whileKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.condition),
-          _mapToken(node.rightParenthesis),
-          _cloneNode(node.body));
-
-  @override
-  WithClause visitWithClause(WithClause node) => astFactory.withClause(
-      _mapToken(node.withKeyword), _cloneNodeList(node.mixinTypes));
-
-  @override
-  YieldStatement visitYieldStatement(YieldStatement node) =>
-      astFactory.yieldStatement(
-          _mapToken(node.yieldKeyword),
-          _mapToken(node.star),
-          _cloneNode(node.expression),
-          _mapToken(node.semicolon));
-
-  E _cloneNode<E extends AstNode>(E node) {
-    if (node == null) {
-      return null;
-    }
-    if (identical(node, _oldNode)) {
-      return _newNode as E;
-    }
-    return node.accept(this) as E;
-  }
-
-  List<E> _cloneNodeList<E extends AstNode>(NodeList<E> nodes) {
-    List<E> clonedNodes = new List<E>();
-    for (E node in nodes) {
-      clonedNodes.add(_cloneNode(node));
-    }
-    return clonedNodes;
-  }
-
-  Token _mapToken(Token oldToken) {
-    if (oldToken == null) {
-      return null;
-    }
-    return _tokenMap.get(oldToken);
-  }
-
-  List<Token> _mapTokens(List<Token> oldTokens) {
-    List<Token> newTokens = new List<Token>(oldTokens.length);
-    for (int index = 0; index < newTokens.length; index++) {
-      newTokens[index] = _mapToken(oldTokens[index]);
-    }
-    return newTokens;
-  }
-}
-
-/**
  * An object used to locate the [AstNode] associated with a source range, given
  * the AST structure built from the source. More specifically, they will return
  * the [AstNode] with the shortest length whose source range completely
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index ca2c1e5..f5b08f4 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -514,7 +514,7 @@
     if (formalCount == 0 && !force) return original;
 
     // Allocate fresh type variables
-    var typeVars = <DartType>[];
+    var typeVars = <TypeParameterElement>[];
     var freshTypeVars = <DartType>[];
     var freshVarElements = <TypeParameterElement>[];
     for (int i = 0; i < formalCount; i++) {
@@ -524,7 +524,7 @@
           new TypeParameterElementImpl.synthetic(typeParamElement.name);
       var freshTypeVar = new TypeParameterTypeImpl(freshElement);
 
-      typeVars.add(typeParamElement.type);
+      typeVars.add(typeParamElement);
       freshTypeVars.add(freshTypeVar);
       freshVarElements.add(freshElement);
     }
@@ -535,7 +535,8 @@
       var bound = typeParamElement.bound;
       if (bound != null) {
         var freshElement = freshVarElements[i] as TypeParameterElementImpl;
-        freshElement.bound = bound.substitute2(freshTypeVars, typeVars);
+        freshElement.bound = Substitution.fromPairs(typeVars, freshTypeVars)
+            .substituteType(bound);
       }
     }
 
@@ -747,7 +748,7 @@
         }
 
         List<DartType> instantiateTypeArgs = <DartType>[];
-        List<DartType> variables = <DartType>[];
+        List<TypeParameterElement> variables = <TypeParameterElement>[];
         typeParametersBuffer.write('<');
         for (TypeParameterElement e in typeFormals) {
           if (e != typeFormals[0]) {
@@ -769,11 +770,12 @@
           t.appendTo(typeParametersBuffer, visitedTypes,
               withNullability: withNullability);
           instantiateTypeArgs.add(t);
-          variables.add(e.type);
+          variables.add(e);
           if (e.bound != null) {
             typeParametersBuffer.write(' extends ');
             TypeImpl renamed =
-                e.bound.substitute2(instantiateTypeArgs, variables);
+                Substitution.fromPairs(variables, instantiateTypeArgs)
+                    .substituteType(e.bound);
             renamed.appendTo(typeParametersBuffer, visitedTypes);
           }
         }
@@ -1173,8 +1175,8 @@
     // We build up a substitution matching up the type parameters
     // from the two types, {variablesFresh/variables1} and
     // {variablesFresh/variables2}
-    List<DartType> variables1 = <DartType>[];
-    List<DartType> variables2 = <DartType>[];
+    List<TypeParameterElement> variables1 = <TypeParameterElement>[];
+    List<TypeParameterElement> variables2 = <TypeParameterElement>[];
     List<DartType> variablesFresh = <DartType>[];
     for (int i = 0; i < count; i++) {
       TypeParameterElement p1 = params1[i];
@@ -1182,18 +1184,18 @@
       TypeParameterElementImpl pFresh =
           new TypeParameterElementImpl.synthetic(p2.name);
 
-      DartType variable1 = p1.type;
-      DartType variable2 = p2.type;
       DartType variableFresh = new TypeParameterTypeImpl(pFresh);
 
-      variables1.add(variable1);
-      variables2.add(variable2);
+      variables1.add(p1);
+      variables2.add(p2);
       variablesFresh.add(variableFresh);
 
       DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
       DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
-      bound1 = bound1.substitute2(variablesFresh, variables1);
-      bound2 = bound2.substitute2(variablesFresh, variables2);
+      bound1 = Substitution.fromPairs(variables1, variablesFresh)
+          .substituteType(bound1);
+      bound2 = Substitution.fromPairs(variables2, variablesFresh)
+          .substituteType(bound2);
       if (!relation(bound2, bound1, p2, p1)) {
         return null;
       }
@@ -1706,8 +1708,8 @@
   bool isDirectSupertypeOf(InterfaceType type) {
     InterfaceType i = this;
     InterfaceType j = type;
+    var substitution = Substitution.fromInterfaceType(j);
     ClassElement jElement = j.element;
-    InterfaceType supertype = jElement.supertype;
     //
     // If J is Object, then it has no direct supertypes.
     //
@@ -1717,10 +1719,9 @@
     //
     // I is listed in the extends clause of J.
     //
-    List<DartType> jArgs = j.typeArguments;
-    List<DartType> jVars = jElement.type.typeArguments;
+    InterfaceType supertype = jElement.supertype;
     if (supertype != null) {
-      supertype = supertype.substitute2(jArgs, jVars);
+      supertype = substitution.substituteType(supertype);
       if (supertype == i) {
         return true;
       }
@@ -1729,7 +1730,7 @@
     // I is listed in the on clause of J.
     //
     for (InterfaceType interfaceType in jElement.superclassConstraints) {
-      interfaceType = interfaceType.substitute2(jArgs, jVars);
+      interfaceType = substitution.substituteType(interfaceType);
       if (interfaceType == i) {
         return true;
       }
@@ -1738,7 +1739,7 @@
     // I is listed in the implements clause of J.
     //
     for (InterfaceType interfaceType in jElement.interfaces) {
-      interfaceType = interfaceType.substitute2(jArgs, jVars);
+      interfaceType = substitution.substituteType(interfaceType);
       if (interfaceType == i) {
         return true;
       }
@@ -1747,7 +1748,7 @@
     // I is listed in the with clause of J.
     //
     for (InterfaceType mixinType in jElement.mixins) {
-      mixinType = mixinType.substitute2(jArgs, jVars);
+      mixinType = substitution.substituteType(mixinType);
       if (mixinType == i) {
         return true;
       }
@@ -2855,8 +2856,6 @@
 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
   static bool _comparingBounds = false;
 
-  static bool _appendingBounds = false;
-
   @override
   final NullabilitySuffix nullabilitySuffix;
 
@@ -2898,29 +2897,6 @@
     return false;
   }
 
-  /**
-   * Append a textual representation of this type to the given [buffer]. The set
-   * of [visitedTypes] is used to prevent infinite recursion.
-   */
-  void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
-      {bool withNullability = false}) {
-    super.appendTo(buffer, visitedTypes, withNullability: withNullability);
-    TypeParameterElement e = element;
-    if (e is TypeParameterMember &&
-        e.bound != e.baseElement.bound &&
-        !_appendingBounds) {
-      buffer.write(' extends ');
-      // If we're appending bounds already, we don't want to do it recursively.
-      _appendingBounds = true;
-      try {
-        (e.bound as TypeImpl)
-            .appendTo(buffer, visitedTypes, withNullability: withNullability);
-      } finally {
-        _appendingBounds = false;
-      }
-    }
-  }
-
   @override
   bool isMoreSpecificThan(DartType s,
       [bool withDynamic = false, Set<Element> visitedElements]) {
@@ -3580,10 +3556,12 @@
     if (argumentTypes.isEmpty) {
       return this;
     }
-    var parameterTypes = typeFormals.map((p) => p.type).toList();
+
+    var substitution = Substitution.fromPairs(typeFormals, argumentTypes);
+
     ParameterElement transformParameter(ParameterElement p) {
       var type = p.type;
-      var newType = type.substitute2(argumentTypes, parameterTypes);
+      var newType = substitution.substituteType(type);
       if (identical(newType, type)) return p;
       return new ParameterElementImpl.synthetic(
           p.name,
@@ -3594,7 +3572,7 @@
     }
 
     return new _FunctionTypeImplStrict._(
-        returnType.substitute2(argumentTypes, parameterTypes),
+        substitution.substituteType(returnType),
         const [],
         _transformOrShare(parameters, transformParameter),
         nullabilitySuffix: nullabilitySuffix);
@@ -3612,56 +3590,12 @@
           "argumentTypes.length (${argumentTypes.length}) != "
           "parameterTypes.length (${parameterTypes.length})");
     }
-    TypeParameterElement transformTypeFormal(TypeParameterElement p) {
-      var bound = p.bound;
-      var newBound = bound?.substitute2(argumentTypes, parameterTypes);
-      if (identical(bound, newBound)) return p;
-      var element = new TypeParameterElementImpl.synthetic(p.name);
-      element.bound = newBound;
-      return element;
-    }
 
-    var newTypeFormals = _transformOrShare(typeFormals, transformTypeFormal);
-    List<DartType> typeFormalsArgumentTypes;
-    List<DartType> typeFormalsParameterTypes;
-    if (!identical(typeFormals, newTypeFormals)) {
-      typeFormalsArgumentTypes = newTypeFormals.map((p) => p.type).toList();
-      typeFormalsParameterTypes = typeFormals.map((p) => p.type).toList();
-    }
-    DartType transformType(DartType t) {
-      t = t.substitute2(argumentTypes, parameterTypes);
-      if (typeFormalsArgumentTypes != null) {
-        t = t.substitute2(typeFormalsArgumentTypes, typeFormalsParameterTypes);
-      }
-      return t;
-    }
-
-    ParameterElement transformParameter(ParameterElement p) {
-      var type = p.type;
-      var newType = transformType(type);
-      if (identical(newType, type)) return p;
-      return new ParameterElementImpl.synthetic(
-          p.name,
-          newType,
-          // ignore: deprecated_member_use_from_same_package
-          p.parameterKind);
-    }
-
-    var newReturnType = transformType(returnType);
-    var newParameters = _transformOrShare(parameters, transformParameter);
-    if (identical(returnType, newReturnType) &&
-        identical(typeFormals, newTypeFormals) &&
-        identical(parameters, newParameters)) {
-      return this;
-    }
-
-    var typeArguments = this.typeArguments.map(transformType).toList();
-
-    return new _FunctionTypeImplStrict._(
-        newReturnType, newTypeFormals, newParameters,
-        element: element,
-        typeArguments: typeArguments,
-        nullabilitySuffix: nullabilitySuffix);
+    var substitution = Substitution.fromPairs(
+      parameterTypes.map<TypeParameterElement>((t) => t.element).toList(),
+      argumentTypes,
+    );
+    return substitution.substituteType(this);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index bc9e976..9a60696 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 
@@ -448,7 +449,7 @@
   }
 
   @override
-  DartType visitNamedType(NamedTypeBuilder type) {
+  DartType visitNamedTypeBuilder(NamedTypeBuilder type) {
     if (type.arguments.isEmpty) {
       return type;
     }
@@ -472,6 +473,9 @@
   }
 
   @override
+  DartType visitUnknownInferredType(UnknownInferredType type) => type;
+
+  @override
   DartType visitVoidType(VoidType type) => type;
 
   static ParameterElementImpl _parameterElement(
diff --git a/pkg/analyzer/lib/src/dart/element/type_visitor.dart b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
index 08b8de6..fe8a706 100644
--- a/pkg/analyzer/lib/src/dart/element/type_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 
@@ -22,10 +23,12 @@
 
   R visitInterfaceType(InterfaceType type) => defaultDartType(type);
 
-  R visitNamedType(NamedTypeBuilder type) => defaultDartType(type);
+  R visitNamedTypeBuilder(NamedTypeBuilder type) => defaultDartType(type);
 
   R visitTypeParameterType(TypeParameterType type) => defaultDartType(type);
 
+  R visitUnknownInferredType(UnknownInferredType type) => defaultDartType(type);
+
   R visitVoidType(VoidType type) => defaultDartType(type);
 
   static R visit<R>(DartType type, DartTypeVisitor<R> visitor) {
@@ -45,11 +48,14 @@
       return visitor.visitInterfaceType(type);
     }
     if (type is NamedTypeBuilder) {
-      return visitor.visitNamedType(type);
+      return visitor.visitNamedTypeBuilder(type);
     }
     if (type is TypeParameterType) {
       return visitor.visitTypeParameterType(type);
     }
+    if (type is UnknownInferredType) {
+      return visitor.visitUnknownInferredType(type);
+    }
     if (type is VoidType) {
       return visitor.visitVoidType(type);
     }
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index dbcc657..89c7e91 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -650,6 +650,9 @@
           correction:
               "Try moving all but one of the declarations inside the loop body.");
 
+  static const ParserErrorCode MULTIPLE_VARIANCE_MODIFIERS =
+      _MULTIPLE_VARIANCE_MODIFIERS;
+
   static const ParserErrorCode MULTIPLE_WITH_CLAUSES = _MULTIPLE_WITH_CLAUSES;
 
   static const ParserErrorCode NAMED_FUNCTION_EXPRESSION = const ParserErrorCode(
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 9653453..8a12c18 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -104,6 +104,7 @@
   _EXTENSION_DECLARES_ABSTRACT_MEMBER,
   _MIXIN_DECLARES_CONSTRUCTOR,
   _NULL_AWARE_CASCADE_OUT_OF_ORDER,
+  _MULTIPLE_VARIANCE_MODIFIERS,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -471,6 +472,11 @@
     r"Only one part-of directive may be declared in a file.",
     correction: "Try removing all but one of the part-of directives.");
 
+const ParserErrorCode _MULTIPLE_VARIANCE_MODIFIERS = const ParserErrorCode(
+    'MULTIPLE_VARIANCE_MODIFIERS',
+    r"Each type parameter can have at most one variance modifier.",
+    correction: "Use at most one of the 'in', 'out', or 'inout' modifiers.");
+
 const ParserErrorCode _MULTIPLE_WITH_CLAUSES = const ParserErrorCode(
     'MULTIPLE_WITH_CLAUSES',
     r"Each class definition can have at most one with clause.",
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 2e6c7f7..a41d8f6 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -69,34 +69,38 @@
     return ResolutionResult.ambiguous;
   }
 
-  /// Return the member with the [name] (without `=`).
+  /// Resolve the [name] (without `=`) to the corresponding getter and setter
+  /// members of the extension [node].
   ///
   /// The [node] is fully resolved, and its type arguments are set.
-  ExecutableElement getOverrideMember(
-    ExtensionOverride node,
-    String name, {
-    bool setter = false,
-  }) {
+  ResolutionResult getOverrideMember(ExtensionOverride node, String name) {
     ExtensionElement element = node.extensionName.staticElement;
 
-    ExecutableElement member;
-    if (setter) {
-      member = element.getSetter(name);
+    ExecutableElement getter;
+    ExecutableElement setter;
+    if (name == '[]') {
+      getter = element.getMethod('[]');
+      setter = element.getMethod('[]=');
     } else {
-      member = element.getGetter(name) ?? element.getMethod(name);
+      getter = element.getGetter(name) ?? element.getMethod(name);
+      setter = element.getSetter(name);
     }
 
-    if (member == null) {
-      return null;
+    if (getter == null && setter == null) {
+      return ResolutionResult.none;
     }
 
-    return ExecutableMember.from2(
-      member,
-      Substitution.fromPairs(
-        element.typeParameters,
-        node.typeArgumentTypes,
-      ),
+    var substitution = Substitution.fromPairs(
+      element.typeParameters,
+      node.typeArgumentTypes,
     );
+
+    var getterMember =
+        getter != null ? ExecutableMember.from2(getter, substitution) : null;
+    var setterMember =
+        setter != null ? ExecutableMember.from2(setter, substitution) : null;
+
+    return ResolutionResult(getter: getterMember, setter: setterMember);
   }
 
   /// Perform upward inference for the override.
@@ -291,17 +295,38 @@
       for (var field in extension.fields) {
         if (field.name == name) {
           candidates.add(
-            _CandidateExtension(extension, field: field),
+            _CandidateExtension(
+              extension,
+              getter: field.getter,
+              setter: field.setter,
+            ),
           );
           return;
         }
       }
-      for (var method in extension.methods) {
-        if (method.name == name) {
+      if (name == '[]') {
+        ExecutableElement getter;
+        ExecutableElement setter;
+        for (var method in extension.methods) {
+          if (method.name == '[]') {
+            getter = method;
+          } else if (method.name == '[]=') {
+            setter = method;
+          }
+        }
+        if (getter != null || setter != null) {
           candidates.add(
-            _CandidateExtension(extension, method: method),
+            _CandidateExtension(extension, getter: getter, setter: setter),
           );
-          return;
+        }
+      } else {
+        for (var method in extension.methods) {
+          if (method.name == name) {
+            candidates.add(
+              _CandidateExtension(extension, getter: method),
+            );
+            return;
+          }
         }
       }
     }
@@ -429,11 +454,11 @@
 
 class _CandidateExtension {
   final ExtensionElement extension;
-  final FieldElement field;
-  final MethodElement method;
+  final ExecutableElement getter;
+  final ExecutableElement setter;
 
-  _CandidateExtension(this.extension, {this.field, this.method})
-      : assert(field != null || method != null);
+  _CandidateExtension(this.extension, {this.getter, this.setter})
+      : assert(getter != null || setter != null);
 }
 
 class _InstantiatedExtension {
@@ -444,22 +469,22 @@
   _InstantiatedExtension(this.candidate, this.substitution, this.extendedType);
 
   ResolutionResult get asResolutionResult {
-    return ResolutionResult(function: method, property: field);
+    return ResolutionResult(getter: getter, setter: setter);
   }
 
   ExtensionElement get extension => candidate.extension;
 
-  FieldElement get field {
-    if (candidate.field == null) {
+  ExecutableElement get getter {
+    if (candidate.getter == null) {
       return null;
     }
-    return FieldMember.from2(candidate.field, substitution);
+    return ExecutableMember.from2(candidate.getter, substitution);
   }
 
-  MethodElement get method {
-    if (candidate.method == null) {
+  ExecutableElement get setter {
+    if (candidate.setter == null) {
       return null;
     }
-    return MethodMember.from2(candidate.method, substitution);
+    return ExecutableMember.from2(candidate.setter, substitution);
   }
 }
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 9244efd..4ac8a57 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -390,7 +390,8 @@
 
   void _resolveExtensionOverride(MethodInvocation node,
       ExtensionOverride override, SimpleIdentifier nameNode, String name) {
-    var member = _extensionResolver.getOverrideMember(override, name);
+    var result = _extensionResolver.getOverrideMember(override, name);
+    var member = result.getter;
 
     if (member == null) {
       _setDynamicResolution(node);
@@ -747,7 +748,7 @@
         var result = _extensionResolver.findExtension(
             type, _nameCall.name, node.methodName);
         if (result.isSingle) {
-          call = result.function;
+          call = result.getter;
         } else if (result.isAmbiguous) {
           return;
         }
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
index d3b7288..f87810c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/element/element.dart';
 
-/// The result of attempting to resolve an identifier to a element.
+/// The result of attempting to resolve an identifier to elements.
 class ResolutionResult {
   /// An instance that can be used anywhere that no element was found.
   static const ResolutionResult none =
@@ -17,27 +17,22 @@
   /// The state of the result.
   final _ResolutionResultState state;
 
-  /// The function that was found, or `null` if the [state] is not
-  /// [_ResolutionResultState.single], or a [property] was found.
-  final ExecutableElement function;
+  /// Return the element that is invoked for reading.
+  final ExecutableElement getter;
 
-  /// The property that was found, or `null` if the [state] is not
-  /// [_ResolutionResultState.single], or a [function] was found.
-  final PropertyInducingElement property;
+  /// Return the element that is invoked for writing.
+  final ExecutableElement setter;
 
-  /// Initialize a newly created result to represent resolving to a single
-  /// [function] or [property].
-  ResolutionResult({this.function, this.property})
-      : assert(function != null || property != null),
+  /// Initialize a newly created result to represent resolving a single
+  /// reading and / or writing result.
+  ResolutionResult({this.getter, this.setter})
+      : assert(getter != null || setter != null),
         state = _ResolutionResultState.single;
 
-  /// Initialize a newly created result with no element and the given [state].
+  /// Initialize a newly created result with no elements and the given [state].
   const ResolutionResult._(this.state)
-      : function = null,
-        property = null;
-
-  /// Return the getter of the [property], or the [function].
-  ExecutableElement get getter => function ?? property?.getter;
+      : getter = null,
+        setter = null;
 
   /// Return `true` if this result represents the case where multiple ambiguous
   /// elements were found.
@@ -55,12 +50,8 @@
   /// If this is a function, return `true` is the function is static.
   /// Otherwise return `false`.
   bool get isStatic {
-    return function?.isStatic ?? property?.isStatic ?? false;
+    return getter?.isStatic ?? setter?.isStatic ?? false;
   }
-
-  /// Return the setter of the [property], or `null` if this is not a property,
-  /// or the property does not have a setter.
-  ExecutableElement get setter => property?.setter;
 }
 
 /// The state of a [ResolutionResult].
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 3f75ebc..6bf0d08 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -621,8 +621,7 @@
     for (File librariesFile in _libraryMapLocations) {
       try {
         String contents = librariesFile.readAsStringSync();
-        return new SdkLibrariesReader(useDart2jsPaths)
-            .readFromFile(librariesFile, contents);
+        return new SdkLibrariesReader().readFromFile(librariesFile, contents);
       } catch (exception, stackTrace) {
         searchedPaths.add(librariesFile.path);
         lastException = exception;
@@ -873,17 +872,7 @@
  *     };
  */
 class SdkLibrariesReader {
-  /**
-   * A flag indicating whether the dart2js path should be used when it is
-   * available.
-   */
-  final bool _useDart2jsPaths;
-
-  /**
-   * Initialize a newly created library reader to use the dart2js path if
-   * [_useDart2jsPaths] is `true`.
-   */
-  SdkLibrariesReader(this._useDart2jsPaths);
+  SdkLibrariesReader([@deprecated bool useDart2jsPaths]);
 
   /**
    * Return the library map read from the given [file], given that the content
@@ -907,7 +896,7 @@
     Parser parser = new Parser(source, errorListener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
     SdkLibrariesReader_LibraryBuilder libraryBuilder =
-        new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);
+        new SdkLibrariesReader_LibraryBuilder(true);
     // If any syntactic errors were found then don't try to visit the AST
     // structure.
     if (!errorListener.errorReported) {
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 11e27cf..d7f00f5 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -106,14 +106,35 @@
  */
 class CompileTimeErrorCode extends AnalyzerErrorCode {
   /**
-   * Member lookups ignore abstract declarations, which means that there will
-   * be a compile-time error if the targeted member `m` is abstract, as well as
-   * when it does not exist at all.
-   *
    * Parameters:
    * 0: the display name for the kind of the found abstract member
    * 1: the name of the member
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an inherited member is
+  // referenced using `super`, but there is no concrete implementation of the
+  // member in the superclass chain. Abstract members can't be invoked.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // abstract class A {
+  //   int get a;
+  // }
+  // class B extends A {
+  //   int get a => super.[!a!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the invocation of the abstract member, possibly replacing it with an
+  // invocation of a concrete member.
+  // TODO(brianwilkerson) This either needs to be generalized (use 'member'
+  //  rather than '{0}') or split into multiple codes.
   static const CompileTimeErrorCode ABSTRACT_SUPER_MEMBER_REFERENCE =
       const CompileTimeErrorCode('ABSTRACT_SUPER_MEMBER_REFERENCE',
           "The {0} '{1}' is always abstract in the supertype.");
@@ -410,12 +431,25 @@
               "Try marking the function body with either 'async' or 'async*'.");
 
   /**
-   * It is a compile-time error if a built-in identifier is used as the declared
-   * name of an extension.
-   *
    * Parameters:
    * 0: the built-in identifier that is being used
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name of an extension is a
+  // built-in identifier. Built-in identifiers can’t be used as extension names.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension [!mixin!] on int {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Choose a different name for the extension.
   static const CompileTimeErrorCode BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME =
       const CompileTimeErrorCode('BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME',
           "The built-in identifier '{0}' can't be used as an extension name.",
@@ -917,10 +951,62 @@
           correction: "Try using a different value for the element, or "
               "removing the keyword 'const' from the set.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the expression of a spread
+  // operator in a constant list or set evaluates to something other than a list
+  // or a set.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // const List<int> list1 = null;
+  // const List<int> list2 = [...[!list1!]];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Change the expression to something that evaluates to either a constant list
+  // or a constant set:
+  //
+  // ```dart
+  // const List<int> list1 = [];
+  // const List<int> list2 = [...list1];
+  // ```
   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.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the expression of a spread
+  // operator in a constant map evaluates to something other than a map.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // const Map<String, int> map1 = null;
+  // const Map<String, int> map2 = {...[!map1!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Change the expression to something that evaluates to a constant map:
+  //
+  // ```dart
+  // const Map<String, int> map1 = {};
+  // const Map<String, int> map2 = {...map1};
+  // ```
   static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
       const CompileTimeErrorCode(
           'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
@@ -960,10 +1046,37 @@
           correction: "Try using 'new' to call the constructor.");
 
   /**
-   * 16.12.2 Const: In all of the above cases, it is a compile-time error if
-   * <i>a<sub>i</sub>, 1 &lt;= i &lt;= n + k</i>, is not a compile-time constant
-   * expression.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a const constructor is invoked
+  // with an argument that isn't a constant expression.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // class C {
+  //   final int i;
+  //   const C(this.i);
+  // }
+  // C f(int i) => const C([!i!]);
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Either make all of the arguments constant expressions, or remove the
+  // `const` keyword to use the non-constant form of the constructor:
+  //
+  // ```dart
+  // class C {
+  //   final int i;
+  //   const C(this.i);
+  // }
+  // C f(int i) => C(i);
+  // ```
   static const CompileTimeErrorCode CONST_WITH_NON_CONSTANT_ARGUMENT =
       const CompileTimeErrorCode('CONST_WITH_NON_CONSTANT_ARGUMENT',
           "Arguments of a constant creation must be constant expressions.",
@@ -1126,18 +1239,31 @@
           correction: "Try renaming one of the constructors.");
 
   /**
-   * 3.1 Scoping: It is a compile-time error if there is more than one entity
-   * with the same name declared in the same scope.
-   *
-   * 7 Classes: It is a compile-time error if a class declares two members of
-   * the same name.
-   *
-   * 7 Classes: It is a compile-time error if a class has an instance member and
-   * a static member with the same name.
-   *
    * Parameters:
    * 0: the name of the duplicate entity
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name is declared, and there is
+  // a previous declaration with the same name in the same scope.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // int x = 0;
+  // int [!x!] = 1;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Choose a different name for one of the declarations.
+  //
+  // ```dart
+  // int x = 0;
+  // int y = 1;
+  // ```
   static const CompileTimeErrorCode DUPLICATE_DEFINITION =
       const CompileTimeErrorCode(
           'DUPLICATE_DEFINITION', "The name '{0}' is already defined.",
@@ -1172,9 +1298,33 @@
               "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).
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when two elements in a constant set
+  // literal have the same value. The set can only contain each value once,
+  // which means that one of the values is unnecessary.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // const Set<String> set = {'a', [!'a'!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove one of the duplicate values:
+  //
+  // ```dart
+  // const Set<String> set = {'a'};
+  // ```
+  //
+  // Note that literal sets preserve the order of their elements, so the choice
+  // of which element to remove might affect the order in which elements are
+  // returned by an iterator.
   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.");
@@ -1199,17 +1349,23 @@
   //
   // #### Common fixes
   //
-  // If one of the keys was supposed to be different, then replace it:
+  // If both entries should be included in the map, then change one of the keys
+  // to be different:
   //
   // ```dart
   // const map = <int, String>{1: 'a', 2: 'b', 3: 'c', 4: 'd'};
   // ```
   //
-  // Otherwise, remove the key/value pair that isn't intended to be in the map:
+  // If only one of the entries is needed, then remove the one that isn't
+  // needed:
   //
   // ```dart
   // const map = <int, String>{1: 'a', 2: 'b', 4: 'd'};
   // ```
+  //
+  // Note that literal maps preserve the order of their entries, so the choice
+  // of which entry to remove might affect the order in which keys and values
+  // are returned by an iterator.
   static const CompileTimeErrorCode EQUAL_KEYS_IN_CONST_MAP =
       const CompileTimeErrorCode('EQUAL_KEYS_IN_CONST_MAP',
           "Two keys in a constant map literal can't be equal.",
@@ -1339,6 +1495,36 @@
    * Parameters:
    * 0: the name of the extension
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name of an extension is used
+  // in an expression other than in an extension override or to qualify an
+  // access to a static member of the extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on int {
+  //   static String m() => '';
+  // }
+  //
+  // var x = [!E!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Replace the name of the extension with a name that can be referenced, such
+  // as a static member defined on the extension:
+  //
+  // ```dart
+  // extension E on int {
+  //   static String m() => '';
+  // }
+  //
+  // var x = E.m();
+  // ```
   static const CompileTimeErrorCode EXTENSION_AS_EXPRESSION =
       const CompileTimeErrorCode('EXTENSION_AS_EXPRESSION',
           "Extension '{0}' can't be used as an expression.",
@@ -1518,6 +1704,39 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is used as
+  // the target of a cascade expression.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on int {
+  //   void m() {}
+  // }
+  // f() {
+  //   E(3)[!..!]m();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Use '.' rather than '..':
+  //
+  // ```dart
+  // extension E on int {
+  //   void m() {}
+  // }
+  // f() {
+  //   E(3).m();
+  // }
+  // ```
+  //
+  // If there are multiple cascaded accesses, you'll need to duplicate the
+  // extension override for each one.
   static const CompileTimeErrorCode EXTENSION_OVERRIDE_WITH_CASCADE =
       const CompileTimeErrorCode(
           'EXTENSION_OVERRIDE_WITH_CASCADE',
@@ -1581,32 +1800,84 @@
           correction: 'Consider adding an access to an instance member.');
 
   /**
-   * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m &lt;
-   * h</i> or if <i>m &gt; n</i>.
-   *
-   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
-   * object results in an uncaught exception being thrown.
-   *
    * Parameters:
    * 0: the maximum number of positional arguments
    * 1: the actual number of positional arguments given
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a method or function invocation
+  // has more positional arguments than the method or function allows.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(int a, int b) {}
+  // void g() {
+  //   f[!(1, 2, 3)!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the arguments that don't correspond to parameters:
+  //
+  // ```dart
+  // void f(int a, int b) {}
+  // void g() {
+  //   f(1, 2);
+  // }
+  // ```
   static const CompileTimeErrorCode EXTRA_POSITIONAL_ARGUMENTS =
       const CompileTimeErrorCode('EXTRA_POSITIONAL_ARGUMENTS',
           "Too many positional arguments: {0} expected, but {1} found.",
           correction: "Try removing the extra arguments.");
 
   /**
-   * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m &lt;
-   * h</i> or if <i>m &gt; n</i>.
-   *
-   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
-   * object results in an uncaught exception being thrown.
-   *
    * Parameters:
    * 0: the maximum number of positional arguments
    * 1: the actual number of positional arguments given
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a method or function invocation
+  // has more positional arguments than the method or function allows, but the
+  // method or function defines named parameters.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(int a, int b, {int c}) {}
+  // void g() {
+  //   f[!(1, 2, 3)!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If some of the arguments should be values for named parameters, then add
+  // the names before the arguments:
+  //
+  // ```dart
+  // void f(int a, int b, {int c}) {}
+  // void g() {
+  //   f(1, 2, c: 3);
+  // }
+  // ```
+  //
+  // Otherwise, remove the arguments that don't correspond to positional
+  // parameters:
+  //
+  // ```dart
+  // void f(int a, int b, {int c}) {}
+  // void g() {
+  //   f(1, 2);
+  // }
+  // ```
   static const CompileTimeErrorCode EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED =
       const CompileTimeErrorCode('EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED',
           "Too many positional arguments: {0} expected, but {1} found.",
@@ -1785,13 +2056,37 @@
               "remove the class from the list.");
 
   /**
-   * 7.10 Superinterfaces: It is a compile-time error if the implements 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 interface that was not found
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name used in the implements
+  // clause of a class or mixin declaration is defined to be something other
+  // than a class or mixin.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // var x;
+  // class C implements [!x!] {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name is the name of an existing class or mixin that's already being
+  // imported, then add a prefix to the import so that the local definition of
+  // the name doesn't shadow the imported name.
+  //
+  // If the name is the name of an existing class or mixin that isn't being
+  // imported, then add an import, with a prefix, for the library in which it’s
+  // declared.
+  //
+  // Otherwise, either replace the name in the implements clause with the name
+  // of an existing class or mixin, or remove the name from the implements
+  // clause.
   static const CompileTimeErrorCode IMPLEMENTS_NON_CLASS =
       const CompileTimeErrorCode('IMPLEMENTS_NON_CLASS',
           "Classes and mixins can only implement other classes and mixins.",
@@ -2334,6 +2629,16 @@
       const CompileTimeErrorCode('INVALID_URI', "Invalid URI syntax: '{0}'.");
 
   /**
+   * Parameters:
+   * 0: the name of the extension
+   */
+  static const CompileTimeErrorCode INVOCATION_OF_EXTENSION_WITHOUT_CALL =
+      const CompileTimeErrorCode(
+          'INVOCATION_OF_EXTENSION_WITHOUT_CALL',
+          "The extension '{0}' does not define a 'call' method so the override "
+              "can't be used in an invocation.");
+
+  /**
    * 13.13 Break: It is a compile-time error if no such statement
    * <i>s<sub>E</sub></i> exists within the innermost function in which
    * <i>s<sub>b</sub></i> occurs.
@@ -2367,6 +2672,42 @@
           correction: "Try defining the label, or "
               "correcting the name to match an existing label.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a map entry (a key/value pair)
+  // is found in a set literal.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // const collection = <String>{[!'a' : 'b'!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you intended for the collection to be a map, then change the code so
+  // that it is a map. In the previous example, you could do this by adding
+  // another type argument:
+  //
+  // ```dart
+  // const collection = <String, String>{'a' : 'b'};
+  // ```
+  //
+  // In other cases, you might need to change the explicit type from `Set` to
+  // `Map`.
+  //
+  // If you intended for the collection to be a set, then remove the map entry,
+  // possibly by replacing the colon with a comma if both values should be
+  // included in the set:
+  //
+  // ```dart
+  // const collection = <String>{'a', 'b'};
+  // ```
   static const CompileTimeErrorCode MAP_ENTRY_NOT_IN_MAP =
       const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
           "Map entries can only be used in a map literal.",
@@ -2772,16 +3113,39 @@
               "used as an expression statement.");
 
   /**
-   * 13.9 Switch: Given a switch statement of the form <i>switch (e) {
-   * label<sub>11</sub> &hellip; label<sub>1j1</sub> case e<sub>1</sub>:
-   * s<sub>1</sub> &hellip; label<sub>n1</sub> &hellip; label<sub>njn</sub> case
-   * e<sub>n</sub>: s<sub>n</sub> default: s<sub>n+1</sub>}</i> or the form
-   * <i>switch (e) { label<sub>11</sub> &hellip; label<sub>1j1</sub> case
-   * e<sub>1</sub>: s<sub>1</sub> &hellip; label<sub>n1</sub> &hellip;
-   * label<sub>njn</sub> case e<sub>n</sub>: s<sub>n</sub>}</i>, it is a
-   * compile-time error if the expressions <i>e<sub>k</sub></i> are not
-   * compile-time constants, for all <i>1 &lt;= k &lt;= n</i>.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the expression in a case clause
+  // isn't a constant expression.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(int i, int j) {
+  //   switch (i) {
+  //     case [!j!]:
+  //       // ...
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Either make the expression a constant expression, or rewrite the switch
+  // statement as a sequence of if statements:
+  //
+  // ```dart
+  // void f(int i, int j) {
+  //   if (i == j) {
+  //     // ...
+  //   }
+  // }
+  // ```
   static const CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION =
       const CompileTimeErrorCode(
           'NON_CONSTANT_CASE_EXPRESSION', "Case expressions must be constant.");
@@ -2898,9 +3262,38 @@
               "Try removing the keyword 'const' from the list literal.");
 
   /**
-   * 12.7 Maps: It is a compile time error if either a key or a value of an
-   * entry in a constant map literal is not a compile-time constant.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a key in a constant map literal
+  // isn't a constant value.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // var a = 'a';
+  // var m = const {[!a!]: 0};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the map needs to be a constant map, then make the key a constant:
+  //
+  // ```dart
+  // const a = 'a';
+  // var m = const {a: 0};
+  // ```
+  //
+  // If the map doesn't need to be a constant map, then remove the `const`
+  // keyword:
+  //
+  // ```dart
+  // var a = 'a';
+  // var m = {a: 0};
+  // ```
   static const CompileTimeErrorCode NON_CONSTANT_MAP_KEY =
       const CompileTimeErrorCode('NON_CONSTANT_MAP_KEY',
           "The keys in a const map literal must be constant.",
@@ -2921,18 +3314,87 @@
           correction: "Try removing the keyword 'const' from the map literal.");
 
   /**
-   * 12.7 Maps: It is a compile time error if either a key or a value of an
-   * entry in a constant map literal is not a compile-time constant.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a value in a constant map
+  // literal isn't a constant value.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // var a = 'a';
+  // var m = const {0: [!a!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the map needs to be a constant map, then make the key a constant:
+  //
+  // ```dart
+  // const a = 'a';
+  // var m = const {0: a};
+  // ```
+  //
+  // If the map doesn't need to be a constant map, then remove the `const`
+  // keyword:
+  //
+  // ```dart
+  // var a = 'a';
+  // var m = {0: a};
+  // ```
   static const CompileTimeErrorCode NON_CONSTANT_MAP_VALUE =
       const CompileTimeErrorCode('NON_CONSTANT_MAP_VALUE',
           "The values in a const map literal must be constant.",
           correction: "Try removing the keyword 'const' from the map literal.");
 
   /**
-   * 12.7 Maps: It is a compile time error if an element of a constant map
-   * literal is not a compile-time constant.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an if element or a spread
+  // element in a constant map isn't a constant element.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because it is attempting to
+  // spread a non-constant map:
+  //
+  // ```dart
+  // var notConst = <int, int>{};
+  // var map = const <int, int>{...[!notConst!]};
+  // ```
+  //
+  // Similarly, the following code produces this diagnostic because the
+  // condition in the if element isn't a constant expression:
+  //
+  // ```dart
+  // bool notConst = true;
+  // var map = const <int, int>{if ([!notConst!]) 1 : 2};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the map needs to be a constant map, then make the elements  constants.
+  // In the spread example, you might do that by making the collection being
+  // spread a constant:
+  //
+  // ```dart
+  // const notConst = <int, int>{};
+  // var map = const <int, int>{...notConst};
+  // ```
+  //
+  // If the map doesn't need to be a constant map, then remove the `const`
+  // keyword:
+  //
+  // ```dart
+  // bool notConst = true;
+  // var map = <int, int>{if (notConst) 1 : 2};
+  // ```
   static const CompileTimeErrorCode NON_CONSTANT_MAP_ELEMENT =
       const CompileTimeErrorCode('NON_CONSTANT_MAP_ELEMENT',
           "The elements in a const map literal must be constant.",
@@ -3022,6 +3484,33 @@
    * 0: the expected number of required arguments
    * 1: the actual number of positional arguments given
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a method or function invocation
+  // has fewer positional arguments than the number of required positional
+  // parameters.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(int a, int b) {}
+  // void g() {
+  //   f[!(0)!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add arguments corresponding to the remaining parameters:
+  //
+  // ```dart
+  // void f(int a, int b) {}
+  // void g() {
+  //   f(0, 1);
+  // }
+  // ```
   static const CompileTimeErrorCode NOT_ENOUGH_POSITIONAL_ARGUMENTS =
       const CompileTimeErrorCode('NOT_ENOUGH_POSITIONAL_ARGUMENTS',
           "{0} positional argument(s) expected, but {1} found.",
@@ -3112,6 +3601,33 @@
           "Spread elements in list or set literals must implement 'Iterable'.",
           hasPublishedDocs: true);
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the static type of the
+  // expression of a spread element that appears in a map literal doesn't
+  // implement the type `Map`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // var l =  <String>['a', 'b'];
+  // var m = <int, String>{...[!l!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // The most common fix is to replace the expression with one that produces a
+  // map:
+  //
+  // ```dart
+  // var l =  <String>['a', 'b'];
+  // var m = <int, String>{...l.asMap()};
+  // ```
   static const CompileTimeErrorCode NOT_MAP_SPREAD = const CompileTimeErrorCode(
       'NOT_MAP_SPREAD',
       "Spread elements in map literals must implement 'Map'.");
@@ -3484,10 +4000,52 @@
           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.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a variable is referenced before
+  // it’s declared. In Dart, variables are visible everywhere in the block in
+  // which they are declared, but can only be referenced after they are
+  // declared.
+  //
+  // The analyzer also produces a context message that indicates where the
+  // declaration is located.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f() {
+  //   print([!i!]);
+  //   int i = 5;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you intended to reference the local variable, move the declaration
+  // before the first reference:
+  //
+  // ```dart
+  // void f() {
+  //   int i = 5;
+  //   print(i);
+  // }
+  // ```
+  //
+  // If you intended to reference a name from an outer scope, such as a
+  // parameter, instance field or top-level variable, then rename the local
+  // declaration so that it doesn't hide the outer variable.
+  //
+  // ```dart
+  // void f(int i) {
+  //   print(i);
+  //   int x = 5;
+  //   print(x);
+  // }
+  // ```
   static const CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION =
       const CompileTimeErrorCode('REFERENCED_BEFORE_DECLARATION',
           "Local variable '{0}' can't be referenced before it is declared.",
@@ -3670,11 +4228,42 @@
           correction: "Try removing the type parameters.");
 
   /**
-   * 15 Metadata: Metadata consists of a series of annotations, each of which
-   * begin with the character @, followed by a constant expression that must be
-   * either a reference to a compile-time constant variable, or a call to a
-   * constant constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name that isn't defined is
+  // used as an annotation.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // [!@undefined!]
+  // void f() {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name is correct, but it isn’t declared yet, then declare the name as
+  // a constant value:
+  //
+  // ```dart
+  // const undefined = 'undefined';
+  //
+  // @undefined
+  // void f() {}
+  // ```
+  //
+  // If the name is wrong, replace the name with the name of a valid constant:
+  //
+  // ```dart
+  // @deprecated
+  // void f() {}
+  // ```
+  //
+  // Otherwise, remove the annotation.
   static const CompileTimeErrorCode UNDEFINED_ANNOTATION =
       const CompileTimeErrorCode(
           'UNDEFINED_ANNOTATION', "Undefined name '{0}' used as an annotation.",
@@ -3960,6 +4549,16 @@
 
   /**
    * Parameters:
+   * 0: the name of the operator that is undefined
+   * 1: the name of the extension that was explicitly specified
+   */
+  static const CompileTimeErrorCode UNDEFINED_EXTENSION_OPERATOR =
+      const CompileTimeErrorCode('UNDEFINED_EXTENSION_OPERATOR',
+          "The operator '{0}' isn't defined for the extension '{1}'.",
+          correction: "Try defining the operator '{0}'.");
+
+  /**
+   * Parameters:
    * 0: the name of the setter that is undefined
    * 1: the name of the extension that was explicitly specified
    */
@@ -4139,12 +4738,67 @@
    * Parameters:
    * 0: the name of the defining type
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an undefined name is found, and
+  // the name is the same as a static member of the extended type or one of its
+  // superclasses.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // class C {
+  //   static void m() {}
+  // }
+  //
+  // extension E on C {
+  //   void f() {
+  //     [!m!]();
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you're trying to reference a static member that's declared outside the
+  // extension, then add the name of the class or extension before the reference
+  // to the member:
+  //
+  // ```dart
+  // class C {
+  //   static void m() {}
+  // }
+  //
+  // extension E on C {
+  //   void f() {
+  //     C.m();
+  //   }
+  // }
+  // ```
+  //
+  // If you're referencing a member that isn't declared yet, add a declaration:
+  //
+  // ```dart
+  // class C {
+  //   static void m() {}
+  // }
+  //
+  // extension E on C {
+  //   void f() {
+  //     m();
+  //   }
+  //
+  //   void m() {}
+  // }
+  // ```
   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.",
+          "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.");
 
   /**
@@ -4432,22 +5086,47 @@
           correction: "Try using the class '{2}' to access the {1}.");
 
   /**
-   * 12.18 Assignment: It is a static type warning if the static type of
-   * <i>e</i> may not be assigned to the static type of <i>v</i>. The static
-   * type of the expression <i>v = e</i> is the static type of <i>e</i>.
-   *
-   * 12.18 Assignment: It is a static type warning if the static type of
-   * <i>e</i> may not be assigned to the static type of <i>C.v</i>. The static
-   * type of the expression <i>C.v = e</i> is the static type of <i>e</i>.
-   *
-   * 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>.
-   * It is a static type warning if the static type of <i>e<sub>2</sub></i> may
-   * not be assigned to <i>T</i>.
-   *
    * Parameters:
    * 0: the name of the right hand side type
    * 1: the name of the left hand side type
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the static type of an expression
+  // that is assigned to a variable isn't assignable to the type of the
+  // variable.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type of the
+  // initializer (`int`) isn't assignable to the type of the variable
+  // (`String`):
+  //
+  // ```dart
+  // int i = 0;
+  // String s = [!i!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the value being assigned is always assignable at runtime, even though
+  // the static types don't reflect that, then add an explicit cast.
+  //
+  // Otherwise, change the value being assigned so that it has the expected
+  // type. In the previous example, this might look like:
+  //
+  // ```dart
+  // int i = 0;
+  // String s = i.toString();
+  // ```
+  //
+  // If you can’t change the value, then change the type of the variable to be
+  // compatible with the type of the value being assigned:
+  //
+  // ```dart
+  // int i = 0;
+  // int s = i;
+  // ```
   static const StaticTypeWarningCode INVALID_ASSIGNMENT =
       const StaticTypeWarningCode(
           'INVALID_ASSIGNMENT',
@@ -4800,6 +5479,34 @@
           "The operator '{0}' isn't defined for the class '{1}'.",
           correction: "Try defining the operator '{0}'.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a prefixed identifier is found
+  // where the prefix is valid, but the identifier isn't declared in any of the
+  // libraries imported using that prefix.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // import 'dart:core' as p;
+  //
+  // void f() {
+  //   p.[!a!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the library in which the name is declared isn't imported yet, add an
+  // import for the library.
+  //
+  // If the name is wrong, then change it to one of the names that's declared in
+  // the imported libraries.
   static const StaticTypeWarningCode UNDEFINED_PREFIXED_NAME =
       const StaticTypeWarningCode(
           'UNDEFINED_PREFIXED_NAME',
@@ -4871,16 +5578,38 @@
               "defining a getter or field named '{0}' in a superclass.");
 
   /**
-   * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
-   * <i>super.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>:
-   * a<sub>n+1</sub>, &hellip; x<sub>n+k</sub>: a<sub>n+k</sub>)</i>. It is a
-   * static type warning if <i>S</i> does not have an accessible instance member
-   * named <i>m</i>.
-   *
    * Parameters:
    * 0: the name of the method that is undefined
    * 1: the resolved type name that the method lookup is happening on
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an inherited method is
+  // referenced using `super`, but there’s no method with that name in the
+  // superclass chain.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // class C {
+  //   void m() {
+  //     super.[!n!]();
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the inherited method you intend to invoke has a different name, then
+  // make the name of the invoked method  match the inherited method.
+  //
+  // If the method you intend to invoke is defined in the same class, then
+  // remove the `super.`.
+  //
+  // If not, then either add the method to one of the superclasses or remove the
+  // invocation.
   static const StaticTypeWarningCode UNDEFINED_SUPER_METHOD =
       const StaticTypeWarningCode('UNDEFINED_SUPER_METHOD',
           "The method '{0}' isn't defined in a superclass of '{1}'.",
@@ -5243,9 +5972,30 @@
           correction: "Try adding one of the required statements.");
 
   /**
-   * 12.32 Type Cast: It is a static warning if <i>T</i> does not denote a type
-   * available in the current lexical scope.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name following the `as` in a
+  // cast expression is defined to be something other than a type.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // num x = 0;
+  // int y = x as [!x!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Replace the name with the name of a type:
+  //
+  // ```dart
+  // num x = 0;
+  // int y = x as int;
+  // ```
   static const StaticWarningCode CAST_TO_NON_TYPE = const StaticWarningCode(
       'CAST_TO_NON_TYPE',
       "The name '{0}' isn't a type, so it can't be used in an 'as' expression.",
@@ -5370,13 +6120,50 @@
               "changing the field's type.");
 
   /**
-   * 5 Variables: It is a static warning if a library, static or local variable
-   * <i>v</i> is final and <i>v</i> is not initialized at its point of
-   * declaration.
-   *
    * Parameters:
    * 0: the name of the uninitialized final variable
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a final field or variable isn't
+  // initialized.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // final [!x!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // For variables and static fields, you can add an initializer:
+  //
+  // ```dart
+  // final x = 0;
+  // ```
+  //
+  // For instance fields, you can add an initializer as shown in the previous
+  // example, or you can initialize the field in every constructor. You can
+  // initialize the field by using a field formal parameter:
+  //
+  // ```dart
+  // class C {
+  //   final int x;
+  //   C(this.x);
+  // }
+  // ```
+  //
+  // You can also initialize the field by using an initializer in the
+  // constructor:
+  //
+  // ```dart
+  // class C {
+  //   final int x;
+  //   C(int y) : x = y * 2;
+  // }
+  // ```
   static const StaticWarningCode FINAL_NOT_INITIALIZED =
       const StaticWarningCode('FINAL_NOT_INITIALIZED',
           "The final variable '{0}' must be initialized.",
@@ -6005,9 +6792,36 @@
           correction: "Try correcting the name to match an existing type.");
 
   /**
-   * 12.31 Type Test: It is a static warning if <i>T</i> does not denote a type
-   * available in the current lexical scope.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name following the `is` in a
+  // type test expression isn't defined.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(Object o) {
+  //   if (o is [!Srting!]) {
+  //     // ...
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Replace the name with the name of a type:
+  //
+  // ```dart
+  // void f(Object o) {
+  //   if (o is String) {
+  //     // ...
+  //   }
+  // }
+  // ```
   static const StaticWarningCode TYPE_TEST_WITH_UNDEFINED_NAME =
       const StaticWarningCode(
           'TYPE_TEST_WITH_UNDEFINED_NAME',
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 5d94e1b..078a9da 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -121,6 +121,9 @@
   /// `true` if triple-shift behavior is enabled
   final bool enableTripleShift;
 
+  /// `true` if variance behavior is enabled
+  final bool enableVariance;
+
   final FeatureSet _featureSet;
 
   AstBuilder(ErrorReporter errorReporter, this.fileUri, this.isFullAst,
@@ -133,6 +136,7 @@
         this.enableControlFlowCollections =
             _featureSet.isEnabled(Feature.control_flow_collections),
         this.enableTripleShift = _featureSet.isEnabled(Feature.triple_shift),
+        this.enableVariance = _featureSet.isEnabled(Feature.variance),
         uri = uri ?? fileUri;
 
   NodeList<ClassMember> get currentDeclarationMembers {
@@ -3338,6 +3342,14 @@
   }
 
   @override
+  void handleVarianceModifier(Token variance) {
+    debugEvent('VarianceModifier');
+    if (!enableVariance) {
+      reportVarianceModifierNotEnabled(variance);
+    }
+  }
+
+  @override
   void handleVoidKeyword(Token voidKeyword) {
     assert(optional('void', voidKeyword));
     debugEvent("VoidKeyword");
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 25b6dcc..b2d006f 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
 /// A visitor that resolves declarations in an AST structure to already built
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 6e95ad6..fd7e626 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -19,7 +19,9 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
@@ -173,9 +175,9 @@
         String methodName = operatorType.lexeme;
         // TODO(brianwilkerson) Change the [methodNameNode] from the left hand
         //  side to the operator.
-        var result = _newPropertyResolver().resolveOperator(
-            leftHandSide, staticType, methodName, leftHandSide);
-        node.staticElement = result.function;
+        var result = _newPropertyResolver()
+            .resolve(leftHandSide, staticType, methodName, leftHandSide);
+        node.staticElement = result.getter;
         if (_shouldReportInvalidMember(staticType, result)) {
           _recordUndefinedToken(
               staticType.element,
@@ -266,10 +268,9 @@
         }
         if (node.newKeyword == null) {
           if (element is ClassElement) {
-            var propertyResolver = _newPropertyResolver();
-            propertyResolver.resolve(prefix, element.type, name.name, name);
-            name.staticElement = propertyResolver.getterResult.getter ??
-                propertyResolver.setterResult.setter ??
+            name.staticElement = element.getMethod(name.name) ??
+                element.getGetter(name.name) ??
+                element.getSetter(name.name) ??
                 element.getNamedConstructor(name.name);
           } else {
             // TODO(brianwilkerson) Report this error.
@@ -396,14 +397,23 @@
     Expression function = node.function;
     DartType functionType;
     if (function is ExtensionOverride) {
-      var member = _extensionResolver.getOverrideMember(function, 'call');
-      if (member != null && member.isStatic) {
+      var result = _extensionResolver.getOverrideMember(function, 'call');
+      var member = result.getter;
+      if (member == null) {
         _resolver.errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
-            node.argumentList);
+            CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
+            function,
+            [function.extensionName.name]);
+        functionType = _resolver.typeProvider.dynamicType;
+      } else {
+        if (member.isStatic) {
+          _resolver.errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+              node.argumentList);
+        }
+        node.staticElement = member;
+        functionType = member.type;
       }
-      node.staticElement = member;
-      functionType = member.type;
     } else {
       functionType = function.staticType;
     }
@@ -466,47 +476,36 @@
   void visitIndexExpression(IndexExpression node) {
     Expression target = node.realTarget;
     DartType staticType = _getStaticType(target);
+
     String getterMethodName = TokenType.INDEX.lexeme;
     String setterMethodName = TokenType.INDEX_EQ.lexeme;
+
+    ResolutionResult result;
+    if (target is ExtensionOverride) {
+      result = _extensionResolver.getOverrideMember(target, getterMethodName);
+    } else {
+      result = _newPropertyResolver()
+          .resolve(target, staticType, getterMethodName, target);
+    }
+
     bool isInGetterContext = node.inGetterContext();
     bool isInSetterContext = node.inSetterContext();
     if (isInGetterContext && isInSetterContext) {
-      // lookup setter
-      ResolutionResult setterResult = _newPropertyResolver()
-          .resolveOperator(target, staticType, setterMethodName, target);
-      // set setter element
-      node.staticElement = setterResult.function;
-      // generate undefined method warning
-      _checkForUndefinedIndexOperator(
-          node, target, setterMethodName, setterResult, staticType);
-      // lookup getter method
-      ResolutionResult getterResult = _newPropertyResolver()
-          .resolveOperator(target, staticType, getterMethodName, target);
-      // set getter element
-      AuxiliaryElements auxiliaryElements =
-          new AuxiliaryElements(getterResult.function, null);
-      node.auxiliaryElements = auxiliaryElements;
-      // generate undefined method warning
-      _checkForUndefinedIndexOperator(
-          node, target, getterMethodName, getterResult, staticType);
+      node.staticElement = result.setter;
+      node.auxiliaryElements = AuxiliaryElements(result.getter, null);
     } else if (isInGetterContext) {
-      // lookup getter method
-      ResolutionResult methodResult = _newPropertyResolver()
-          .resolveOperator(target, staticType, getterMethodName, target);
-      // set getter element
-      node.staticElement = methodResult.function;
-      // generate undefined method warning
-      _checkForUndefinedIndexOperator(
-          node, target, getterMethodName, methodResult, staticType);
+      node.staticElement = result.getter;
     } else if (isInSetterContext) {
-      // lookup setter method
-      ResolutionResult methodResult = _newPropertyResolver()
-          .resolveOperator(target, staticType, setterMethodName, target);
-      // set setter element
-      node.staticElement = methodResult.function;
-      // generate undefined method warning
+      node.staticElement = result.setter;
+    }
+
+    if (isInGetterContext) {
       _checkForUndefinedIndexOperator(
-          node, target, setterMethodName, methodResult, staticType);
+          node, target, getterMethodName, result, result.getter, staticType);
+    }
+    if (isInSetterContext) {
+      _checkForUndefinedIndexOperator(
+          node, target, setterMethodName, result, result.setter, staticType);
     }
   }
 
@@ -558,8 +557,8 @@
     String methodName = _getPostfixOperator(node);
     DartType staticType = _getStaticType(operand);
     var result = _newPropertyResolver()
-        .resolveOperator(operand, staticType, methodName, operand);
-    node.staticElement = result.function;
+        .resolve(operand, staticType, methodName, operand);
+    node.staticElement = result.getter;
     if (_shouldReportInvalidMember(staticType, result)) {
       if (operand is SuperExpression) {
         _recordUndefinedToken(
@@ -665,8 +664,8 @@
       String methodName = _getPrefixOperator(node);
       DartType staticType = _getStaticType(operand, read: true);
       var result = _newPropertyResolver()
-          .resolveOperator(operand, staticType, methodName, operand);
-      node.staticElement = result.function;
+          .resolve(operand, staticType, methodName, operand);
+      node.staticElement = result.getter;
       if (_shouldReportInvalidMember(staticType, result)) {
         if (operand is SuperExpression) {
           _recordUndefinedToken(
@@ -702,12 +701,9 @@
       SimpleIdentifier propertyName = node.propertyName;
       String memberName = propertyName.name;
       ExecutableElement member;
+      var result = _extensionResolver.getOverrideMember(target, memberName);
       if (propertyName.inSetterContext()) {
-        member = _extensionResolver.getOverrideMember(
-          target,
-          memberName,
-          setter: true,
-        );
+        member = result.setter;
         if (member == null) {
           _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
@@ -715,8 +711,7 @@
               [memberName, element.name]);
         }
         if (propertyName.inGetterContext()) {
-          PropertyAccessorElement getter =
-              _extensionResolver.getOverrideMember(target, memberName);
+          PropertyAccessorElement getter = result.getter;
           if (getter == null) {
             _resolver.errorReporter.reportErrorForNode(
                 CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
@@ -726,7 +721,7 @@
           propertyName.auxiliaryElements = AuxiliaryElements(getter, null);
         }
       } else if (propertyName.inGetterContext()) {
-        member = _extensionResolver.getOverrideMember(target, memberName);
+        member = result.getter;
         if (member == null) {
           _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
@@ -867,7 +862,7 @@
       var propertyResolver = _newPropertyResolver();
       propertyResolver.resolve(null, enclosingType, node.name, node);
       node.auxiliaryElements = AuxiliaryElements(
-        propertyResolver.getterResult.getter,
+        propertyResolver.result.getter,
         null,
       );
     }
@@ -979,37 +974,57 @@
    * the target of the expression. The [methodName] is the name of the operator
    * associated with the context of using of the given index expression.
    */
-  bool _checkForUndefinedIndexOperator(
+  void _checkForUndefinedIndexOperator(
       IndexExpression expression,
       Expression target,
       String methodName,
       ResolutionResult result,
+      ExecutableElement element,
       DartType staticType) {
-    if (_shouldReportInvalidMember(staticType, result)) {
-      Token leftBracket = expression.leftBracket;
-      Token rightBracket = expression.rightBracket;
-      ErrorCode errorCode;
-      var errorArguments = [methodName, staticType.displayName];
-      if (target is SuperExpression) {
-        errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR;
-      } else if (staticType != null && staticType.isVoid) {
-        errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
-        errorArguments = [];
-      } else {
-        errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR;
-      }
-      if (leftBracket == null || rightBracket == null) {
-        _recordUndefinedNode(
-            staticType.element, errorCode, expression, errorArguments);
-      } else {
-        int offset = leftBracket.offset;
-        int length = rightBracket.offset - offset + 1;
-        _recordUndefinedOffset(
-            staticType.element, errorCode, offset, length, errorArguments);
-      }
-      return true;
+    if (result.isAmbiguous) {
+      return;
     }
-    return false;
+    if (element != null) {
+      return;
+    }
+    if (target is! ExtensionOverride) {
+      if (staticType == null || staticType.isDynamic) {
+        return;
+      }
+    }
+
+    var leftBracket = expression.leftBracket;
+    var rightBracket = expression.rightBracket;
+    var offset = leftBracket.offset;
+    var length = rightBracket.end - offset;
+    if (target is ExtensionOverride) {
+      _resolver.errorReporter.reportErrorForOffset(
+        CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
+        offset,
+        length,
+        [methodName, target.staticElement.name],
+      );
+    } else if (target is SuperExpression) {
+      _resolver.errorReporter.reportErrorForOffset(
+        StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
+        offset,
+        length,
+        [methodName, staticType.displayName],
+      );
+    } else if (staticType.isVoid) {
+      _resolver.errorReporter.reportErrorForOffset(
+        StaticWarningCode.USE_OF_VOID_RESULT,
+        offset,
+        length,
+      );
+    } else {
+      _resolver.errorReporter.reportErrorForOffset(
+        StaticTypeWarningCode.UNDEFINED_OPERATOR,
+        offset,
+        length,
+        [methodName, staticType.displayName],
+      );
+    }
   }
 
   /**
@@ -1100,7 +1115,7 @@
       var propertyResolver = _newPropertyResolver();
       propertyResolver.resolve(null, invokeType,
           FunctionElement.CALL_METHOD_NAME, invocation.function);
-      MethodElement callMethod = propertyResolver.getterResult.function;
+      ExecutableElement callMethod = propertyResolver.result.getter;
       invocation.staticElement = callMethod;
       parameterizableType = callMethod?.type;
       parameters = (parameterizableType as FunctionType)?.typeFormals;
@@ -1227,20 +1242,6 @@
   }
 
   /**
-   * Record that the given [offset]/[length] is undefined, causing an error to
-   * be reported if appropriate. The [declaringElement] is the element inside
-   * which no declaration was found. If this element is a proxy, no error will
-   * be reported. If null, then an error will always be reported. The
-   * [errorCode] is the error code to report. The [arguments] are arguments to
-   * the error message.
-   */
-  void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode,
-      int offset, int length, List<Object> arguments) {
-    _resolver.errorReporter
-        .reportErrorForOffset(errorCode, offset, length, arguments);
-  }
-
-  /**
    * Record that the given [token] is undefined, causing an error to be reported
    * if appropriate. The [declaringElement] is the element inside which no
    * declaration was found. If this element is a proxy, no error will be
@@ -1253,6 +1254,44 @@
     _resolver.errorReporter.reportErrorForToken(errorCode, token, arguments);
   }
 
+  /// Resolve the [constructorName] to the constructor in the class [element].
+  /// Perform inference using [argumentList].
+  ConstructorElement _resolveAnnotationConstructor(
+    ClassElement element,
+    String constructorName,
+    ArgumentList argumentList,
+  ) {
+    var constructor = constructorName != null
+        ? element.getNamedConstructor(constructorName)
+        : element.unnamedConstructor;
+    if (constructor == null) {
+      return null;
+    }
+    if (!constructor.isAccessibleIn(_definingLibrary)) {
+      return null;
+    }
+
+    var typeParameters = element.typeParameters;
+    if (typeParameters.isEmpty) {
+      return constructor;
+    }
+
+    var typeArgs = _resolver.typeSystem.inferGenericFunctionOrType(
+      typeParameters: typeParameters,
+      parameters: constructor.parameters,
+      declaredReturnType: null,
+      argumentTypes: argumentList.arguments.map((a) => a.staticType).toList(),
+      contextReturnType: null,
+      isConst: true,
+      errorReporter: _resolver.errorReporter,
+      errorNode: argumentList,
+    );
+    return ExecutableMember.from2(
+      constructor,
+      Substitution.fromPairs(typeParameters, typeArgs),
+    );
+  }
+
   void _resolveAnnotationConstructorInvocationArguments(
       Annotation annotation, ConstructorElement constructor) {
     ArgumentList argumentList = annotation.arguments;
@@ -1299,7 +1338,11 @@
       }
       // Class(args)
       if (element1 is ClassElement) {
-        constructor = element1.type.lookUpConstructor(null, _definingLibrary);
+        constructor = _resolveAnnotationConstructor(
+          element1,
+          null,
+          annotation.arguments,
+        );
       } else if (element1 == null) {
         undefined = true;
       }
@@ -1327,8 +1370,11 @@
       }
       // Class.constructor(args)
       if (element1 is ClassElement) {
-        constructor =
-            element1.type.lookUpConstructor(nameNode2.name, _definingLibrary);
+        constructor = _resolveAnnotationConstructor(
+          element1,
+          nameNode2.name,
+          annotation.arguments,
+        );
         nameNode2.staticElement = constructor;
       }
       if (element1 == null && element2 == null) {
@@ -1353,7 +1399,11 @@
           return;
         }
         // prefix.Class.constructor(args)
-        constructor = element2.type.lookUpConstructor(name3, _definingLibrary);
+        constructor = _resolveAnnotationConstructor(
+          element2,
+          name3,
+          annotation.arguments,
+        );
         nameNode3.staticElement = constructor;
       } else if (element2 == null) {
         undefined = true;
@@ -1437,7 +1487,7 @@
         MethodElement member = element.getMethod(methodName);
         if (member == null) {
           _resolver.errorReporter.reportErrorForToken(
-              CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
+              CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
               node.operator,
               [methodName, element.name]);
         }
@@ -1446,10 +1496,10 @@
       }
       DartType leftType = _getStaticType(leftOperand);
       ResolutionResult result = _newPropertyResolver()
-          .resolveOperator(leftOperand, leftType, methodName, node);
+          .resolve(leftOperand, leftType, methodName, node);
 
-      node.staticElement = result.function;
-      node.staticInvokeType = result.function?.type;
+      node.staticElement = result.getter;
+      node.staticInvokeType = result.getter?.type;
       if (_shouldReportInvalidMember(leftType, result)) {
         if (leftOperand is SuperExpression) {
           _recordUndefinedToken(
@@ -1722,15 +1772,19 @@
       return;
     }
 
-    var propertyResolver = _newPropertyResolver();
-    propertyResolver.resolve(
-        target, staticType, propertyName.name, propertyName);
+    var result = _newPropertyResolver()
+        .resolve(target, staticType, propertyName.name, propertyName);
 
     if (propertyName.inGetterContext()) {
-      var getterResult = propertyResolver.getterResult;
-      if (getterResult.isSingle) {
-        propertyName.staticElement = getterResult.getter;
-      } else if (getterResult.isNone) {
+      var shouldReportUndefinedGetter = false;
+      if (result.isSingle) {
+        var getter = result.getter;
+        if (getter != null) {
+          propertyName.staticElement = getter;
+        } else {
+          shouldReportUndefinedGetter = true;
+        }
+      } else if (result.isNone) {
         if (staticType is FunctionType &&
             propertyName.name == FunctionElement.CALL_METHOD_NAME) {
           // Referencing `.call` on a `Function` type is OK.
@@ -1739,31 +1793,34 @@
             propertyName.name == FunctionElement.CALL_METHOD_NAME) {
           // Referencing `.call` on a `Function` type is OK.
         } else {
-          _resolver.errorReporter.reportErrorForNode(
-            StaticTypeWarningCode.UNDEFINED_GETTER,
-            propertyName,
-            [propertyName.name, staticType.displayName],
-          );
+          shouldReportUndefinedGetter = true;
         }
       }
+      if (shouldReportUndefinedGetter) {
+        _resolver.errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.UNDEFINED_GETTER,
+          propertyName,
+          [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) {
+      if (result.isSingle) {
+        var setter = result.setter;
+        if (setter != null) {
+          propertyName.staticElement = setter;
+        } else {
+          var getter = result.getter;
           propertyName.staticElement = getter;
           // A more specific error will be reported in ErrorVerifier.
-        } else {
-          _resolver.errorReporter.reportErrorForNode(
-            StaticTypeWarningCode.UNDEFINED_SETTER,
-            propertyName,
-            [propertyName.name, staticType.displayName],
-          );
         }
+      } else if (result.isNone) {
+        _resolver.errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.UNDEFINED_SETTER,
+          propertyName,
+          [propertyName.name, staticType.displayName],
+        );
       }
     }
   }
@@ -1790,7 +1847,7 @@
             var propertyResolver = _newPropertyResolver();
             propertyResolver.resolve(
                 null, enclosingClass.thisType, identifier.name, identifier);
-            setter = propertyResolver.setterResult.setter;
+            setter = propertyResolver.result.setter;
           }
         }
         if (setter != null) {
@@ -1830,9 +1887,9 @@
             null, enclosingType, identifier.name, identifier);
         if (identifier.inSetterContext() ||
             identifier.parent is CommentReference) {
-          element = propertyResolver.setterResult.setter;
+          element = propertyResolver.result.setter;
         }
-        element ??= propertyResolver.getterResult.getter;
+        element ??= propertyResolver.result.getter;
       }
     }
     return element;
@@ -1994,8 +2051,7 @@
   final LibraryElement _definingLibrary;
   final ExtensionMemberResolver _extensionResolver;
 
-  ResolutionResult getterResult = ResolutionResult.none;
-  ResolutionResult setterResult = ResolutionResult.none;
+  ResolutionResult result = ResolutionResult.none;
 
   _PropertyResolver(
     this._typeProvider,
@@ -2005,13 +2061,11 @@
   );
 
   /// Look up the getter and the setter with the given [name] in the [type].
-  /// Set results into [getterResult] or [setterResult] correspondingly.
-  /// Methods are considered getters for this purpose.
   ///
   /// The [target] is optional, and used to identify `super`.
   ///
   /// The [errorNode] is used to report the ambiguous extension issue.
-  void resolve(
+  ResolutionResult resolve(
     Expression target,
     DartType type,
     String name,
@@ -2019,21 +2073,28 @@
   ) {
     type = _resolveTypeParameter(type);
 
-    PropertyAccessorElement typeGetter;
-    PropertyAccessorElement typeSetter;
-    ExecutableElement typeMethod;
+    ExecutableElement typeGetter;
+    ExecutableElement typeSetter;
 
     void lookupIn(InterfaceType type) {
       var isSuper = target is SuperExpression;
 
-      typeGetter = type.lookUpInheritedGetter(name,
-          library: _definingLibrary, thisType: !isSuper);
+      if (name == '[]') {
+        typeGetter = type.lookUpInheritedMethod('[]',
+            library: _definingLibrary, thisType: !isSuper);
 
-      typeSetter = type.lookUpInheritedSetter(name,
-          library: _definingLibrary, thisType: !isSuper);
+        typeSetter = type.lookUpInheritedMethod('[]=',
+            library: _definingLibrary, thisType: !isSuper);
+      } else {
+        typeGetter = type.lookUpInheritedGetter(name,
+            library: _definingLibrary, thisType: !isSuper);
 
-      typeMethod = type.lookUpInheritedMethod(name,
-          library: _definingLibrary, thisType: !isSuper);
+        typeGetter ??= type.lookUpInheritedMethod(name,
+            library: _definingLibrary, thisType: !isSuper);
+
+        typeSetter = type.lookUpInheritedSetter(name,
+            library: _definingLibrary, thisType: !isSuper);
+      }
     }
 
     if (type is InterfaceType) {
@@ -2041,38 +2102,18 @@
     } else if (type is FunctionType) {
       lookupIn(_typeProvider.functionType);
     } else {
-      return;
+      return ResolutionResult.none;
     }
 
-    if (typeGetter != null) {
-      getterResult = ResolutionResult(property: typeGetter.variable);
-    } else if (typeMethod != null) {
-      getterResult = ResolutionResult(function: typeMethod);
-    }
-    if (typeSetter != null) {
-      setterResult = ResolutionResult(property: typeSetter.variable);
+    if (typeGetter != null || typeSetter != null) {
+      result = ResolutionResult(getter: typeGetter, setter: typeSetter);
     }
 
-    if (getterResult.isNone && setterResult.isNone) {
-      var result = _extensionResolver.findExtension(type, name, errorNode);
-      if (result.isSingle) {
-        if (result.getter != null) {
-          getterResult = result;
-        }
-        if (result.setter != null) {
-          setterResult = result;
-        }
-      } else if (result.isAmbiguous) {
-        getterResult = ResolutionResult.ambiguous;
-        setterResult = ResolutionResult.ambiguous;
-      }
+    if (result.isNone) {
+      result = _extensionResolver.findExtension(type, name, errorNode);
     }
-  }
 
-  ResolutionResult resolveOperator(
-      Expression target, DartType type, String name, Expression nameNode) {
-    resolve(target, type, name, nameNode);
-    return getterResult;
+    return result;
   }
 
   /// If the given [type] is a type parameter, replace it with its bound.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 2f1a57f..66c7f6c 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -272,6 +272,7 @@
         }
       }
     }
+    _checkStrictInferenceInParameters(node.parameters);
     super.visitConstructorDeclaration(node);
   }
 
@@ -316,6 +317,7 @@
       if (node.parent is CompilationUnit) {
         _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
       }
+      _checkStrictInferenceInParameters(node.functionExpression.parameters);
       super.visitFunctionDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
@@ -334,6 +336,10 @@
     if (node.parent is! FunctionDeclaration) {
       _checkForMissingReturn(null, node.body, node.declaredElement, node);
     }
+    DartType functionType = InferenceContext.getContext(node);
+    if (functionType is! FunctionType) {
+      _checkStrictInferenceInParameters(node.parameters);
+    }
     super.visitFunctionExpression(node);
   }
 
@@ -341,6 +347,7 @@
   void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
     _checkStrictInferenceReturnType(
         node.returnType, node, node.identifier.name);
+    _checkStrictInferenceInParameters(node.parameters);
     super.visitFunctionTypedFormalParameter(node);
   }
 
@@ -386,6 +393,7 @@
       _checkForMissingReturn(node.returnType, node.body, element, node);
       _checkForUnnecessaryNoSuchMethod(node);
       _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
+      _checkStrictInferenceInParameters(node.parameters);
       super.visitMethodDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
@@ -1136,7 +1144,35 @@
     }
   }
 
-  /// In "strict-inference" mode, check that [returnNode]'s return type is specified.
+  /// In "strict-inference" mode, check that each of the [parameters]' type is
+  /// specified.
+  _checkStrictInferenceInParameters(FormalParameterList parameters) {
+    void checkParameterTypeIsKnown(SimpleFormalParameter parameter) {
+      if (parameter.type == null) {
+        ParameterElement element = parameter.declaredElement;
+        _errorReporter.reportTypeErrorForNode(
+          HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
+          parameter,
+          [element.displayName],
+        );
+      }
+    }
+
+    if (_strictInference && parameters != null) {
+      for (FormalParameter parameter in parameters.parameters) {
+        if (parameter is SimpleFormalParameter) {
+          checkParameterTypeIsKnown(parameter);
+        } else if (parameter is DefaultFormalParameter) {
+          if (parameter.parameter is SimpleFormalParameter) {
+            checkParameterTypeIsKnown(parameter.parameter);
+          }
+        }
+      }
+    }
+  }
+
+  /// In "strict-inference" mode, check that [returnNode]'s return type is
+  /// specified.
   void _checkStrictInferenceReturnType(
       AstNode returnType, AstNode reportNode, String displayName) {
     if (!_strictInference) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 91b6336..1263674 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -117,8 +117,7 @@
   /**
    * Given a formal parameter list and a function type use the function type
    * to infer types for any of the parameters which have implicit (missing)
-   * types.  Only infers types in strong mode.  Returns true if inference
-   * has occurred.
+   * types.  Returns true if inference has occurred.
    */
   bool inferFormalParameterList(
       FormalParameterList node, DartType functionType) {
@@ -525,34 +524,6 @@
     _resolver.extensionResolver.resolveOverride(node);
   }
 
-  /// No inference is performed here; just static checking for the
-  /// "strict-inference" static analysis mode.
-  @override
-  void visitFormalParameterList(FormalParameterList node) {
-    void checkParameterTypeIsKnown(SimpleFormalParameter parameter) {
-      ParameterElement element = parameter.declaredElement;
-      if (parameter.type == null) {
-        _resolver.errorReporter.reportTypeErrorForNode(
-          HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
-          parameter,
-          [element.displayName],
-        );
-      }
-    }
-
-    if (_strictInference) {
-      for (FormalParameter parameter in node.parameters) {
-        if (parameter is SimpleFormalParameter) {
-          checkParameterTypeIsKnown(parameter);
-        } else if (parameter is DefaultFormalParameter) {
-          if (parameter.parameter is SimpleFormalParameter) {
-            checkParameterTypeIsKnown(parameter.parameter);
-          }
-        }
-      }
-    }
-  }
-
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     FunctionExpression function = node.functionExpression;
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index 75ab704..7ed3c90 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 
 /**
@@ -80,261 +77,3 @@
     }
   }
 }
-
-/**
- * The interface `MapIterator` defines the behavior of objects that iterate over the entries
- * in a map.
- *
- * This interface defines the concept of a current entry and provides methods to access the key and
- * value in the current entry. When an iterator is first created it will be positioned before the
- * first entry and there is no current entry until [moveNext] is invoked. When all of the
- * entries have been accessed there will also be no current entry.
- *
- * There is no guarantee made about the order in which the entries are accessible.
- */
-abstract class MapIterator<K, V> {
-  /**
-   * Return the key associated with the current element.
-   *
-   * @return the key associated with the current element
-   * @throws NoSuchElementException if there is no current element
-   */
-  K get key;
-
-  /**
-   * Return the value associated with the current element.
-   *
-   * @return the value associated with the current element
-   * @throws NoSuchElementException if there is no current element
-   */
-  V get value;
-
-  /**
-   * Set the value associated with the current element to the given value.
-   *
-   * @param newValue the new value to be associated with the current element
-   * @throws NoSuchElementException if there is no current element
-   */
-  void set value(V newValue);
-
-  /**
-   * Advance to the next entry in the map. Return `true` if there is a current element that
-   * can be accessed after this method returns. It is safe to invoke this method even if the
-   * previous invocation returned `false`.
-   *
-   * @return `true` if there is a current element that can be accessed
-   */
-  bool moveNext();
-}
-
-/**
- * Instances of the class `MultipleMapIterator` implement an iterator that can be used to
- * sequentially access the entries in multiple maps.
- */
-class MultipleMapIterator<K, V> implements MapIterator<K, V> {
-  /**
-   * The iterators used to access the entries.
-   */
-  List<MapIterator<K, V>> _iterators;
-
-  /**
-   * The index of the iterator currently being used to access the entries.
-   */
-  int _iteratorIndex = -1;
-
-  /**
-   * The current iterator, or `null` if there is no current iterator.
-   */
-  MapIterator<K, V> _currentIterator;
-
-  /**
-   * Initialize a newly created iterator to return the entries from the given maps.
-   *
-   * @param maps the maps containing the entries to be iterated
-   */
-  MultipleMapIterator(List<Map<K, V>> maps) {
-    int count = maps.length;
-    _iterators = new List<MapIterator<K, V>>(count);
-    for (int i = 0; i < count; i++) {
-      _iterators[i] = new SingleMapIterator<K, V>(maps[i]);
-    }
-  }
-
-  @override
-  K get key {
-    if (_currentIterator == null) {
-      throw new StateError('No element');
-    }
-    return _currentIterator.key;
-  }
-
-  @override
-  V get value {
-    if (_currentIterator == null) {
-      throw new StateError('No element');
-    }
-    return _currentIterator.value;
-  }
-
-  @override
-  void set value(V newValue) {
-    if (_currentIterator == null) {
-      throw new StateError('No element');
-    }
-    _currentIterator.value = newValue;
-  }
-
-  @override
-  bool moveNext() {
-    if (_iteratorIndex < 0) {
-      if (_iterators.isEmpty) {
-        _currentIterator = null;
-        return false;
-      }
-      if (_advanceToNextIterator()) {
-        return true;
-      } else {
-        _currentIterator = null;
-        return false;
-      }
-    }
-    if (_currentIterator.moveNext()) {
-      return true;
-    } else if (_advanceToNextIterator()) {
-      return true;
-    } else {
-      _currentIterator = null;
-      return false;
-    }
-  }
-
-  /**
-   * Under the assumption that there are no more entries that can be returned using the current
-   * iterator, advance to the next iterator that has entries.
-   *
-   * @return `true` if there is a current iterator that has entries
-   */
-  bool _advanceToNextIterator() {
-    _iteratorIndex++;
-    while (_iteratorIndex < _iterators.length) {
-      MapIterator<K, V> iterator = _iterators[_iteratorIndex];
-      if (iterator.moveNext()) {
-        _currentIterator = iterator;
-        return true;
-      }
-      _iteratorIndex++;
-    }
-    return false;
-  }
-}
-
-/**
- * Instances of the class `SingleMapIterator` implement an iterator that can be used to access
- * the entries in a single map.
- */
-class SingleMapIterator<K, V> implements MapIterator<K, V> {
-  /**
-   * The [Map] containing the entries to be iterated over.
-   */
-  final Map<K, V> _map;
-
-  /**
-   * The iterator used to access the entries.
-   */
-  Iterator<K> _keyIterator;
-
-  /**
-   * The current key, or `null` if there is no current key.
-   */
-  K _currentKey;
-
-  /**
-   * The current value.
-   */
-  V _currentValue;
-
-  /**
-   * Initialize a newly created iterator to return the entries from the given map.
-   *
-   * @param map the map containing the entries to be iterated over
-   */
-  SingleMapIterator(this._map) {
-    this._keyIterator = _map.keys.iterator;
-  }
-
-  @override
-  K get key {
-    if (_currentKey == null) {
-      throw new StateError('No element');
-    }
-    return _currentKey;
-  }
-
-  @override
-  V get value {
-    if (_currentKey == null) {
-      throw new StateError('No element');
-    }
-    if (_currentValue == null) {
-      _currentValue = _map[_currentKey];
-    }
-    return _currentValue;
-  }
-
-  @override
-  void set value(V newValue) {
-    if (_currentKey == null) {
-      throw new StateError('No element');
-    }
-    _currentValue = newValue;
-    _map[_currentKey] = newValue;
-  }
-
-  @override
-  bool moveNext() {
-    if (_keyIterator.moveNext()) {
-      _currentKey = _keyIterator.current;
-      _currentValue = null;
-      return true;
-    } else {
-      _currentKey = null;
-      return false;
-    }
-  }
-
-  /**
-   * Returns a new [SingleMapIterator] instance for the given [Map].
-   */
-  static SingleMapIterator forMap(Map map) => new SingleMapIterator(map);
-}
-
-/**
- * Instances of the class `TokenMap` map one set of tokens to another set of tokens.
- */
-class TokenMap {
-  /**
-   * A table mapping tokens to tokens. This should be replaced by a more performant implementation.
-   * One possibility is a pair of parallel arrays, with keys being sorted by their offset and a
-   * cursor indicating where to start searching.
-   */
-  Map<Token, Token> _map = new HashMap<Token, Token>();
-
-  /**
-   * Return the token that is mapped to the given token, or `null` if there is no token
-   * corresponding to the given token.
-   *
-   * @param key the token being mapped to another token
-   * @return the token that is mapped to the given token
-   */
-  Token get(Token key) => _map[key];
-
-  /**
-   * Map the key to the value.
-   *
-   * @param key the token being mapped to the value
-   * @param value the token to which the key will be mapped
-   */
-  void put(Token key, Token value) {
-    _map[key] = value;
-  }
-}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 25e5b7f..bb96dd0 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -289,7 +289,10 @@
 
     var libraryContext = elementFactory.libraryMap[uriStr];
     if (libraryContext == null) {
-      throw ArgumentError('Missing library: $uriStr');
+      throw ArgumentError(
+        'Missing library: $uriStr\n'
+        'Available libraries: ${elementFactory.libraryMap.keys.toList()}',
+      );
     }
     var libraryNode = libraryContext.node;
     var hasName = libraryNode.name.isNotEmpty;
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index ddf6cf8..3a196922 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -900,11 +900,18 @@
 
       // The member may be from a superclass, so we need to ensure the type
       // parameters are properly substituted.
-      var classType = targetType.element.type;
-      var classLowerBound = classType.instantiate(new List.filled(
-          classType.typeParameters.length, BottomTypeImpl.instance));
+      var classElement = targetType.element;
+      var classLowerBound = classElement.instantiate(
+        typeArguments: List.filled(
+          classElement.typeParameters.length,
+          BottomTypeImpl.instance,
+        ),
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
       var memberLowerBound = inheritance.getMember(
-          classLowerBound, Name(element.librarySource.uri, element.name));
+        classLowerBound,
+        Name(element.librarySource.uri, element.name),
+      );
       if (memberLowerBound == null &&
           element.enclosingElement is ExtensionElement) {
         return;
@@ -1465,11 +1472,11 @@
     // Find all generic interfaces that could be used to call into members of
     // this class. This will help us identify which parameters need checks
     // for soundness.
-    var allCovariant = _findAllGenericInterfaces(element.type);
+    var allCovariant = _findAllGenericInterfaces(element);
     if (allCovariant.isEmpty) return;
 
     var seenConcreteMembers = new HashSet<String>();
-    var members = _getConcreteMembers(element.type, seenConcreteMembers);
+    var members = _getConcreteMembers(element.thisType, seenConcreteMembers);
 
     // For members on this class, check them against all generic interfaces.
     var checks = _findCovariantChecks(members, allCovariant);
@@ -1646,7 +1653,7 @@
     void visitImmediateSuper(InterfaceType type) {
       // For members of mixins/supertypes, check them against new interfaces,
       // and also record any existing checks they already had.
-      var oldCovariant = _findAllGenericInterfaces(type);
+      var oldCovariant = _findAllGenericInterfaces(type.element);
       var newCovariant = allCovariant.difference(oldCovariant);
       if (newCovariant.isEmpty) return;
 
@@ -1688,32 +1695,40 @@
     return x == y;
   }
 
-  /// Find all generic interfaces that are implemented by [type], including
-  /// [type] itself if it is generic.
+  /// Find all generic interfaces that are implemented by [element], including
+  /// [element] itself if it is generic.
   ///
   /// This represents the complete set of unsafe covariant interfaces that could
-  /// be used to call members of [type].
+  /// be used to call members of [element].
   ///
   /// Because we're going to instantiate these to their upper bound, we don't
   /// have to track type parameters.
-  static Set<ClassElement> _findAllGenericInterfaces(InterfaceType type) {
-    var visited = new HashSet<ClassElement>();
-    var genericSupertypes = new Set<ClassElement>();
+  static Set<ClassElement> _findAllGenericInterfaces(ClassElement element) {
+    var visited = <ClassElement>{};
+    var genericSupertypes = <ClassElement>{};
 
-    void visitTypeAndSupertypes(InterfaceType type) {
-      var element = type.element;
+    void visitClassAndSupertypes(ClassElement element) {
       if (visited.add(element)) {
         if (element.typeParameters.isNotEmpty) {
           genericSupertypes.add(element);
         }
+
         var supertype = element.supertype;
-        if (supertype != null) visitTypeAndSupertypes(supertype);
-        element.mixins.forEach(visitTypeAndSupertypes);
-        element.interfaces.forEach(visitTypeAndSupertypes);
+        if (supertype != null) {
+          visitClassAndSupertypes(supertype.element);
+        }
+
+        for (var interface in element.mixins) {
+          visitClassAndSupertypes(interface.element);
+        }
+
+        for (var interface in element.interfaces) {
+          visitClassAndSupertypes(interface.element);
+        }
       }
     }
 
-    visitTypeAndSupertypes(type);
+    visitClassAndSupertypes(element);
 
     return genericSupertypes;
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index acef919..7e9a9ed 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -151,6 +151,10 @@
     return _node(search, (n) => n is IntegerLiteral);
   }
 
+  Label label(String search) {
+    return _node(search, (n) => n is Label);
+  }
+
   LibraryDirective library(String search) {
     return _node(search, (n) => n is LibraryDirective);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 176212d..da08116 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -344,6 +344,7 @@
 
   void add(E value) {}
   void addAll(Iterable<E> iterable) {}
+  Map<int, E> asMap() {}
   void clear() {}
   int indexOf(Object element);
   E removeLast() {}
@@ -499,7 +500,7 @@
       'dart:html',
       '$sdkRoot/lib/html/dart2js/html_dart2js.dart',
       '''
-library dart.html;
+library dart.dom.html;
 import 'dart:async';
 
 class Event {}
@@ -566,6 +567,10 @@
   bool autofocus;
 }
 
+class EmbedElement extends HtmlEment {
+  String src;
+}
+
 class HeadingElement extends HtmlElement {
   factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
   factory HeadingElement.h1() => document.createElement("h1");
@@ -592,6 +597,10 @@
   String src;
 }
 
+class ImageElement extends HtmlEment {
+  String src;
+}
+
 class OptionElement extends HtmlElement {
   factory OptionElement({String data: '', String value : '', bool selected: false}) {
   }
@@ -600,6 +609,11 @@
   }
 }
 
+class ScriptElement extends HtmlElement {
+  String src;
+  String type;
+}
+
 class TableSectionElement extends HtmlElement {
 
   List<TableRowElement> get rows => null;
@@ -652,7 +666,7 @@
       'dart:html',
       '$sdkRoot/lib/html/dartium/html_dartium.dart',
       '''
-library dart.html;
+library dart.dom.html;
 import 'dart:async';
 
 class Event {}
@@ -719,6 +733,10 @@
   bool autofocus;
 }
 
+class EmbedElement extends HtmlEment {
+  String src;
+}
+
 class HeadingElement extends HtmlElement {
   factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
   factory HeadingElement.h1() => document.createElement("h1");
@@ -745,6 +763,10 @@
   String src;
 }
 
+class ImageElement extends HtmlEment {
+  String src;
+}
+
 class OptionElement extends HtmlElement {
   factory OptionElement({String data: '', String value : '', bool selected: false}) {
   }
@@ -753,6 +775,11 @@
   }
 }
 
+class ScriptElement extends HtmlElement {
+  String src;
+  String type;
+}
+
 class TableSectionElement extends HtmlElement {
 
   List<TableRowElement> get rows => null;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 67ae027..a1a5220 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.38.3
+version: 0.38.4
 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.25
+  front_end: 0.1.26
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
-  kernel: 0.3.25
+  kernel: 0.3.26
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
@@ -27,5 +27,6 @@
 dev_dependencies:
   analysis_tool:
     path: ../analysis_tool
+  pedantic: ^1.8.0
   test: ^1.0.0
   test_reflective_loader: ^0.1.8
diff --git a/pkg/analyzer/test/dart/analysis/declared_variables_test.dart b/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
index 2460423..4563f45 100644
--- a/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
+++ b/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
@@ -9,8 +9,6 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/test_support.dart';
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DeclaredVariablesTest);
@@ -18,7 +16,7 @@
 }
 
 @reflectiveTest
-class DeclaredVariablesTest extends EngineTestCase {
+class DeclaredVariablesTest {
   void test_getBool_false() {
     TestTypeProvider typeProvider = new TestTypeProvider();
     String variableName = "var";
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 163cb6c..61d45e6 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -133,7 +133,7 @@
 }
 
 @reflectiveTest
-class ConstructorDeclarationTest extends EngineTestCase {
+class ConstructorDeclarationTest {
   void test_firstTokenAfterCommentAndMetadata_all_inverted() {
     Token externalKeyword = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
     externalKeyword.offset = 14;
@@ -205,7 +205,7 @@
 }
 
 @reflectiveTest
-class FieldFormalParameterTest extends EngineTestCase {
+class FieldFormalParameterTest {
   void test_endToken_noParameters() {
     FieldFormalParameter parameter =
         AstTestFactory.fieldFormalParameter2('field');
@@ -220,7 +220,7 @@
 }
 
 @reflectiveTest
-class IndexExpressionTest extends EngineTestCase {
+class IndexExpressionTest {
   void test_inGetterContext_assignment_compound_left() {
     IndexExpression expression = AstTestFactory.indexExpression(
         AstTestFactory.identifier3("a"), AstTestFactory.identifier3("b"));
@@ -343,7 +343,7 @@
 }
 
 @reflectiveTest
-class MethodDeclarationTest extends EngineTestCase {
+class MethodDeclarationTest {
   void test_firstTokenAfterCommentAndMetadata_external() {
     MethodDeclaration declaration =
         AstTestFactory.methodDeclaration4(external: true, name: 'm');
@@ -406,7 +406,7 @@
 }
 
 @reflectiveTest
-class NodeListTest extends EngineTestCase {
+class NodeListTest {
   void test_add() {
     AstNode parent = AstTestFactory.argumentList();
     AstNode firstNode = AstTestFactory.booleanLiteral(true);
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index 92d475a..fc77013 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -19,6 +19,7 @@
 import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer/src/generated/testing/node_search.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -222,8 +223,8 @@
   void test_metadata_localVariableDeclaration() {
     var code = 'f() { @a int x, y; }';
     buildElementsForText(code);
-    var x = findLocalVariable(code, 'x, ');
-    var y = findLocalVariable(code, 'x, ');
+    var x = findLocalVariable('x, ');
+    var y = findLocalVariable('x, ');
     checkMetadata(x);
     checkMetadata(y);
     expect(x.metadata, same(y.metadata));
@@ -232,15 +233,15 @@
   void test_metadata_visitDeclaredIdentifier() {
     var code = 'f() { for (@a var x in y) {} }';
     buildElementsForText(code);
-    var x = findLocalVariable(code, 'x in');
+    var x = findLocalVariable('x in');
     checkMetadata(x);
   }
 
   void test_visitCatchClause() {
     var code = 'f() { try {} catch (e, s) {} }';
     buildElementsForText(code);
-    var e = findLocalVariable(code, 'e, ');
-    var s = findLocalVariable(code, 's) {}');
+    var e = findLocalVariable('e, ');
+    var s = findLocalVariable('s) {}');
 
     expect(e, isNotNull);
     expect(e.name, 'e');
@@ -263,7 +264,7 @@
   void test_visitCatchClause_withType() {
     var code = 'f() { try {} on E catch (e) {} }';
     buildElementsForText(code);
-    var e = findLocalVariable(code, 'e) {}');
+    var e = findLocalVariable('e) {}');
     expect(e, isNotNull);
     expect(e.name, 'e');
     expect(e.hasImplicitType, isFalse);
@@ -292,7 +293,7 @@
   void test_visitDeclaredIdentifier_noType() {
     var code = 'f() { for (var i in []) {} }';
     buildElementsForText(code);
-    var variable = findLocalVariable(code, 'i in');
+    var variable = findLocalVariable('i in');
     assertHasCodeRange(variable, 11, 5);
     expect(variable, isNotNull);
     expect(variable.hasImplicitType, isTrue);
@@ -309,7 +310,7 @@
   void test_visitDeclaredIdentifier_type() {
     var code = 'f() { for (int i in []) {} }';
     buildElementsForText(code);
-    var variable = findLocalVariable(code, 'i in');
+    var variable = findLocalVariable('i in');
     assertHasCodeRange(variable, 11, 5);
     expect(variable.hasImplicitType, isFalse);
     expect(variable.isConst, isFalse);
@@ -522,7 +523,7 @@
   void test_visitLabeledStatement() {
     String code = 'f() { l: print(42); }';
     buildElementsForText(code);
-    LabelElement label = findLabel(code, 'l:');
+    LabelElement label = findLabel('l:');
     expect(label, isNotNull);
     expect(label.name, 'l');
     expect(label.isSynthetic, isFalse);
@@ -548,13 +549,13 @@
     expect(parameter, isNotNull);
     expect(parameter.name, parameterName);
 
-    var v = findLocalVariable(code, 'v;');
+    var v = findLocalVariable('v;');
     expect(v.name, 'v');
 
-    var e = findLocalVariable(code, 'e) {}');
+    var e = findLocalVariable('e) {}');
     expect(e.name, 'e');
 
-    LabelElement label = findLabel(code, 'l:');
+    LabelElement label = findLabel('l:');
     expect(label, isNotNull);
     expect(label.name, labelName);
   }
@@ -750,7 +751,7 @@
   void test_visitVariableDeclaration_inConstructor() {
     var code = 'class C { C() { var v = 1; } }';
     buildElementsForText(code);
-    var v = findLocalVariable(code, 'v =');
+    var v = findLocalVariable('v =');
     assertHasCodeRange(v, 16, 9);
     expect(v.hasImplicitType, isTrue);
     expect(v.name, 'v');
@@ -1063,11 +1064,12 @@
     main.encloseElements(holder.functions);
     main.encloseElements(holder.localVariables);
 
-    var f1 = findLocalFunction(code, 'f1() {');
-    var f2 = findLocalFunction(code, 'f2() {');
-    var v1 = findLocalVariable(code, 'v1;');
-    var v2 = findLocalVariable(code, 'v2;');
-    var v3 = findLocalVariable(code, 'v3;');
+    findNode = FindNode(code, _compilationUnit);
+    var f1 = findLocalFunction('f1() {');
+    var f2 = findLocalFunction('f2() {');
+    var v1 = findLocalVariable('v1;');
+    var v2 = findLocalVariable('v2;');
+    var v3 = findLocalVariable('v3;');
 
     expect(v1.enclosingElement, main);
     {
@@ -1198,7 +1200,7 @@
   void test_visitVariableDeclaration_local() {
     var code = 'class C { m() { T v = null; } }';
     buildElementsForText(code);
-    LocalVariableElement element = findIdentifier(code, 'v =').staticElement;
+    LocalVariableElement element = findNode.simple('v =').staticElement;
     expect(element.hasImplicitType, isFalse);
     expect(element.name, 'v');
     expect(element.initializer, isNotNull);
@@ -2607,6 +2609,7 @@
 abstract class _BaseTest extends ParserTestCase {
   CompilationUnitElement compilationUnitElement;
   CompilationUnit _compilationUnit;
+  FindNode findNode;
 
   CompilationUnit get compilationUnit => _compilationUnit;
 
@@ -2667,20 +2670,16 @@
 
   AstVisitor createElementBuilder(ElementHolder holder);
 
-  SimpleIdentifier findIdentifier(String code, String prefix) {
-    return EngineTestCase.findSimpleIdentifier(compilationUnit, code, prefix);
+  LabelElement findLabel(String prefix) {
+    return findNode.simple(prefix).staticElement;
   }
 
-  LabelElement findLabel(String code, String prefix) {
-    return findIdentifier(code, prefix).staticElement;
+  FunctionElement findLocalFunction(String search) {
+    return findNode.functionDeclaration(search).declaredElement;
   }
 
-  FunctionElement findLocalFunction(String code, String prefix) {
-    return findIdentifier(code, prefix).staticElement;
-  }
-
-  LocalVariableElement findLocalVariable(String code, String prefix) {
-    return findIdentifier(code, prefix).staticElement;
+  LocalVariableElement findLocalVariable(String search) {
+    return findNode.simple(search).staticElement;
   }
 
   void setUp() {
@@ -2702,6 +2701,7 @@
     AnalysisEngine.instance.logger = logger;
     try {
       _compilationUnit = parseCompilationUnit(code);
+      findNode = FindNode(code, _compilationUnit);
       compilationUnit.accept(visitor);
     } finally {
       expect(logger.log, hasLength(0));
diff --git a/pkg/analyzer/test/dart/element/element_test.dart b/pkg/analyzer/test/dart/element/element_test.dart
index bfab82b..9ad4872 100644
--- a/pkg/analyzer/test/dart/element/element_test.dart
+++ b/pkg/analyzer/test/dart/element/element_test.dart
@@ -7,8 +7,6 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/test_support.dart';
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ElementKindTest);
@@ -16,7 +14,7 @@
 }
 
 @reflectiveTest
-class ElementKindTest extends EngineTestCase {
+class ElementKindTest {
   void test_of_nonNull() {
     expect(ElementKind.of(ElementFactory.classElement2("A")),
         same(ElementKind.CLASS));
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
index a796291..1b84665 100644
--- a/pkg/analyzer/test/error/error_reporter_test.dart
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -28,9 +28,7 @@
   }
 
   test_reportErrorForElement_named() async {
-    addTestFile('class A {}');
-    await resolveTestFile();
-
+    await resolveTestCode('class A {}');
     var element = findElement.class_('A');
     var reporter = ErrorReporter(listener, element.source);
     reporter.reportErrorForElement(
@@ -44,12 +42,10 @@
   }
 
   test_reportErrorForElement_unnamed() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async';
 import 'dart:math';
 ''');
-    await resolveTestFile();
-
     var element = findElement.import('dart:math');
 
     var reporter = ErrorReporter(listener, element.source);
@@ -94,7 +90,7 @@
   test_reportTypeErrorForNode_differentNames() async {
     newFile('/test/lib/a.dart', content: 'class A {}');
     newFile('/test/lib/b.dart', content: 'class B {}');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'package:test/a.dart';
 import 'package:test/b.dart';
 
@@ -102,8 +98,6 @@
   x;
 }
 ''');
-    await resolveTestFile();
-
     var aImport = findElement.importFind('package:test/a.dart');
     var bImport = findElement.importFind('package:test/b.dart');
 
@@ -131,7 +125,7 @@
   test_reportTypeErrorForNode_sameName() async {
     newFile('/test/lib/a.dart', content: 'class A {}');
     newFile('/test/lib/b.dart', content: 'class A {}');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'package:test/a.dart';
 import 'package:test/b.dart';
 
@@ -139,8 +133,6 @@
   x;
 }
 ''');
-    await resolveTestFile();
-
     var aImport = findElement.importFind('package:test/a.dart');
     var bImport = findElement.importFind('package:test/b.dart');
 
@@ -167,7 +159,7 @@
   test_reportTypeErrorForNode_sameName_functionType() async {
     newFile('/test/lib/a.dart', content: 'class A{}');
     newFile('/test/lib/b.dart', content: 'class A{}');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as a;
 import 'b.dart' as b;
 
@@ -178,8 +170,6 @@
   x;
 }
 ''');
-    await resolveTestFile();
-
     var fa = findNode.topLevelVariableDeclaration('fa');
     var fb = findNode.topLevelVariableDeclaration('fb');
 
@@ -199,7 +189,7 @@
   test_reportTypeErrorForNode_sameName_nested() async {
     newFile('/test/lib/a.dart', content: 'class A{}');
     newFile('/test/lib/b.dart', content: 'class A{}');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as a;
 import 'b.dart' as b;
 
@@ -211,8 +201,6 @@
   x;
 }
 ''');
-    await resolveTestFile();
-
     var ba = findNode.topLevelVariableDeclaration('ba');
     var bb = findNode.topLevelVariableDeclaration('bb');
 
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index a0153b8..c7b52204 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -134,7 +134,7 @@
 }
 
 @reflectiveTest
-class ErrorSeverityTest extends EngineTestCase {
+class ErrorSeverityTest {
   test_max_error_error() async {
     expect(ErrorSeverity.ERROR.max(ErrorSeverity.ERROR),
         same(ErrorSeverity.ERROR));
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 7d8db75..accf42d 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -487,18 +487,15 @@
 
   Future<EvaluationResult> _getExpressionValue(String expressionCode,
       {String context: ''}) async {
-    var path = convertPath('/test/lib/test.dart');
-
-    var file = newFile(path, content: '''
+    await resolveTestCode('''
 var x = $expressionCode;
 
 $context
 ''');
 
-    await resolveTestFile();
-
     var expression = findNode.variableDeclaration('x =').initializer;
 
+    var file = getFile(result.path);
     var evaluator = ConstantEvaluator(
       file.createSource(result.uri),
       result.typeProvider,
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index db29c01..e223c2f 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/declaration_resolver.dart';
@@ -17,7 +16,6 @@
 
 import '../src/dart/resolution/driver_resolution.dart';
 import '../util/element_type_matchers.dart';
-import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -54,9 +52,7 @@
   Future<void> setupCode(String code) async {
     this.code = code;
 
-    addTestFile(code + ' const a = null;');
-    await resolveTestFile();
-
+    await resolveTestCode(code + ' const a = null;');
     unit = result.unit;
     unit2 = _cloneResolveUnit(unit);
   }
@@ -103,7 +99,7 @@
   }
 
   test_exportDirective_resynthesized() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 @a
 export "dart:async";
 
@@ -113,7 +109,6 @@
 const a = null;
 const b = null;
 ''');
-    await resolveTestFile();
     unit = result.unit;
 
     expect(unit.directives[0].metadata.single.name.name, 'a');
@@ -186,7 +181,7 @@
   }
 
   test_importDirective_resynthesized() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 @a
 import "dart:async";
 
@@ -196,7 +191,6 @@
 const a = null;
 const b = null;
 ''');
-    await resolveTestFile();
     unit = result.unit;
 
     expect(unit.directives[0].metadata.single.name.name, 'a');
@@ -223,8 +217,7 @@
   }
 
   test_libraryDirective_resynthesized() async {
-    addTestFile('@a library L; const a = null;');
-    await resolveTestFile();
+    await resolveTestCode('@a library L; const a = null;');
     unit = result.unit;
 
     expect(unit.directives.single.metadata.single.name.name, 'a');
@@ -245,9 +238,8 @@
     await setupCode('f() { @a g() {} }');
     // Note: metadata on local function declarations is ignored by the
     // analyzer.  TODO(paulberry): is this a bug?
-    FunctionDeclaration node = EngineTestCase.findNode(
-        unit, code, 'g', (AstNode n) => n is FunctionDeclaration);
-    NodeList<Annotation> metadata = (node as FunctionDeclarationImpl).metadata;
+    var node = FindNode(code, unit).functionDeclaration('g()');
+    NodeList<Annotation> metadata = node.metadata;
     if (Parser.useFasta) {
       expect(metadata, hasLength(1));
     } else {
@@ -285,7 +277,7 @@
     newFile('/test/lib/part_a.dart', content: 'part of L;');
     newFile('/test/lib/part_b.dart', content: 'part of L;');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 library L;
 
 @a
@@ -297,7 +289,6 @@
 const a = null;
 const b = null;
 ''');
-    await resolveTestFile();
     unit = result.unit;
 
     expect(unit.directives[1].metadata.single.name.name, 'a');
@@ -354,8 +345,7 @@
   }
 
   NodeList<Annotation> _findMetadata(CompilationUnit unit, String search) {
-    AstNode node =
-        EngineTestCase.findNode(unit, code, search, (AstNode _) => true);
+    var node = FindNode(code, unit).any(search);
     while (node != null) {
       if (node is AnnotatedNode && node.metadata.isNotEmpty) {
         return node.metadata;
@@ -372,7 +362,7 @@
 @reflectiveTest
 class DeclarationResolverTest extends DriverResolutionTest {
   test_closure_inside_catch_block() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   try {
   } catch (e) {
@@ -380,14 +370,13 @@
   }
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_labeled_statement() async {
-    addTestFile('''
+    await resolveTestCode('''
 f(b) {
   foo: while (true) {
     if (b) {
@@ -397,14 +386,13 @@
   }
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_switch_case() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(k, m) {
   switch (k) {
     case 0:
@@ -413,14 +401,13 @@
   }
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_switch_default() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(k, m) {
   switch (k) {
     default:
@@ -429,18 +416,15 @@
   }
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_functionDeclaration_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int get zzz => 42;
 ''');
-    await resolveTestFile();
-
     var getterElement = findElement.topGet('zzz');
     expect(getterElement.isGetter, isTrue);
 
@@ -451,11 +435,9 @@
   }
 
   test_functionDeclaration_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void set zzz(_) {}
 ''');
-    await resolveTestFile();
-
     var setterElement = findElement.topSet('zzz');
     expect(setterElement.isSetter, isTrue);
 
@@ -466,92 +448,83 @@
   }
 
   test_genericFunction_asFunctionReturnType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 Function(int, String) f() => null;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asGenericFunctionReturnType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef F<T> = int Function(T t, S s) Function<S>(int);
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asMethodReturnType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   Function(int, String) m() => null;
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asParameterReturnType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 f(Function(int, String) p) => null;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTopLevelVariableType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int Function(int, String) v;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 List<Function(int)> v;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_lessNodes() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 Map<Function<int>> v;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_moreNodes() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 List<Function<int>, Function<String>> v;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_noNodes() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 List v;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
@@ -561,34 +534,29 @@
     String code = r'''
 var v = <Function(int)>[];
 ''';
-    addTestFile(code);
-    await resolveTestFile();
-
+    await resolveTestCode(code);
     var newUnit = _cloneResolveUnit(result.unit);
     var initializer = FindNode(result.content, newUnit).listLiteral('>[]');
     expect(initializer.typeArguments.arguments[0].type, isNotNull);
   }
 
   test_genericFunction_invalid_missingParameterName() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef F = Function({int});
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_invalid_functionDeclaration_getter_inFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 var v = (() {
   main() {
     int get zzz => 42;
   }
 });
 ''');
-    await resolveTestFile();
-
     // re-resolve
     var unit2 = _cloneResolveUnit(result.unit);
     var getterName = FindNode(result.content, unit2).simple('zzz =>');
@@ -598,15 +566,13 @@
   }
 
   test_invalid_functionDeclaration_setter_inFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 var v = (() {
   main() {
     set zzz(x) {}
   }
 });
 ''');
-    await resolveTestFile();
-
     // re-resolve
     var unit2 = _cloneResolveUnit(result.unit);
     var setterName = FindNode(result.content, unit2).simple('zzz(x)');
@@ -616,96 +582,86 @@
   }
 
   test_visitExportDirective_notExistingSource() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 export 'foo.dart';
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitExportDirective_unresolvedUri() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 export 'package:foo/bar.dart';
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitFunctionExpression() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main(List<String> items) {
   items.forEach((item) {});
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_0() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef F<T> = Function<S>(List<S> list, Function<A>(A), T);
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_1() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef F = Function({int});
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_2() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef F = int;
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitImportDirective_notExistingSource() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'foo.dart';
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitImportDirective_unresolvedUri() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'package:foo/bar.dart';
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitMethodDeclaration_getter_duplicate() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int get zzz => 1;
   String get zzz => null;
 }
 ''');
-    await resolveTestFile();
-
     var firstElement = findNode.simple('zzz => 1').staticElement;
     var secondElement = findNode.simple('zzz => null').staticElement;
     expect(firstElement, isNot(same(secondElement)));
@@ -720,15 +676,13 @@
   }
 
   test_visitMethodDeclaration_getterSetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int _field = 0;
   int get field => _field;
   void set field(value) {_field = value;}
 }
 ''');
-    await resolveTestFile();
-
     var getterElement = findElement.getter('field');
     var setterElement = findElement.setter('field');
 
@@ -742,14 +696,12 @@
   }
 
   test_visitMethodDeclaration_method_duplicate() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void zzz(x) {}
   void zzz(y) {}
 }
 ''');
-    await resolveTestFile();
-
     MethodElement firstElement = findNode.simple('zzz(x)').staticElement;
     MethodElement secondElement = findNode.simple('zzz(y)').staticElement;
     expect(firstElement, isNot(same(secondElement)));
@@ -765,14 +717,12 @@
 
   test_visitMethodDeclaration_setter_duplicate() async {
     // https://github.com/dart-lang/sdk/issues/25601
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   set zzz(x) {}
   set zzz(y) {}
 }
 ''');
-    await resolveTestFile();
-
     PropertyAccessorElement firstElement =
         findNode.simple('zzz(x)').staticElement;
     PropertyAccessorElement secondElement =
@@ -789,23 +739,21 @@
   }
 
   test_visitMethodDeclaration_unaryMinus() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C operator -() => null;
   C operator -(C other) => null;
 }
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitPartDirective_notExistingSource() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 part 'foo.bar';
 ''');
-    await resolveTestFile();
     // re-resolve
     _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index a03c601..6a4c187 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -275,13 +275,11 @@
       String annotationText,
       validator(SimpleIdentifier name1, SimpleIdentifier name2,
           SimpleIdentifier name3, Element annotationElement)) async {
-    addTestFile('''
+    await resolveTestCode('''
 import 'a.dart' $annotationPrefix;
 $annotationText
 class C {}
 ''');
-    await resolveTestFile();
-
     var clazz = findNode.classDeclaration('C');
     Annotation annotation = clazz.metadata.single;
     Identifier name = annotation.name;
@@ -298,8 +296,7 @@
 }
 
 @reflectiveTest
-class ElementResolverTest extends EngineTestCase
-    with ResourceProviderMixin, ElementsTypesMixin {
+class ElementResolverTest with ResourceProviderMixin, ElementsTypesMixin {
   /**
    * The error listener to which errors will be reported.
    */
@@ -376,9 +373,7 @@
     _listener.assertNoErrors();
   }
 
-  @override
   void setUp() {
-    super.setUp();
     _listener = new GatheringErrorListener();
     _createResolver();
   }
@@ -427,7 +422,7 @@
         leftHandSide, TokenType.PLUS_EQ, AstTestFactory.integer(1));
     _resolveNode(assignment);
     expect(
-        assignment.staticElement, same(getMethod(_typeProvider.numType, "+")));
+        assignment.staticElement, same(_typeProvider.numType.getMethod('+')));
     _listener.assertNoErrors();
   }
 
@@ -488,7 +483,7 @@
     BinaryExpression expression = AstTestFactory.binaryExpression(
         left, TokenType.PLUS, AstTestFactory.identifier3("j"));
     _resolveNode(expression);
-    expect(expression.staticElement, getMethod(numType, "+"));
+    expect(expression.staticElement, numType.getMethod('+'));
     _listener.assertNoErrors();
   }
 
@@ -793,7 +788,7 @@
         AstTestFactory.methodInvocation(left, methodName);
     _resolveNode(invocation);
     expect(invocation.methodName.staticElement,
-        same(getMethod(numType, methodName)));
+        same(numType.getMethod(methodName)));
     _listener.assertNoErrors();
   }
 
@@ -804,7 +799,7 @@
     PostfixExpression expression =
         AstTestFactory.postfixExpression(operand, TokenType.PLUS_PLUS);
     _resolveNode(expression);
-    expect(expression.staticElement, getMethod(numType, "+"));
+    expect(expression.staticElement, numType.getMethod('+'));
     _listener.assertNoErrors();
   }
 
@@ -830,8 +825,10 @@
         AstTestFactory.postfixExpression(operand, TokenType.BANG);
     _resolveNode(expression);
     // TODO(danrubel): fails with Unsupported operation
-    expect(expression.staticElement, getMethod(numType, "!"));
+    expect(expression.staticElement, numType.getMethod('!'));
     _listener.assertNoErrors();
+    // TODO(scheglov) This is wrong: `expr!` should not be resolved to `num.!`.
+    fail('Expectations are wrong.');
   }
 
   test_visitPrefixedIdentifier_dynamic() async {
@@ -942,7 +939,7 @@
     PrefixExpression expression =
         AstTestFactory.prefixExpression(TokenType.PLUS_PLUS, operand);
     _resolveNode(expression);
-    expect(expression.staticElement, getMethod(numType, "+"));
+    expect(expression.staticElement, numType.getMethod('+'));
     _listener.assertNoErrors();
   }
 
@@ -1012,7 +1009,7 @@
     String fieldName = 'nan';
     SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
     _resolveInClass(node, doubleType.element);
-    expect(node.staticElement, getGetter(doubleType, fieldName));
+    expect(node.staticElement, doubleType.getGetter(fieldName));
     _listener.assertNoErrors();
   }
 
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 165a105..6659778 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -223,8 +223,7 @@
   }
 
   Future<void> _assertCanBeAnalyzed(String text) async {
-    addTestFile(text);
-    await resolveTestFile();
+    await resolveTestCode(text);
     assertHasTestErrors();
   }
 }
@@ -271,8 +270,7 @@
   }
 
   Future<void> _assertCanBeAnalyzed(String text) async {
-    addTestFile(text);
-    await resolveTestFile();
+    await resolveTestCode(text);
     assertHasTestErrors();
   }
 }
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 805d5c7..1a16278 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -46,6 +46,7 @@
     defineReflectiveTests(SimpleParserTest_Fasta);
     defineReflectiveTests(StatementParserTest_Fasta);
     defineReflectiveTests(TopLevelParserTest_Fasta);
+    defineReflectiveTests(VarianceParserTest_Fasta);
   });
 }
 
@@ -1801,6 +1802,133 @@
   }
 }
 
+@reflectiveTest
+class VarianceParserTest_Fasta extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    return super.parseCompilationUnit(content,
+        codes: codes,
+        errors: errors,
+        featureSet: featureSet ??
+            FeatureSet.forTesting(
+              sdkVersion: '2.5.0',
+              additionalFeatures: [Feature.variance],
+            ));
+  }
+
+  void test_class_enabled_single() {
+    var unit = parseCompilationUnit('class A<in T> { }');
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+    expect(classDecl.typeParameters.typeParameters, hasLength(1));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+  }
+
+  void test_class_enabled_multipleVariances() {
+    var unit = parseCompilationUnit('class A<in out inout T> { }', errors: [
+      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 11, 3),
+      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 15, 5)
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+    expect(classDecl.typeParameters.typeParameters, hasLength(1));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+  }
+
+  void test_class_disabled_single() {
+    parseCompilationUnit('class A<out T> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_class_disabled_multiple() {
+    parseCompilationUnit('class A<in T, inout U, out V> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 2),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 5),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 23, 3)
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_mixin_enabled_single() {
+    var unit = parseCompilationUnit('mixin A<inout T> { }');
+    expect(unit.declarations, hasLength(1));
+    var mixinDecl = unit.declarations[0] as MixinDeclaration;
+    expect(mixinDecl.name.name, 'A');
+    expect(mixinDecl.typeParameters.typeParameters, hasLength(1));
+    expect(mixinDecl.typeParameters.typeParameters[0].name.name, 'T');
+  }
+
+  void test_mixin_disabled_single() {
+    parseCompilationUnit('mixin A<inout T> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_mixin_disabled_multiple() {
+    parseCompilationUnit('mixin A<inout T, out U> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_typedef_enabled() {
+    parseCompilationUnit('typedef A<inout X> = X Function(X);', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+    ]);
+  }
+
+  void test_typedef_disabled() {
+    parseCompilationUnit('typedef A<inout X> = X Function(X);',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_list_enabled() {
+    parseCompilationUnit('List<out String> stringList = [];', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
+    ]);
+  }
+
+  void test_list_disabled() {
+    parseCompilationUnit('List<out String> stringList = [];',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_function_enabled() {
+    parseCompilationUnit('void A(in int value) {}', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 2),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
+    ]);
+  }
+
+  void test_function_disabled() {
+    parseCompilationUnit('void A(in int value) {}',
+        errors: [
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 2),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+}
+
 /**
  * Implementation of [AbstractParserTestCase] specialized for testing the
  * Fasta parser.
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 584d201..ed1b914 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -9412,9 +9412,7 @@
  * Implementation of [AbstractParserTestCase] specialized for testing the
  * analyzer parser.
  */
-class ParserTestCase extends EngineTestCase
-    with ParserTestHelpers
-    implements AbstractParserTestCase {
+class ParserTestCase with ParserTestHelpers implements AbstractParserTestCase {
   /**
    * A flag indicating whether parser is to parse function bodies.
    */
@@ -10046,9 +10044,7 @@
     }
   }
 
-  @override
   void setUp() {
-    super.setUp();
     parseFunctionBodies = true;
   }
 }
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 691b596..c49393b 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
 import 'dart:collection';
 
 import 'package:analyzer/dart/analysis/features.dart';
@@ -61,7 +60,7 @@
 }
 
 @reflectiveTest
-class ChangeSetTest extends EngineTestCase {
+class ChangeSetTest {
   void test_changedContent() {
     TestSource source = new TestSource();
     String content = "";
@@ -157,13 +156,12 @@
   }
 
   test_enclosingElement_invalidLocalFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C() {
     int get x => 0;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
       ParserErrorCode.EXPECTED_TOKEN
@@ -189,7 +187,7 @@
     // therefore discard the propagated type.
     //
     // So this test does not use strong mode.
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 abstract class Iter {
   List<S> map<S>(S f(x));
 }
@@ -867,7 +865,7 @@
 }
 
 @reflectiveTest
-class TypePropagationTest extends ResolverTestCase {
+class TypePropagationTest extends DriverResolutionTest {
   test_assignment_null() async {
     String code = r'''
 main() {
@@ -875,144 +873,73 @@
   v = null;
   return v; // return
 }''';
-    CompilationUnit unit;
-    {
-      Source source = addSource(code);
-      TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-      assertNoErrors(source);
-      verify([source]);
-      unit = analysisResult.unit;
-    }
-    {
-      SimpleIdentifier identifier = EngineTestCase.findNode(
-          unit, code, "v; // declare", (node) => node is SimpleIdentifier);
-      expect(identifier.staticType, typeProvider.intType);
-    }
-    {
-      SimpleIdentifier identifier = EngineTestCase.findNode(
-          unit, code, "v = null;", (node) => node is SimpleIdentifier);
-      expect(identifier.staticType, typeProvider.intType);
-    }
-    {
-      SimpleIdentifier identifier = EngineTestCase.findNode(
-          unit, code, "v; // return", (node) => node is SimpleIdentifier);
-      expect(identifier.staticType, typeProvider.intType);
-    }
+    await resolveTestCode(code);
+    assertType(findNode.simple('v; // declare'), 'int');
+    assertType(findNode.simple('v = null;'), 'int');
+    assertType(findNode.simple('v; // return'), 'int');
   }
 
   test_functionExpression_asInvocationArgument_notSubtypeOfStaticType() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A {
   m(void f(int i)) {}
 }
 x() {
   A a = new A();
   a.m(() => 0);
-}''';
-    Source source = addSource(code);
-    CompilationUnit unit = await _computeResolvedUnit(source, noErrors: false);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    // () => 0
-    FunctionExpression functionExpression = EngineTestCase.findNode(
-        unit, code, "() => 0)", (node) => node is FunctionExpression);
-    expect((functionExpression.staticType as FunctionType).parameters.length,
-        same(0));
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 63, 7),
+    ]);
+    assertType(findNode.functionExpression('() => 0'), 'int Function()');
   }
 
   test_initializer_hasStaticType() async {
-    Source source = addSource(r'''
+    await resolveTestCode(r'''
 f() {
   int v = 0;
   return v;
 }''');
-    CompilationUnit unit = await _computeResolvedUnit(source);
-    FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration;
-    BlockFunctionBody body =
-        function.functionExpression.body as BlockFunctionBody;
-    NodeList<Statement> statements = body.block.statements;
-    // Type of 'v' in declaration.
-    {
-      VariableDeclarationStatement statement =
-          statements[0] as VariableDeclarationStatement;
-      SimpleIdentifier variableName = statement.variables.variables[0].name;
-      expect(variableName.staticType, typeProvider.intType);
-    }
-    // Type of 'v' in reference.
-    {
-      ReturnStatement statement = statements[1] as ReturnStatement;
-      SimpleIdentifier variableName = statement.expression as SimpleIdentifier;
-      expect(variableName.staticType, typeProvider.intType);
-    }
+    assertType(findNode.simple('v = 0;'), 'int');
+    assertType(findNode.simple('v;'), 'int');
   }
 
   test_initializer_hasStaticType_parameterized() async {
-    Source source = addSource(r'''
+    await resolveTestCode(r'''
 f() {
   List<int> v = <int>[];
   return v;
 }''');
-    CompilationUnit unit = await _computeResolvedUnit(source);
-    FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration;
-    BlockFunctionBody body =
-        function.functionExpression.body as BlockFunctionBody;
-    NodeList<Statement> statements = body.block.statements;
-    // Type of 'v' in declaration.
-    {
-      VariableDeclarationStatement statement =
-          statements[0] as VariableDeclarationStatement;
-      SimpleIdentifier variableName = statement.variables.variables[0].name;
-      expect(variableName.staticType, isNotNull);
-    }
-    // Type of 'v' in reference.
-    {
-      ReturnStatement statement = statements[1] as ReturnStatement;
-      SimpleIdentifier variableName = statement.expression as SimpleIdentifier;
-      expect(variableName.staticType, isNotNull);
-    }
+    assertType(findNode.simple('v ='), 'List<int>');
+    assertType(findNode.simple('v;'), 'List<int>');
   }
 
   test_initializer_null() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   int v = null;
-  return v; // marker
-}''';
-    CompilationUnit unit;
-    {
-      Source source = addSource(code);
-      unit = await _computeResolvedUnit(source);
-    }
-    {
-      SimpleIdentifier identifier = EngineTestCase.findNode(
-          unit, code, "v = null;", (node) => node is SimpleIdentifier);
-      expect(identifier.staticType, typeProvider.intType);
-    }
-    {
-      SimpleIdentifier identifier = EngineTestCase.findNode(
-          unit, code, "v; // marker", (node) => node is SimpleIdentifier);
-      expect(identifier.staticType, typeProvider.intType);
-    }
+  return v;
+}''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v;'), 'int');
   }
 
   test_invocation_target_prefixed() async {
-    addNamedSource('/helper.dart', '''
-library helper;
+    newFile('/test/lib/a.dart', content: r'''
 int max(int x, int y) => 0;
 ''');
-    String code = '''
-import 'helper.dart' as helper;
+    await resolveTestCode('''
+import 'a.dart' as helper;
 main() {
   helper.max(10, 10); // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    SimpleIdentifier methodName =
-        findMarkedIdentifier(code, unit, "(10, 10); // marker");
-    MethodInvocation methodInvoke = methodName.parent;
-    expect(methodInvoke.methodName.staticElement, isNotNull);
+}''');
+    assertElement(
+      findNode.simple('max(10, 10)'),
+      findElement.importFind('package:test/a.dart').topFunction('max'),
+    );
   }
 
   test_is_subclass() async {
-    Source source = addSource(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   B m() => this;
@@ -1023,20 +950,15 @@
   }
   return p;
 }''');
-    CompilationUnit unit = await _computeResolvedUnit(source);
-    FunctionDeclaration function = unit.declarations[2] as FunctionDeclaration;
-    BlockFunctionBody body =
-        function.functionExpression.body as BlockFunctionBody;
-    IfStatement ifStatement = body.block.statements[0] as IfStatement;
-    ReturnStatement statement =
-        (ifStatement.thenStatement as Block).statements[0] as ReturnStatement;
-    MethodInvocation invocation = statement.expression as MethodInvocation;
-    expect(invocation.methodName.staticElement, isNotNull);
+    assertElement(
+      findNode.methodInvocation('p.m()'),
+      findElement.method('m', of: 'B'),
+    );
   }
 
   test_mutatedOutsideScope() async {
     // https://code.google.com/p/dart/issues/detail?id=22732
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class Base {
 }
 
@@ -1061,104 +983,59 @@
   }
   x = null;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_objectAccessInference_disabled_for_library_prefix() async {
-    String name = 'hashCode';
-    addNamedSource('/helper.dart', '''
-library helper;
-dynamic get $name => 42;
+    newFile('/test/lib/a.dart', content: '''
+dynamic get hashCode => 42;
 ''');
-    String code = '''
-import 'helper.dart' as helper;
+    await assertNoErrorsInCode('''
+import 'a.dart' as helper;
 main() {
-  helper.$name; // marker
-}''';
-
-    CompilationUnit unit = await resolveSource(code);
-    SimpleIdentifier id = findMarkedIdentifier(code, unit, "; // marker");
-    PrefixedIdentifier prefixedId = id.parent;
-    expect(id.staticType, typeProvider.dynamicType);
-    expect(prefixedId.staticType, typeProvider.dynamicType);
+  helper.hashCode;
+}''');
+    assertTypeDynamic(findNode.prefixed('helper.hashCode'));
   }
 
   test_objectAccessInference_disabled_for_local_getter() async {
-    String name = 'hashCode';
-    String code = '''
-dynamic get $name => null;
+    await assertNoErrorsInCode('''
+dynamic get hashCode => null;
 main() {
-  $name; // marker
-}''';
-
-    CompilationUnit unit = await resolveSource(code);
-    SimpleIdentifier getter = findMarkedIdentifier(code, unit, "; // marker");
-    expect(getter.staticType, typeProvider.dynamicType);
+  hashCode; // marker
+}''');
+    assertTypeDynamic(findNode.simple('hashCode; // marker'));
   }
 
   test_objectMethodInference_disabled_for_library_prefix() async {
-    String name = 'toString';
-    addNamedSource('/helper.dart', '''
-library helper;
+    newFile('/test/lib/a.dart', content: '''
 dynamic toString = (int x) => x + 42;
 ''');
-    String code = '''
-import 'helper.dart' as helper;
+    await assertNoErrorsInCode('''
+import 'a.dart' as helper;
 main() {
-  helper.$name(); // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    SimpleIdentifier methodName =
-        findMarkedIdentifier(code, unit, "(); // marker");
-    MethodInvocation methodInvoke = methodName.parent;
-    expect(methodName.staticType, typeProvider.dynamicType);
-    expect(methodInvoke.staticType, typeProvider.dynamicType);
+  helper.toString();
+}''');
+    assertTypeDynamic(findNode.methodInvocation('helper.toString()'));
   }
 
   test_objectMethodInference_disabled_for_local_function() async {
-    String name = 'toString';
-    String code = '''
+    await resolveTestCode('''
 main() {
-  dynamic $name = () => null;
-  $name(); // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-
-    SimpleIdentifier identifier = findMarkedIdentifier(code, unit, "$name = ");
-    expect(identifier.staticType, typeProvider.dynamicType);
-
-    SimpleIdentifier methodName =
-        findMarkedIdentifier(code, unit, "(); // marker");
-    MethodInvocation methodInvoke = methodName.parent;
-    expect(methodName.staticType, typeProvider.dynamicType);
-    expect(methodInvoke.staticType, typeProvider.dynamicType);
+  dynamic toString = () => null;
+  toString(); // marker
+}''');
+    assertTypeDynamic(findNode.simple('toString ='));
+    assertTypeDynamic(findNode.simple('toString(); // marker'));
   }
 
   @failingTest
   test_propagatedReturnType_functionExpression() async {
     // TODO(scheglov) disabled because we don't resolve function expression
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var v = (() {return 42;})();
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.dynamicType);
-  }
-
-  /**
-   * Return the resolved unit for the given [source].
-   *
-   * If [noErrors] is not specified or is not `true`, [assertNoErrors].
-   */
-  Future<CompilationUnit> _computeResolvedUnit(Source source,
-      {bool noErrors: true}) async {
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    if (noErrors) {
-      assertNoErrors(source);
-      verify([source]);
-    }
-    return analysisResult.unit;
+}''');
+    assertTypeDynamic(findNode.simple('v = '));
   }
 }
 
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index aa995d1..cc089a6 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -32,6 +32,7 @@
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 
+import '../src/dart/resolution/driver_resolution.dart';
 import 'test_analysis_context.dart';
 import 'test_support.dart';
 
@@ -308,7 +309,7 @@
   }
 }
 
-class ResolverTestCase extends EngineTestCase with ResourceProviderMixin {
+class ResolverTestCase with ResourceProviderMixin {
   /**
    * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and
    * [HintCode.UNUSED_FIELD].
@@ -384,16 +385,6 @@
       addNamedSource(_defaultSourceName, contents);
 
   /**
-   * The [code] that assigns the value to the variable "v", no matter how. We
-   * check that "v" has expected static type.
-   */
-  void assertAssignedType(
-      String code, CompilationUnit unit, DartType expectedStaticType) {
-    SimpleIdentifier identifier = findMarkedIdentifier(code, unit, "v = ");
-    expect(identifier.staticType, expectedStaticType);
-  }
-
-  /**
    * Assert that the number of errors reported against the given
    * [source] matches the number of errors that are given and that they have
    * the expected error codes. The order in which the errors were gathered is
@@ -474,26 +465,6 @@
     verify([source]);
   }
 
-  /**
-   * The [code] that iterates using variable "v". We check that "v" has expected
-   * static type.
-   */
-  void assertPropagatedIterationType(
-      String code, CompilationUnit unit, DartType expectedStaticType) {
-    SimpleIdentifier identifier = findMarkedIdentifier(code, unit, "v in ");
-    expect(identifier.staticType, expectedStaticType);
-  }
-
-  /**
-   * Check the static type of the expression marked with "; // marker" comment.
-   */
-  void assertTypeOfMarkedExpression(
-      String code, CompilationUnit unit, DartType expectedStaticType) {
-    SimpleIdentifier identifier =
-        findMarkedIdentifier(code, unit, "; // marker");
-    expect(identifier.staticType, expectedStaticType);
-  }
-
   Future<TestAnalysisResult> computeAnalysisResult(Source source) async {
     TestAnalysisResult analysisResult;
     ResolvedUnitResult result = await driver.getResult(source.fullName);
@@ -573,16 +544,6 @@
     return library;
   }
 
-  /**
-   * Return the [SimpleIdentifier] from [unit] marked by [marker] in [code].
-   * The source code must have no errors and be verifiable.
-   */
-  SimpleIdentifier findMarkedIdentifier(
-      String code, CompilationUnit unit, String marker) {
-    return EngineTestCase.findNode(
-        unit, code, marker, (node) => node is SimpleIdentifier);
-  }
-
   Expression findTopLevelConstantExpression(
           CompilationUnit compilationUnit, String name) =>
       findTopLevelDeclaration(compilationUnit, name).initializer;
@@ -706,17 +667,13 @@
     verify([source]);
   }
 
-  @override
   void setUp() {
     ElementFactory.flushStaticState();
-    super.setUp();
     reset();
   }
 
-  @override
   void tearDown() {
     AnalysisEngine.instance.clearCaches();
-    super.tearDown();
   }
 
   /**
@@ -738,11 +695,7 @@
  * Shared infrastructure for [StaticTypeAnalyzer2Test] and
  * [StrongModeStaticTypeAnalyzer2Test].
  */
-class StaticTypeAnalyzer2TestShared extends ResolverTestCase {
-  String testCode;
-  Source testSource;
-  CompilationUnit testUnit;
-
+class StaticTypeAnalyzer2TestShared extends DriverResolutionTest {
   /**
    * Find the expression that starts at the offset of [search] and validate its
    * that its static type matches the given [type].
@@ -752,7 +705,7 @@
    * to match the type.
    */
   void expectExpressionType(String search, type) {
-    Expression expression = findExpression(search);
+    Expression expression = findNode.expression(search);
     _expectType(expression.staticType, type);
   }
 
@@ -778,7 +731,7 @@
       fail('Wrong element type: ${element.runtimeType}');
     }
 
-    SimpleIdentifier identifier = findIdentifier(name);
+    SimpleIdentifier identifier = findNode.simple(name);
     // Element is either ExecutableElement or ParameterElement.
     var element = identifier.staticElement;
     FunctionTypeImpl functionType = (element as dynamic).type;
@@ -797,7 +750,7 @@
    * output.
    */
   FunctionTypeImpl expectFunctionType2(String name, String type) {
-    SimpleIdentifier identifier = findIdentifier(name);
+    SimpleIdentifier identifier = findNode.simple(name);
     FunctionTypeImpl functionType = identifier.staticType;
     expect('$functionType', type);
     return functionType;
@@ -811,7 +764,7 @@
    * to match the type.
    */
   void expectIdentifierType(String name, type) {
-    SimpleIdentifier identifier = findIdentifier(name);
+    SimpleIdentifier identifier = findNode.simple(name);
     _expectType(identifier.staticType, type);
   }
 
@@ -824,34 +777,13 @@
    * to match the type.
    */
   void expectInitializerType(String name, type) {
-    SimpleIdentifier identifier = findIdentifier(name);
+    SimpleIdentifier identifier = findNode.simple(name);
     VariableDeclaration declaration =
         identifier.thisOrAncestorOfType<VariableDeclaration>();
     Expression initializer = declaration.initializer;
     _expectType(initializer.staticType, type);
   }
 
-  Expression findExpression(String search) {
-    return EngineTestCase.findNode(
-        testUnit, testCode, search, (node) => node is Expression);
-  }
-
-  SimpleIdentifier findIdentifier(String search) {
-    return EngineTestCase.findNode(
-        testUnit, testCode, search, (node) => node is SimpleIdentifier);
-  }
-
-  Future<void> resolveTestUnit(String code, {bool noErrors: true}) async {
-    testCode = code;
-    testSource = addSource(testCode);
-    TestAnalysisResult analysisResult = await computeAnalysisResult(testSource);
-    if (noErrors) {
-      assertNoErrors(testSource);
-    }
-    verify([testSource]);
-    testUnit = analysisResult.unit;
-  }
-
   /**
    * Validates that [type] matches [expected].
    *
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 5470859..1ff1558 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -21,7 +21,7 @@
   });
 }
 
-class CharacterRangeReaderTest extends EngineTestCase {
+class CharacterRangeReaderTest {
   void test_advance() {
     CharSequenceReader baseReader = new CharSequenceReader("xyzzy");
     CharacterRangeReader reader = new CharacterRangeReader(baseReader, 1, 4);
@@ -78,7 +78,7 @@
 }
 
 @reflectiveTest
-class LineInfoTest extends EngineTestCase {
+class LineInfoTest {
   final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
 
   void test_lineInfo_multilineComment() {
diff --git a/pkg/analyzer/test/generated/sdk_test.dart b/pkg/analyzer/test/generated/sdk_test.dart
index 6dae63b..e62602f 100644
--- a/pkg/analyzer/test/generated/sdk_test.dart
+++ b/pkg/analyzer/test/generated/sdk_test.dart
@@ -9,8 +9,6 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'test_support.dart';
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DartSdkManagerTest);
@@ -19,7 +17,7 @@
 }
 
 @reflectiveTest
-class DartSdkManagerTest extends EngineTestCase with ResourceProviderMixin {
+class DartSdkManagerTest with ResourceProviderMixin {
   void test_anySdk() {
     DartSdkManager manager = new DartSdkManager('/a/b/c', false);
     expect(manager.anySdk, isNull);
@@ -63,7 +61,7 @@
 }
 
 @reflectiveTest
-class SdkDescriptionTest extends EngineTestCase {
+class SdkDescriptionTest {
   void test_equals_differentPaths_nested() {
     AnalysisOptions options = new AnalysisOptionsImpl();
     SdkDescription left = new SdkDescription(<String>['/a/b/c'], options);
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index de35b72..7df3a66 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -20,7 +20,7 @@
 @reflectiveTest
 class SimpleResolverTest extends DriverResolutionTest {
   test_argumentResolution_required_matching() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2, 3);
@@ -31,7 +31,7 @@
   }
 
   test_argumentResolution_required_tooFew() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2);
@@ -42,7 +42,7 @@
   }
 
   test_argumentResolution_required_tooMany() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2, 3);
@@ -53,7 +53,7 @@
   }
 
   test_argumentResolution_requiredAndNamed_extra() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void f() {
     g(1, 2, c: 3, d: 4);
@@ -64,7 +64,7 @@
   }
 
   test_argumentResolution_requiredAndNamed_matching() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2, c: 3);
@@ -75,7 +75,7 @@
   }
 
   test_argumentResolution_requiredAndNamed_missing() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void f() {
     g(1, 2, d: 3);
@@ -86,7 +86,7 @@
   }
 
   test_argumentResolution_requiredAndPositional_fewer() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void f() {
     g(1, 2, 3);
@@ -97,7 +97,7 @@
   }
 
   test_argumentResolution_requiredAndPositional_matching() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2, 3, 4);
@@ -108,7 +108,7 @@
   }
 
   test_argumentResolution_requiredAndPositional_more() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void f() {
     g(1, 2, 3, 4);
@@ -119,7 +119,7 @@
   }
 
   test_argumentResolution_setter_propagated() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var a = new A();
   a.sss = 0;
@@ -127,8 +127,6 @@
 class A {
   set sss(x) {}
 }''');
-    await resolveTestFile();
-
     var rhs = findNode.assignment(' = 0;').rightHandSide;
     expect(
       rhs.staticParameterElement,
@@ -137,7 +135,7 @@
   }
 
   test_argumentResolution_setter_propagated_propertyAccess() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var a = new A();
   a.b.sss = 0;
@@ -148,8 +146,6 @@
 class B {
   set sss(x) {}
 }''');
-    await resolveTestFile();
-
     var rhs = findNode.assignment(' = 0;').rightHandSide;
     expect(
       rhs.staticParameterElement,
@@ -158,7 +154,7 @@
   }
 
   test_argumentResolution_setter_static() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   A a = new A();
   a.sss = 0;
@@ -166,8 +162,6 @@
 class A {
   set sss(x) {}
 }''');
-    await resolveTestFile();
-
     var rhs = findNode.assignment(' = 0;').rightHandSide;
     expect(
       rhs.staticParameterElement,
@@ -176,7 +170,7 @@
   }
 
   test_argumentResolution_setter_static_propertyAccess() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   A a = new A();
   a.b.sss = 0;
@@ -187,8 +181,6 @@
 class B {
   set sss(x) {}
 }''');
-    await resolveTestFile();
-
     var rhs = findNode.assignment(' = 0;').rightHandSide;
     expect(
       rhs.staticParameterElement,
@@ -199,7 +191,7 @@
   test_breakTarget_labeled() async {
     // Verify that the target of the label is correctly found and is recorded
     // as the unlabeled portion of the statement.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   loop1: while (true) {
     loop2: for (int i = 0; i < 10; i++) {
@@ -209,8 +201,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var break1 = findNode.breakStatement('break loop1;');
     var whileStatement = findNode.whileStatement('while (');
     expect(break1.target, same(whileStatement));
@@ -221,52 +211,46 @@
   }
 
   test_breakTarget_unlabeledBreakFromDo() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   do {
     break;
   } while (true);
 }
 ''');
-    await resolveTestFile();
-
     var doStatement = findNode.doStatement('do {');
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(doStatement));
   }
 
   test_breakTarget_unlabeledBreakFromFor() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   for (int i = 0; i < 10; i++) {
     break;
   }
 }
 ''');
-    await resolveTestFile();
-
     var forStatement = findNode.forStatement('for (');
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(forStatement));
   }
 
   test_breakTarget_unlabeledBreakFromForEach() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   for (x in []) {
     break;
   }
 }
 ''');
-    await resolveTestFile();
-
     var forStatement = findNode.forStatement('for (');
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(forStatement));
   }
 
   test_breakTarget_unlabeledBreakFromSwitch() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     switch (0) {
@@ -276,23 +260,19 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var switchStatement = findNode.switchStatement('switch (');
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(switchStatement));
   }
 
   test_breakTarget_unlabeledBreakFromWhile() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     break;
   }
 }
 ''');
-    await resolveTestFile();
-
     var whileStatement = findNode.whileStatement('while (');
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(whileStatement));
@@ -301,7 +281,7 @@
   test_breakTarget_unlabeledBreakToOuterFunction() async {
     // Verify that unlabeled break statements can't resolve to loops in an
     // outer function.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     void g() {
@@ -310,8 +290,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, isNull);
   }
@@ -336,7 +314,7 @@
   test_continueTarget_labeled() async {
     // Verify that the target of the label is correctly found and is recorded
     // as the unlabeled portion of the statement.
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   loop1: while (true) {
     loop2: for (int i = 0; i < 10; i++) {
@@ -346,8 +324,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var continue1 = findNode.continueStatement('continue loop1');
     var whileStatement = findNode.whileStatement('while (');
     expect(continue1.target, same(whileStatement));
@@ -358,67 +334,59 @@
   }
 
   test_continueTarget_unlabeledContinueFromDo() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   do {
     continue;
   } while (true);
 }
 ''');
-    await resolveTestFile();
-
     var doStatement = findNode.doStatement('do {');
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(doStatement));
   }
 
   test_continueTarget_unlabeledContinueFromFor() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   for (int i = 0; i < 10; i++) {
     continue;
   }
 }
 ''');
-    await resolveTestFile();
-
     var forStatement = findNode.forStatement('for (');
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(forStatement));
   }
 
   test_continueTarget_unlabeledContinueFromForEach() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   for (x in []) {
     continue;
   }
 }
 ''');
-    await resolveTestFile();
-
     var forStatement = findNode.forStatement('for (');
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(forStatement));
   }
 
   test_continueTarget_unlabeledContinueFromWhile() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     continue;
   }
 }
 ''');
-    await resolveTestFile();
-
     var whileStatement = findNode.whileStatement('while (');
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(whileStatement));
   }
 
   test_continueTarget_unlabeledContinueSkipsSwitch() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     switch (0) {
@@ -428,8 +396,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var whileStatement = findNode.whileStatement('while (');
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(whileStatement));
@@ -438,7 +404,7 @@
   test_continueTarget_unlabeledContinueToOuterFunction() async {
     // Verify that unlabeled continue statements can't resolve to loops in an
     // outer function.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {
   while (true) {
     void g() {
@@ -447,15 +413,12 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, isNull);
   }
 
   test_empty() async {
-    addTestFile('');
-    await resolveTestFile();
+    await resolveTestCode('');
     assertNoTestErrors();
   }
 
@@ -464,10 +427,9 @@
 main() {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 export 'a.dart';
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var library = result.libraryElement;
@@ -478,10 +440,9 @@
   }
 
   test_entryPoint_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var library = result.libraryElement;
@@ -492,8 +453,7 @@
   }
 
   test_entryPoint_none() async {
-    addTestFile('');
-    await resolveTestFile();
+    await resolveTestCode('');
     assertNoTestErrors();
 
     var library = result.libraryElement;
@@ -504,12 +464,11 @@
     newFile('/test/lib/a.dart', content: r'''
 enum EEE {A, B, C}
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 void f(EEE e) {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
@@ -527,13 +486,12 @@
   }
 
   test_fieldFormalParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int x;
   int y;
   A(this.x) : y = x {}
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -583,7 +541,7 @@
   }
 
   test_getter_and_setter_fromMixins_bare_identifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   get x => null;
@@ -599,7 +557,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -621,7 +578,7 @@
     // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
     // a SimpleIdentifier that's inside a property access.  This bug should be
     // fixed.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class B {}
 class M1 {
   get x => null;
@@ -653,7 +610,7 @@
   }
 
   test_getter_fromMixins_bare_identifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   get x => null;
@@ -667,7 +624,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -680,7 +636,7 @@
   }
 
   test_getter_fromMixins_property_access() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   get x => null;
@@ -693,7 +649,6 @@
   var y = new C().x;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -706,7 +661,7 @@
   }
 
   test_getterAndSetterWithDifferentTypes() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get f => 0;
   void set f(String s) {}
@@ -714,17 +669,15 @@
 g (A a) {
   a.f = a.f.toString();
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
     verifyTestResolved();
   }
 
   test_hasReferenceToSuper() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B {toString() => super.toString();}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -743,7 +696,7 @@
     newFile('/test/lib/lib2.dart', content: r'''
 set foo(value) {}''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'lib1.dart' hide foo;
 import 'lib2.dart';
 
@@ -751,7 +704,6 @@
   foo = 0;
 }
 A a;''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
@@ -762,12 +714,11 @@
   return x * x;
 }''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as _a;
 main() {
   _a.f(0);
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
@@ -778,7 +729,7 @@
     // single error generated when the only problem is that an imported file
     // does not exist.
     //
-    addTestFile('''
+    await resolveTestCode('''
 import 'missing.dart' as p;
 int a = p.q + p.r.s;
 String b = p.t(a) + p.u(v: 0);
@@ -795,7 +746,6 @@
   H(int i) : super(i);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
     verifyTestResolved();
   }
@@ -806,7 +756,7 @@
     // single error generated when the only problem is that an imported file
     // does not exist.
     //
-    addTestFile('''
+    await resolveTestCode('''
 import 'missing.dart' show q, r, t, u, T, U, V, W;
 int a = q + r.s;
 String b = t(a) + u(v: 0);
@@ -823,7 +773,6 @@
   H(int i) : super(i);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
     verifyTestResolved();
   }
@@ -857,12 +806,11 @@
   }
 
   test_indexExpression_typeParameters_invalidAssignmentWarning() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 f() {
   List<List<int>> b;
   b[0][0] = 'hi';
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verifyTestResolved();
   }
@@ -899,11 +847,10 @@
   }
 
   test_isValidMixin_badSuperclass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A extends B {}
 class B {}
 class C = Object with A;''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verifyTestResolved();
@@ -913,12 +860,11 @@
   }
 
   test_isValidMixin_constructor() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A() {}
 }
 class C = Object with A;''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
     );
@@ -929,12 +875,11 @@
   }
 
   test_isValidMixin_factoryConstructor() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   factory A() => null;
 }
 class C = Object with A;''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -943,14 +888,13 @@
   }
 
   test_isValidMixin_super() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   toString() {
     return super.toString();
   }
 }
 class C = Object with A;''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
     verifyTestResolved();
 
@@ -984,23 +928,20 @@
   }
 
   test_localVariable_types_invoked() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 main() {
   var myVar = (int p) => 'foo';
   myVar(42);
 }''');
-    await resolveTestFile();
-
     var node = findNode.simple('myVar(42)');
     assertType(node, 'String Function(int)');
   }
 
   test_metadata_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 @A class C<A> {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1015,12 +956,11 @@
   }
 
   test_metadata_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 class C {
   @A int f;
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1029,13 +969,12 @@
   }
 
   test_metadata_fieldFormalParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 class C {
   int f;
   C(@A this.f);
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1044,10 +983,9 @@
   }
 
   test_metadata_function() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 @A f() {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1056,10 +994,9 @@
   }
 
   test_metadata_functionTypedParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 f(@A int p(int x)) {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1068,10 +1005,9 @@
   }
 
   test_metadata_libraryDirective() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 @A library lib;
 const A = null;''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1080,12 +1016,11 @@
   }
 
   test_metadata_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 class C {
   @A void m() {}
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1094,10 +1029,9 @@
   }
 
   test_metadata_namedParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 f({@A int p : 0}) {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1106,10 +1040,9 @@
   }
 
   test_metadata_positionalParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 f([@A int p = 0]) {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1118,10 +1051,9 @@
   }
 
   test_metadata_simpleParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 f(@A p1, @A int p2) {}''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1130,10 +1062,9 @@
   }
 
   test_metadata_typedef() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const A = null;
 @A typedef F<A>();''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1147,7 +1078,7 @@
   }
 
   test_method_fromMixin() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class B {
   bar() => 1;
 }
@@ -1159,13 +1090,12 @@
   bar() => super.bar();
   foo() => super.foo();
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_method_fromMixins() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   void f() {}
@@ -1178,7 +1108,6 @@
   new C().f();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1189,7 +1118,7 @@
   }
 
   test_method_fromMixins_bare_identifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   void f() {}
@@ -1203,7 +1132,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1214,7 +1142,7 @@
   }
 
   test_method_fromMixins_invoked_from_outside_class() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   void f() {}
@@ -1227,7 +1155,6 @@
   new C().f();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1238,7 +1165,7 @@
   }
 
   test_method_fromSuperclassMixin() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void m1() {}
 }
@@ -1249,13 +1176,12 @@
 f(C c) {
   c.m1();
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_methodCascades() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void m1() {}
   void m2() {}
@@ -1265,13 +1191,12 @@
      ..m2();
   }
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_methodCascades_withSetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   String name;
   void m1() {}
@@ -1283,23 +1208,21 @@
      ..m2();
   }
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_resolveAgainstNull() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 f(var p) {
   return null == p;
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_setter_fromMixins_bare_identifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   set x(value) {}
@@ -1313,7 +1236,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1324,7 +1246,7 @@
   }
 
   test_setter_fromMixins_property_access() async {
-    addTestFile('''
+    await resolveTestCode('''
 class B {}
 class M1 {
   set x(value) {}
@@ -1337,7 +1259,6 @@
   new C().x = 1;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
 
@@ -1348,7 +1269,7 @@
   }
 
   test_setter_inherited() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get x => 0;
   set x(int p) {}
@@ -1357,20 +1278,18 @@
   int get x => super.x == null ? 0 : super.x;
   int f() => x = 1;
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
 
   test_setter_static() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 set s(x) {
 }
 
 main() {
   s = 123;
 }''');
-    await resolveTestFile();
     assertNoTestErrors();
     verifyTestResolved();
   }
@@ -1404,8 +1323,6 @@
    *           valid
    */
   Future<void> _validateArgumentResolution(List<int> indices) async {
-    await resolveTestFile();
-
     var g = findElement.method('g');
     var parameters = g.parameters;
 
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index c9246a0..abfd5fc 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -53,14 +53,13 @@
 @reflectiveTest
 class SetLiteralsTest extends StaticTypeAnalyzer2TestShared {
   test_emptySetLiteral_parameter_typed() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   useSet({});
 }
 void useSet(Set<int> s) {
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectExpressionType('{}', 'Set<int>');
   }
 }
@@ -71,90 +70,83 @@
 @reflectiveTest
 class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
   test_FunctionExpressionInvocation_block() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var foo = (() { return 1; })();
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   test_FunctionExpressionInvocation_curried() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 typedef int F();
 F f() => null;
 main() {
   var foo = f()();
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   test_FunctionExpressionInvocation_expression() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var foo = (() => 1)();
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   test_MethodInvocation_nameType_localVariable() async {
-    String code = r"""
+    await assertNoErrorsInCode(r"""
 typedef Foo();
 main() {
   Foo foo;
   foo();
 }
-""";
-    await resolveTestUnit(code);
+""");
     // "foo" should be resolved to the "Foo" type
     expectIdentifierType("foo();", new TypeMatcher<FunctionType>());
   }
 
   test_MethodInvocation_nameType_parameter_FunctionTypeAlias() async {
-    String code = r"""
+    await assertNoErrorsInCode(r"""
 typedef Foo();
 main(Foo foo) {
   foo();
 }
-""";
-    await resolveTestUnit(code);
+""");
     // "foo" should be resolved to the "Foo" type
     expectIdentifierType("foo();", new TypeMatcher<FunctionType>());
   }
 
   test_MethodInvocation_nameType_parameter_propagatedType() async {
-    String code = r"""
+    await assertNoErrorsInCode(r"""
 typedef Foo();
 main(p) {
   if (p is Foo) {
     p();
   }
 }
-""";
-    await resolveTestUnit(code);
+""");
     expectIdentifierType("p()", 'dynamic Function()');
   }
 
   test_staticMethods_classTypeParameters() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   static void m() => null;
 }
 main() {
   print(C.m);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectFunctionType('m);', 'void Function()');
   }
 
   test_staticMethods_classTypeParameters_genericMethod() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   static void m<S>(S s) {
     void f<U>(S s, U u) {}
@@ -164,8 +156,7 @@
 main() {
   print(C.m);
 }
-''';
-    await resolveTestUnit(code);
+''');
     // C - m
     TypeParameterType typeS;
     {
@@ -208,31 +199,28 @@
 @reflectiveTest
 class StaticTypeAnalyzer3Test extends StaticTypeAnalyzer2TestShared {
   test_emptyMapLiteral_initializer_var() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var v = {};
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectExpressionType('{}', 'Map<dynamic, dynamic>');
   }
 
   test_emptyMapLiteral_parameter_typed() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   useMap({});
 }
 void useMap(Map<int, int> m) {
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectExpressionType('{}', 'Map<int, int>');
   }
 }
 
 @reflectiveTest
-class StaticTypeAnalyzerTest extends EngineTestCase
-    with ResourceProviderMixin, ElementsTypesMixin {
+class StaticTypeAnalyzerTest with ResourceProviderMixin, ElementsTypesMixin {
   /**
    * The error listener to which errors will be reported.
    */
@@ -275,9 +263,7 @@
     _listener.assertNoErrors();
   }
 
-  @override
   void setUp() {
-    super.setUp();
     _listener = new GatheringErrorListener();
     _analyzer = _createAnalyzer();
   }
@@ -519,7 +505,7 @@
     // 1 + 2.0
     BinaryExpression node = AstTestFactory.binaryExpression(
         _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0));
-    node.staticElement = getMethod(_typeProvider.numType, "+");
+    node.staticElement = _typeProvider.numType.getMethod('+');
     expect(_analyze(node), same(_typeProvider.doubleType));
     _listener.assertNoErrors();
   }
@@ -528,7 +514,7 @@
     // 1 + 2
     BinaryExpression node = AstTestFactory.binaryExpression(
         _resolvedInteger(1), TokenType.PLUS, _resolvedInteger(2));
-    node.staticElement = getMethod(_typeProvider.numType, "+");
+    node.staticElement = _typeProvider.numType.getMethod('+');
     expect(_analyze(node), same(_typeProvider.intType));
     _listener.assertNoErrors();
   }
@@ -537,7 +523,7 @@
     // 2 / 2
     BinaryExpressionImpl node = AstTestFactory.binaryExpression(
         _resolvedInteger(2), TokenType.SLASH, _resolvedInteger(2));
-    node.staticElement = getMethod(_typeProvider.numType, "/");
+    node.staticElement = _typeProvider.numType.getMethod('/');
     node.staticInvokeType = node.staticElement.type;
     expect(_analyze(node), _typeProvider.doubleType);
     _listener.assertNoErrors();
@@ -570,7 +556,7 @@
     // 1 * 2.0
     BinaryExpression node = AstTestFactory.binaryExpression(
         _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0));
-    node.staticElement = getMethod(_typeProvider.numType, "*");
+    node.staticElement = _typeProvider.numType.getMethod('*');
     expect(_analyze(node), same(_typeProvider.doubleType));
     _listener.assertNoErrors();
   }
@@ -1122,7 +1108,7 @@
     // -0
     PrefixExpression node =
         AstTestFactory.prefixExpression(TokenType.MINUS, _resolvedInteger(0));
-    MethodElement minusMethod = getMethod(_typeProvider.numType, "-");
+    MethodElement minusMethod = _typeProvider.numType.getMethod('-');
     node.staticElement = minusMethod;
     expect(_analyze(node), _typeProvider.numType);
     _listener.assertNoErrors();
@@ -1132,7 +1118,7 @@
     // --0
     PrefixExpression node = AstTestFactory.prefixExpression(
         TokenType.MINUS_MINUS, _resolvedInteger(0));
-    MethodElement minusMethod = getMethod(_typeProvider.numType, "-");
+    MethodElement minusMethod = _typeProvider.numType.getMethod('-');
     node.staticElement = minusMethod;
     expect(_analyze(node), same(_typeProvider.intType));
     _listener.assertNoErrors();
@@ -1150,7 +1136,7 @@
     // ++0
     PrefixExpression node = AstTestFactory.prefixExpression(
         TokenType.PLUS_PLUS, _resolvedInteger(0));
-    MethodElement plusMethod = getMethod(_typeProvider.numType, "+");
+    MethodElement plusMethod = _typeProvider.numType.getMethod('+');
     node.staticElement = plusMethod;
     expect(_analyze(node), same(_typeProvider.intType));
     _listener.assertNoErrors();
@@ -1160,7 +1146,7 @@
     // ~0
     PrefixExpression node =
         AstTestFactory.prefixExpression(TokenType.TILDE, _resolvedInteger(0));
-    MethodElement tildeMethod = getMethod(_typeProvider.intType, "~");
+    MethodElement tildeMethod = _typeProvider.intType.getMethod('~');
     node.staticElement = tildeMethod;
     expect(_analyze(node), _typeProvider.intType);
     _listener.assertNoErrors();
@@ -1490,20 +1476,19 @@
 class StaticTypeAnalyzerWithSetLiteralsTest
     extends StaticTypeAnalyzer2TestShared {
   test_emptySetLiteral_inferredFromLinkedHashSet() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 import 'dart:collection';
 LinkedHashSet<int> test4() => {};
-''';
-    await resolveTestUnit(code, noErrors: false);
+''', [
+      error(StrongModeCode.INVALID_CAST_LITERAL_SET, 56, 2),
+    ]);
     expectExpressionType('{}', 'Set<dynamic>');
-    await assertErrorsInCode(code, [StrongModeCode.INVALID_CAST_LITERAL_SET]);
   }
 
   test_emptySetLiteral_initializer_typed_nested() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 Set<Set<int>> ints = {{}};
-''';
-    await resolveTestUnit(code);
+''');
     expectExpressionType('{}', 'Set<int>');
     expectExpressionType('{{}}', 'Set<Set<int>>');
   }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index bac33e6..8557eb0 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -20,6 +20,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../src/dart/resolution/driver_resolution.dart';
 import '../utils.dart';
 import 'resolver_test_case.dart';
 
@@ -4134,16 +4135,10 @@
 @reflectiveTest
 class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
   void expectStaticInvokeType(String search, String type) {
-    var invocation = findIdentifier(search).parent as MethodInvocation;
+    var invocation = findNode.simple(search).parent as MethodInvocation;
     expect(invocation.staticInvokeType.toString(), type);
   }
 
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    resetWith(options: options);
-  }
-
   test_dynamicObjectGetter_hashCode() async {
     String code = r'''
 main() {
@@ -4151,7 +4146,7 @@
   var foo = a.hashCode;
 }
 ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
     expectInitializerType('foo', 'int');
   }
 
@@ -4161,7 +4156,7 @@
     import "dart:async";
     dynamic test(FutureOr<int> x) => (x is int) && (x.abs() == 0);
    ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
   }
 
   test_futureOr_promotion2() async {
@@ -4172,7 +4167,7 @@
     dynamic test(FutureOr<int> x) => (x is Future<int>) &&
                                      (x.then((x) => x) == null);
    ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
   }
 
   test_futureOr_promotion3() async {
@@ -4183,7 +4178,7 @@
     dynamic test<T extends num>(FutureOr<T> x) => (x is T) &&
                                                   (x.abs() == 0);
    ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
   }
 
   test_futureOr_promotion4() async {
@@ -4194,32 +4189,30 @@
     dynamic test<T extends num>(FutureOr<T> x) => (x is Future<T>) &&
                                                   (x.then((x) => x) == null);
    ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
   }
 
   test_generalizedVoid_assignToVoidOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void main() {
   void x;
   x = 42;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_genericFunction() async {
-    await resolveTestUnit(r'T f<T>(T x) => null;');
+    await assertNoErrorsInCode(r'T f<T>(T x) => null;');
     expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
-    SimpleIdentifier f = findIdentifier('f');
+    SimpleIdentifier f = findNode.simple('f');
     FunctionElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_bounds() async {
-    await resolveTestUnit(r'T f<T extends num>(T x) => null;');
+    await assertNoErrorsInCode(r'T f<T extends num>(T x) => null;');
     expectFunctionType('f', 'T Function<T extends num>(T)',
         elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
   }
@@ -4228,7 +4221,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void g(T f<T>(T x)) {}
 ''');
     var type = expectFunctionType2('f', 'T Function<T>(T)');
@@ -4237,14 +4230,14 @@
   }
 
   test_genericFunction_static() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   static T f<T>(T x) => null;
 }
 ''');
     expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
-    SimpleIdentifier f = findIdentifier('f');
+    SimpleIdentifier f = findNode.simple('f');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), 'String Function(String)');
@@ -4258,7 +4251,7 @@
 class C {
   static F f1;
   F f2;
-  void g(F f3) {
+  void g(F f3) { // C
     F f4;
     f0(3);
     f1(3);
@@ -4271,7 +4264,7 @@
 class D<S> {
   static F f1;
   F f2;
-  void g(F f3) {
+  void g(F f3) { // D
     F f4;
     f0(3);
     f1(3);
@@ -4281,11 +4274,10 @@
   }
 }
 ''';
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
 
     checkBody(String className) {
-      List<Statement> statements =
-          AstFinder.getStatementsInMethod(testUnit, className, "g");
+      var statements = findNode.block('{ // $className').statements;
 
       for (int i = 1; i <= 5; i++) {
         Expression exp = (statements[i] as ExpressionStatement).expression;
@@ -4299,13 +4291,13 @@
 
   test_genericFunction_upwardsAndDownwards() async {
     // Regression tests for https://github.com/dart-lang/sdk/issues/27586.
-    await resolveTestUnit(r'List<num> x = [1, 2];');
+    await assertNoErrorsInCode(r'List<num> x = [1, 2];');
     expectInitializerType('x', 'List<num>');
   }
 
   test_genericFunction_upwardsAndDownwards_Object() async {
     // Regression tests for https://github.com/dart-lang/sdk/issues/27625.
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 List<Object> aaa = [];
 List<Object> bbb = [1, 2, 3];
 List<Object> ccc = [null];
@@ -4320,7 +4312,7 @@
   }
 
   test_genericMethod() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   List<T> f<T>(E e) => null;
 }
@@ -4328,12 +4320,12 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', 'List<T> Function<T>(E)',
+    expectFunctionType('f<T>', 'List<T> Function<T>(E)',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
         typeFormals: '[T]');
-    SimpleIdentifier c = findIdentifier('cOfString');
+    SimpleIdentifier c = findNode.simple('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
     expect(ft.toString(), 'List<T> Function<T>(String)');
     ft = ft.instantiate([typeProvider.intType]);
@@ -4341,7 +4333,7 @@
   }
 
   test_genericMethod_explicitTypeParams() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   List<T> f<T>(E e) => null;
 }
@@ -4350,16 +4342,16 @@
   var x = cOfString.f<int>('hi');
 }
 ''');
-    MethodInvocation f = findIdentifier('f<int>').parent;
+    MethodInvocation f = findNode.simple('f<int>').parent;
     FunctionType ft = f.staticInvokeType;
     expect(ft.toString(), 'List<int> Function(String)');
 
-    SimpleIdentifier x = findIdentifier('x');
+    SimpleIdentifier x = findNode.simple('x');
     expect(x.staticType, typeProvider.listType2(typeProvider.intType));
   }
 
   test_genericMethod_functionExpressionInvocation_explicit() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(T e) => null;
   static T g<T>(T e) => null;
@@ -4396,7 +4388,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = (pf)<int>(3);
 }
@@ -4408,7 +4400,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = (pf)(3);
 }
@@ -4420,7 +4412,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(T e) => null;
   static T g<T>(T e) => null;
@@ -4454,7 +4446,7 @@
   }
 
   test_genericMethod_functionInvocation_explicit() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(T e) => null;
   static T g<T>(T e) => null;
@@ -4488,7 +4480,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = pf<int>(3);
 }
@@ -4500,7 +4492,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = pf(3);
 }
@@ -4509,7 +4501,7 @@
   }
 
   test_genericMethod_functionInvocation_inferred() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(T e) => null;
   static T g<T>(T e) => null;
@@ -4540,7 +4532,7 @@
   }
 
   test_genericMethod_functionTypedParameter() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   List<T> f<T>(T f(E e)) => null;
 }
@@ -4548,13 +4540,13 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', 'List<T> Function<T>(T Function(E))',
+    expectFunctionType('f<T>', 'List<T> Function<T>(T Function(E))',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
         typeFormals: '[T]');
 
-    SimpleIdentifier c = findIdentifier('cOfString');
+    SimpleIdentifier c = findNode.simple('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
     expect(ft.toString(), 'List<T> Function<T>(T Function(String))');
     ft = ft.instantiate([typeProvider.intType]);
@@ -4565,7 +4557,7 @@
     // TODO(paulberry): remove when dartbug.com/28515 fixed.
     if (!AnalysisDriver.useSummary2) return;
 
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 void test<S>(T pf<T>(T e)) {
   var paramTearOff = pf;
 }
@@ -4577,7 +4569,7 @@
     // Regression test for:
     // https://github.com/dart-lang/sdk/issues/25100#issuecomment-162047588
     // These should not cause any hints or warnings.
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class List<E> {
   T map<T>(T f(E e)) => null;
 }
@@ -4591,83 +4583,77 @@
     expectIdentifierType(
         'map((e) => 3);', 'T Function<T>(T Function(dynamic))');
 
-    MethodInvocation m1 = findIdentifier('map((e) => e);').parent;
+    MethodInvocation m1 = findNode.methodInvocation('map((e) => e);');
     expect(m1.staticInvokeType.toString(),
         'dynamic Function(dynamic Function(dynamic))');
-    MethodInvocation m2 = findIdentifier('map((e) => 3);').parent;
+    MethodInvocation m2 = findNode.methodInvocation('map((e) => 3);');
     expect(
         m2.staticInvokeType.toString(), 'int Function(int Function(dynamic))');
   }
 
   test_genericMethod_max_doubleDouble() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:math';
 main() {
   var foo = max(1.0, 2.0);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'double');
   }
 
   test_genericMethod_max_doubleDouble_prefixed() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:math' as math;
 main() {
   var foo = math.max(1.0, 2.0);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'double');
   }
 
   test_genericMethod_max_doubleInt() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:math';
 main() {
   var foo = max(1.0, 2);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'num');
   }
 
   test_genericMethod_max_intDouble() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:math';
 main() {
   var foo = max(1, 2.0);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'num');
   }
 
   test_genericMethod_max_intInt() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:math';
 main() {
   var foo = max(1, 2);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   test_genericMethod_nestedBound() async {
-    String code = r'''
+    // Just validate that there is no warning on the call to `.abs()`.
+    await assertNoErrorsInCode(r'''
 class Foo<T extends num> {
   void method<U extends T>(U u) {
     u.abs();
   }
 }
-''';
-    // Just validate that there is no warning on the call to `.abs()`.
-    await resolveTestUnit(code);
+''');
   }
 
   test_genericMethod_nestedCapture() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   T f<S>(S x) {
     new C<S>().f<int>(3);
@@ -4676,7 +4662,7 @@
   }
 }
 ''');
-    MethodInvocation f = findIdentifier('f<int>(3);').parent;
+    MethodInvocation f = findNode.methodInvocation('f<int>(3);');
     expect(f.staticInvokeType.toString(), 'S Function(int)');
 
     expectIdentifierType('f;', 'S Function<S₀>(S₀)');
@@ -4684,7 +4670,7 @@
 
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/30236')
   test_genericMethod_nestedCaptureBounds() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   T f<S extends T>(S x) {
     new C<S>().f<int>(3);
@@ -4693,7 +4679,7 @@
   }
 }
 ''');
-    MethodInvocation f = findIdentifier('f<int>(3);').parent;
+    MethodInvocation f = findNode.methodInvocation('f<int>(3);');
     expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}',
@@ -4703,18 +4689,18 @@
   }
 
   test_genericMethod_nestedFunctions() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 S f<S>(S x) {
   g<S>(S x) => f;
   return null;
 }
 ''');
-    expectIdentifierType('f', 'S Function<S>(S)');
-    expectIdentifierType('g', 'S Function<S>(S) Function<S>(S)');
+    expectIdentifierType('f<S>', 'S Function<S>(S)');
+    expectIdentifierType('g<S>', 'S Function<S>(S) Function<S>(S)');
   }
 
   test_genericMethod_override() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   T f<T>(T x) => null;
 }
@@ -4724,14 +4710,14 @@
 ''');
     expectFunctionType('f<T>(T x) => null; // from D', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
-    SimpleIdentifier f = findIdentifier('f<T>(T x) => null; // from D');
+    SimpleIdentifier f = findNode.simple('f<T>(T x) => null; // from D');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericMethod_override_bounds() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B {
   T f<T extends A>(T x) => null;
@@ -4748,7 +4734,7 @@
   }
 
   test_genericMethod_override_covariant_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   num get x;
   set x(covariant num _);
@@ -4758,13 +4744,10 @@
   int x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericMethod_override_differentContextsSameBounds() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
         class GenericMethodBounds<T> {
   Type get t => T;
   GenericMethodBounds<E> foo<E extends T>() => new GenericMethodBounds<E>();
@@ -4778,13 +4761,10 @@
       new GenericMethodBounds<E>();
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericMethod_override_invalidContravariantTypeParamBounds() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {}
 class C {
@@ -4792,14 +4772,13 @@
 }
 class D extends C {
   T f<T extends B>(T x) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1),
+    ]);
   }
 
   test_genericMethod_override_invalidCovariantTypeParamBounds() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {}
 class C {
@@ -4807,36 +4786,33 @@
 }
 class D extends C {
   T f<T extends A>(T x) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1),
+    ]);
   }
 
   test_genericMethod_override_invalidReturnType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class C {
   Iterable<T> f<T>(T x) => null;
 }
 class D extends C {
   String f<S>(S x) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 74, 1),
+    ]);
   }
 
   test_genericMethod_override_invalidTypeParamCount() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class C {
   T f<T>(T x) => null;
 }
 class D extends C {
   S f<T, S>(T x) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 59, 1),
+    ]);
   }
 
   test_genericMethod_propagatedType_promotion() async {
@@ -4847,7 +4823,7 @@
     // example won't work, as we now compute a static type and therefore discard
     // the propagated type. So a new test was created that doesn't run under
     // strong mode.
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 abstract class Iter {
   List<S> map<S>(S f(x));
 }
@@ -4862,7 +4838,7 @@
   }
 
   test_genericMethod_tearoff() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(E e) => null;
   static T g<T>(T e) => null;
@@ -4894,7 +4870,7 @@
 
   @failingTest
   test_genericMethod_tearoff_instantiated() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   T f<T>(E e) => null;
   static T g<T>(T e) => null;
@@ -4925,42 +4901,42 @@
   }
 
   test_genericMethod_then() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:async';
 String toString(int x) => x.toString();
 main() {
   Future<int> bar = null;
   var foo = bar.then(toString);
 }
-''';
-    await resolveTestUnit(code);
+''');
 
     expectInitializerType('foo', 'Future<String>');
   }
 
   test_genericMethod_then_prefixed() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:async' as async;
 String toString(int x) => x.toString();
 main() {
   async.Future<int> bar = null;
   var foo = bar.then(toString);
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'Future<String>');
   }
 
   test_genericMethod_then_propagatedType() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/25482.
-    String code = r'''
+    await assertErrorsInCode(r'''
 import 'dart:async';
 void main() {
   Future<String> p;
   var foo = p.then((r) => new Future<String>.value(3));
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 3),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 106, 1),
+    ]);
     // Note: this correctly reports the error
     // StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE when run with the driver;
     // when run without the driver, it reports no errors.  So we don't bother
@@ -4969,7 +4945,7 @@
   }
 
   test_genericMethod_toplevel_field_staticTearoff() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   static T g<T>(T e) => null;
   static T Function<T>(T) h = null;
@@ -4983,7 +4959,7 @@
   }
 
   test_implicitBounds() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {}
 
 class B<T extends num> {}
@@ -4999,8 +4975,7 @@
   var bb = new B();
   var cc = new C();
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectIdentifierType('ai', "A<dynamic>");
     expectIdentifierType('bi', "B<num>");
     expectIdentifierType('ci', "C<int, B<int>, A<dynamic>>");
@@ -5009,154 +4984,119 @@
     expectIdentifierType('cc', "C<int, B<int>, A<dynamic>>");
   }
 
-  test_inferClosureType_parameters() async {
-    Source source = addSource(r'''
-typedef F({bool p});
-foo(callback(F f)) {}
-main() {
-  foo((f) {
-    f(p: false);
-  });
-}
-''');
-    var result = await computeAnalysisResult(source);
-    var main = result.unit.declarations[2] as FunctionDeclaration;
-    var body = main.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var invocation = statement.expression as MethodInvocation;
-    var closure = invocation.argumentList.arguments[0] as FunctionExpression;
-    var closureType = closure.staticType as FunctionType;
-    var fType = closureType.parameters[0].type as FunctionType;
-    // The inferred type of "f" in "foo()" invocation must own its parameters.
-    ParameterElement p = fType.parameters[0];
-    expect(p.name, 'p');
-    expect(p.enclosingElement, same(fType.element));
-  }
-
   test_instantiateToBounds_class_error_extension_malbounded() async {
     // Test that superclasses are strictly checked for malbounded default
     // types
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C<T0 extends List<T1>, T1 extends List<T0>> {}
 class D extends C {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(
-        testSource, [CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
+    ]);
   }
 
   test_instantiateToBounds_class_error_instantiation_malbounded() async {
     // Test that instance creations are strictly checked for malbounded default
     // types
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C<T0 extends List<T1>, T1 extends List<T0>> {}
 void test() {
   var c = new C();
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.COULD_NOT_INFER,
-      CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 73, 1),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 81, 1),
+      error(StrongModeCode.COULD_NOT_INFER, 81, 1),
     ]);
     expectIdentifierType('c =', 'C<List<dynamic>, List<List<dynamic>>>');
   }
 
   test_instantiateToBounds_class_error_recursion() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C<T0 extends List<T1>, T1 extends List<T0>> {}
 C c;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertNoErrors(testSource);
+''', []);
+
     expectIdentifierType('c;', 'C<List<dynamic>, List<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_recursion_self() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C<T extends C<T>> {}
 C c;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertNoErrors(testSource);
+''', []);
+
     expectIdentifierType('c;', 'C<C<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_recursion_self2() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<E> {}
 class C<T extends A<T>> {}
 C c;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertNoErrors(testSource);
+''', []);
+
     expectIdentifierType('c;', 'C<A<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_typedef() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 typedef T F<T>(T x);
 class C<T extends F<T>> {}
 C c;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertNoErrors(testSource);
+''', []);
+
     expectIdentifierType('c;', 'C<dynamic Function(dynamic)>');
   }
 
   test_instantiateToBounds_class_ok_implicitDynamic_multi() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends Map<T1, T2>, T1 extends List, T2 extends int> {}
 C c;
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType(
         'c;', 'C<Map<List<dynamic>, int>, List<dynamic>, int>');
   }
 
   test_instantiateToBounds_class_ok_referenceOther_after() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends T1, T1 extends int> {}
 C c;
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType('c;', 'C<int, int>');
   }
 
   test_instantiateToBounds_class_ok_referenceOther_after2() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends Map<T1, T1>, T1 extends int> {}
 C c;
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType('c;', 'C<Map<int, int>, int>');
   }
 
   test_instantiateToBounds_class_ok_referenceOther_before() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends int, T1 extends T0> {}
 C c;
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType('c;', 'C<int, int>');
   }
 
   test_instantiateToBounds_class_ok_referenceOther_multi() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends Map<T1, T2>, T1 extends List<T2>, T2 extends int> {}
 C c;
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType('c;', 'C<Map<List<int>, int>, List<int>, int>');
   }
 
   test_instantiateToBounds_class_ok_simpleBounds() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {}
 class B<T extends num> {}
 class C<T extends List<int>> {}
@@ -5167,9 +5107,8 @@
   C c;
   D d;
 }
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectIdentifierType('a;', 'A<dynamic>');
     expectIdentifierType('b;', 'B<num>');
     expectIdentifierType('c;', 'C<List<int>>');
@@ -5179,21 +5118,22 @@
   test_instantiateToBounds_generic_function_error_malbounded() async {
     // Test that generic methods are strictly checked for malbounded default
     // types
-    String code = r'''
+    await assertErrorsInCode(r'''
 T0 f<T0 extends List<T1>, T1 extends List<T0>>() {}
 void g() {
   var c = f();
   return;
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(
-        testSource, [HintCode.MISSING_RETURN, StrongModeCode.COULD_NOT_INFER]);
+''', [
+      error(HintCode.MISSING_RETURN, 0, 2),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 69, 1),
+      error(StrongModeCode.COULD_NOT_INFER, 73, 1),
+    ]);
     expectIdentifierType('c =', 'List<dynamic>');
   }
 
   test_instantiateToBounds_method_ok_referenceOther_before() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   void m<S0 extends T, S1 extends List<S0>>(S0 p0, S1 p1) {}
 
@@ -5201,14 +5141,13 @@
     m(null, null);
   }
 }
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectStaticInvokeType('m(null', 'void Function(Null, Null)');
   }
 
   test_instantiateToBounds_method_ok_referenceOther_before2() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   Map<S0, S1> m<S0 extends T, S1 extends List<S0>>() => null;
 
@@ -5216,14 +5155,13 @@
     m();
   }
 }
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectStaticInvokeType('m();', 'Map<T, List<T>> Function()');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   void m<S extends T>(S p0) {}
 
@@ -5231,14 +5169,13 @@
     m(null);
   }
 }
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectStaticInvokeType('m(null)', 'void Function(Null)');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds2() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T> {
   S m<S extends T>() => null;
 
@@ -5246,14 +5183,13 @@
     m();
   }
 }
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
+
     expectStaticInvokeType('m();', 'T Function()');
   }
 
   test_issue32396() async {
-    await resolveTestUnit(r'''
+    await assertNoErrorsInCode(r'''
 class C<E> {
   static T g<T>(T e) => null;
   static final h = g;
@@ -5262,190 +5198,169 @@
   }
 
   test_notInstantiatedBound_class_error_recursion() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<T extends B> {} // points to a
 class B<T extends A> {} // points to b
 class C<T extends A> {} // points to a cyclical type
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 18, 1),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 57, 1),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 96, 1),
     ]);
   }
 
   test_notInstantiatedBound_class_error_recursion_less_direct() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<T extends B<A>> {}
 class B<T extends A<B>> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 20, 1),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 47, 1),
     ]);
   }
 
   test_notInstantiatedBound_class_error_recursion_typedef() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 typedef F(C value);
 class C<T extends F> {}
 class D<T extends C> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 19),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 38, 1),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 62, 1),
     ]);
   }
 
   test_notInstantiatedBound_error_class_argument() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends List<K>> {}
 class C<T extends A> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 51, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_class_argument2() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends List<List<K>>> {}
 class C<T extends A> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 57, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_class_direct() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends K> {}
 class C<T extends A> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 45, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_class_indirect() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends K> {}
 class C<T extends List<A>> {}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 50, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_functionType() async {
-    await resolveTestUnit(r'''
+    await assertErrorsInCode(r'''
 class A<T extends Function(T)> {}
 class B<T extends T Function()> {}
 class C<T extends A> {}
 class D<T extends B> {}
-''', noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 87, 1),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 111, 1),
     ]);
   }
 
   test_notInstantiatedBound_error_typedef_argument() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends List<K>> {}
 typedef void F<T extends A>();
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 58, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_typedef_argument2() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends List<List<K>>> {}
 typedef void F<T extends A>();
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 64, 1),
+    ]);
   }
 
   test_notInstantiatedBound_error_typedef_direct() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class A<K, V extends K> {}
 typedef void F<T extends A>();
-''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+''', [
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 52, 1),
+    ]);
   }
 
   test_notInstantiatedBound_ok_class() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T extends int> {}
 class C1<T extends A> {}
 class C2<T extends List<A>> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_class_class2() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {}
 class C<T extends A<int>> {}
 class D<T extends C> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_class_class3() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {}
 class B<T extends int> {}
 class C<T extends A<B>> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_class_class4() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<K, V> {}
 class B<T extends int> {}
 class C<T extends A<B, B>> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_class_function() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class A<T extends void Function()> {}
 class B<T extends A> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_class_typedef() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 typedef void F<T extends int>();
 class C<T extends F> {}
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_notInstantiatedBound_ok_typedef_class() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C<T extends int> {}
 typedef void F<T extends C>();
-''';
-    await resolveTestUnit(code);
-    assertNoErrors(testSource);
+''');
   }
 
   test_objectMethodOnFunctions_Anonymous() async {
-    String code = r'''
+    await _objectMethodOnFunctions_helper2(r'''
 void main() {
   var f = (x) => 3;
   // No errors, correct type
@@ -5467,12 +5382,11 @@
   (f)..toString();
   (f)..toString;
   (f)..hashCode;
-}''';
-    await _objectMethodOnFunctions_helper2(code);
+}''');
   }
 
   test_objectMethodOnFunctions_Function() async {
-    String code = r'''
+    await _objectMethodOnFunctions_helper2(r'''
 void main() {
   Function f;
   // No errors, correct type
@@ -5494,12 +5408,11 @@
   (f)..toString();
   (f)..toString;
   (f)..hashCode;
-}''';
-    await _objectMethodOnFunctions_helper2(code);
+}''');
   }
 
   test_objectMethodOnFunctions_Static() async {
-    String code = r'''
+    await _objectMethodOnFunctions_helper2(r'''
 int f(int x) => null;
 void main() {
   // No errors, correct type
@@ -5521,12 +5434,11 @@
   (f)..toString();
   (f)..toString;
   (f)..hashCode;
-}''';
-    await _objectMethodOnFunctions_helper2(code);
+}''');
   }
 
   test_objectMethodOnFunctions_Typedef() async {
-    String code = r'''
+    await _objectMethodOnFunctions_helper2(r'''
 typedef bool Predicate<T>(T object);
 
 void main() {
@@ -5550,110 +5462,93 @@
   (f)..toString();
   (f)..toString;
   (f)..hashCode;
-}''';
-    await _objectMethodOnFunctions_helper2(code);
+}''');
   }
 
   test_returnOfInvalidType_object_void() async {
     await assertErrorsInCode(
-        "Object f() { void voidFn() => null; return voidFn(); }",
-        [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+        "Object f() { void voidFn() => null; return voidFn(); }", [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 43, 8),
+    ]);
   }
 
   test_setterWithDynamicTypeIsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {
   dynamic set f(String s) => null;
 }
 dynamic set g(int x) => null;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.NON_VOID_RETURN_FOR_SETTER,
-      StaticWarningCode.NON_VOID_RETURN_FOR_SETTER
+''', [
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 12, 7),
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 47, 7),
     ]);
-    verify([source]);
   }
 
   test_setterWithExplicitVoidType_returningVoid() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void returnsVoid() {}
 class A {
   void set f(String s) => returnsVoid();
 }
 void set g(int x) => returnsVoid();
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_setterWithNoVoidType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {
   set f(String s) {
     return '42';
   }
 }
 set g(int x) => 42;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 41, 4),
     ]);
-    verify([source]);
   }
 
   test_setterWithNoVoidType_returningVoid() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void returnsVoid() {}
 class A {
   set f(String s) => returnsVoid();
 }
 set g(int x) => returnsVoid();
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_setterWithOtherTypeIsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {
   String set f(String s) => null;
 }
 Object set g(x) => null;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.NON_VOID_RETURN_FOR_SETTER,
-      StaticWarningCode.NON_VOID_RETURN_FOR_SETTER
+''', [
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 12, 6),
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 46, 6),
     ]);
-    verify([source]);
   }
 
   test_ternaryOperator_null_left() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var foo = (true) ? null : 3;
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   test_ternaryOperator_null_right() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var foo = (true) ? 3 : null;
 }
-''';
-    await resolveTestUnit(code);
+''');
     expectInitializerType('foo', 'int');
   }
 
   Future<void> _objectMethodOnFunctions_helper2(String code) async {
-    await resolveTestUnit(code);
+    await assertNoErrorsInCode(code);
     expectIdentifierType('t0', "String");
     expectIdentifierType('t1', "String Function()");
     expectIdentifierType('t2', "int");
@@ -5664,83 +5559,71 @@
 }
 
 @reflectiveTest
-class StrongModeTypePropagationTest extends ResolverTestCase {
-  @override
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    resetWith(options: options);
-  }
-
+class StrongModeTypePropagationTest extends DriverResolutionTest {
   test_foreachInference_dynamic_disabled() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var list = <int>[];
   for (dynamic v in list) {
     v; // marker
   }
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertPropagatedIterationType(code, unit, typeProvider.dynamicType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.dynamicType);
+}''');
+    assertTypeDynamic(findNode.simple('v in'));
+    assertTypeDynamic(findNode.simple('v; // marker'));
   }
 
   test_foreachInference_reusedVar_disabled() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var list = <int>[];
   var v;
   for (v in list) {
     v; // marker
   }
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertPropagatedIterationType(code, unit, typeProvider.dynamicType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.dynamicType);
+}''');
+    assertTypeDynamic(findNode.simple('v in'));
+    assertTypeDynamic(findNode.simple('v; // marker'));
   }
 
   test_foreachInference_var() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var list = <int>[];
   for (var v in list) {
     v; // marker
   }
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertPropagatedIterationType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v in'), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_foreachInference_var_iterable() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   Iterable<int> list = <int>[];
   for (var v in list) {
     v; // marker
   }
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertPropagatedIterationType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v in'), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_foreachInference_var_stream() async {
-    String code = r'''
+    await resolveTestCode(r'''
 import 'dart:async';
 main() async {
   Stream<int> stream = null;
   await for (var v in stream) {
     v; // marker
   }
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertPropagatedIterationType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v in'), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_inconsistentMethodInheritance_inferFunctionTypeFromTypedef() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef bool F<E>(E argument);
 
 abstract class Base {
@@ -5756,58 +5639,51 @@
 
 class C extends Override implements Base {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_localVariableInference_bottom_disabled() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var v = null;
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.dynamicType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.dynamicType);
+}''');
+    assertTypeDynamic(findNode.simple('v ='));
+    assertTypeDynamic(findNode.simple('v; // marker'));
   }
 
   test_localVariableInference_constant() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var v = 3;
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_declaredType_disabled() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   dynamic v = 3;
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.dynamicType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.dynamicType);
+}''');
+    assertTypeDynamic(findNode.simple('v ='));
+    assertTypeDynamic(findNode.simple('v; // marker'));
   }
 
   test_localVariableInference_noInitializer_disabled() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var v;
   v = 3;
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.dynamicType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.dynamicType);
+}''');
+    assertTypeDynamic(findNode.simple('v ='));
+    assertTypeDynamic(findNode.simple('v; // marker'));
   }
 
   test_localVariableInference_transitive_field_inferred_lexical() async {
-    String code = r'''
+    await resolveTestCode(r'''
 class A {
   final x = 3;
   f() {
@@ -5817,14 +5693,13 @@
 }
 main() {
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_field_inferred_reversed() async {
-    String code = r'''
+    await resolveTestCode(r'''
 class A {
   f() {
     var v = x;
@@ -5834,14 +5709,13 @@
 }
 main() {
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_field_lexical() async {
-    String code = r'''
+    await resolveTestCode(r'''
 class A {
   int x = 3;
   f() {
@@ -5851,14 +5725,13 @@
 }
 main() {
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_field_reversed() async {
-    String code = r'''
+    await resolveTestCode(r'''
 class A {
   f() {
     var v = x;
@@ -5868,85 +5741,78 @@
 }
 main() {
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_list_local() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var x = <int>[3];
   var v = x[0];
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_local() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var x = 3;
   var v = x;
   v; // marker
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+}''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
-  test_localVariableInference_transitive_toplevel_inferred_lexical() async {
-    String code = r'''
+  test_localVariableInference_transitive_topLevel_inferred_lexical() async {
+    await resolveTestCode(r'''
 final x = 3;
 main() {
   var v = x;
   v; // marker
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
   test_localVariableInference_transitive_toplevel_inferred_reversed() async {
-    String code = r'''
+    await resolveTestCode(r'''
 main() {
   var v = x;
   v; // marker
 }
 final x = 3;
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
-  test_localVariableInference_transitive_toplevel_lexical() async {
-    String code = r'''
+  test_localVariableInference_transitive_topLevel_lexical() async {
+    await resolveTestCode(r'''
 int x = 3;
 main() {
   var v = x;
   v; // marker
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 
-  test_localVariableInference_transitive_toplevel_reversed() async {
-    String code = r'''
+  test_localVariableInference_transitive_topLevel_reversed() async {
+    await resolveTestCode(r'''
 main() {
   var v = x;
   v; // marker
 }
 int x = 3;
-''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.intType);
-    assertTypeOfMarkedExpression(code, unit, typeProvider.intType);
+''');
+    assertType(findNode.simple('v ='), 'int');
+    assertType(findNode.simple('v; // marker'), 'int');
   }
 }
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index f85b302..4b73b9c 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -2,107 +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:analyzer/dart/ast/ast.dart' show AstNode, SimpleIdentifier;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 
-import 'test_analysis_context.dart';
-
-/// The class `EngineTestCase` defines utility methods for making assertions.
-class EngineTestCase {
-  /// Return `true` if the fasta parser is being used.
-  bool get usingFastaParser => Parser.useFasta;
-
-  /// Assert that the given collection of [elements] has the same number of
-  /// elements as the number of specified [names], and that for each specified
-  /// name, a corresponding element can be found in the given collection with
-  /// that name.
-  void assertNamedElements(List<Element> elements, List<String> names) {
-    for (String elemName in names) {
-      bool found = false;
-      for (Element elem in elements) {
-        if (elem.name == elemName) {
-          found = true;
-          break;
-        }
-      }
-      if (!found) {
-        StringBuffer buffer = new StringBuffer();
-        buffer.write("Expected element named: ");
-        buffer.write(elemName);
-        buffer.write("\n  but found: ");
-        for (Element elem in elements) {
-          buffer.write(elem.name);
-          buffer.write(", ");
-        }
-        fail(buffer.toString());
-      }
-    }
-    expect(elements, hasLength(names.length));
-  }
-
-  AnalysisContext createAnalysisContext() {
-    return TestAnalysisContext();
-  }
-
-  /// Return the getter in the given [type] with the given [name]. Inherited
-  /// getters are ignored.
-  PropertyAccessorElement getGetter(InterfaceType type, String getterName) {
-    for (PropertyAccessorElement accessor in type.element.accessors) {
-      if (accessor.isGetter && accessor.name == getterName) {
-        return accessor;
-      }
-    }
-    fail("Could not find getter named $getterName in ${type.displayName}");
-  }
-
-  /// Return the method in the given [type] with the given [name]. Inherited
-  /// methods are ignored.
-  MethodElement getMethod(InterfaceType type, String methodName) {
-    for (MethodElement method in type.element.methods) {
-      if (method.name == methodName) {
-        return method;
-      }
-    }
-    fail("Could not find method named $methodName in ${type.displayName}");
-  }
-
-  void setUp() {}
-
-  void tearDown() {}
-
-  /// Return the [AstNode] with requested type at offset of the [prefix].
-  static AstNode findNode(
-      AstNode root, String code, String prefix, Predicate<AstNode> predicate) {
-    int offset = code.indexOf(prefix);
-    if (offset == -1) {
-      throw new ArgumentError("Not found '$prefix'.");
-    }
-    AstNode node = new NodeLocator(offset).searchWithin(root);
-    return node.thisOrAncestorMatching(predicate);
-  }
-
-  /// Find the [SimpleIdentifier] with at offset of the [prefix].
-  static SimpleIdentifier findSimpleIdentifier(
-      AstNode root, String code, String prefix) {
-    int offset = code.indexOf(prefix);
-    if (offset == -1) {
-      throw new ArgumentError("Not found '$prefix'.");
-    }
-    return new NodeLocator(offset).searchWithin(root);
-  }
-}
-
 /// A description of an error that is expected to be reported.
 class ExpectedError {
   /// An empty array of error descriptors used when no errors are expected.
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 858c95e..d5f31a8 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:collection';
-
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
@@ -18,7 +16,6 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -31,12 +28,9 @@
     defineReflectiveTests(BooleanArrayTest);
     defineReflectiveTests(ExceptionHandlingDelegatingAstVisitorTest);
     defineReflectiveTests(LineInfoTest);
-    defineReflectiveTests(MultipleMapIteratorTest);
     defineReflectiveTests(NodeReplacerTest);
-    defineReflectiveTests(SingleMapIteratorTest);
     defineReflectiveTests(SourceRangeTest);
     defineReflectiveTests(StringUtilitiesTest);
-    defineReflectiveTests(TokenMapTest);
   });
 }
 
@@ -69,7 +63,7 @@
 }
 
 @reflectiveTest
-class AstClonerTest extends EngineTestCase {
+class AstClonerTest {
   void test_visitAdjacentStrings() {
     _assertCloneExpression("'a' 'b'");
   }
@@ -1337,7 +1331,7 @@
 }
 
 @reflectiveTest
-class ExceptionHandlingDelegatingAstVisitorTest extends EngineTestCase {
+class ExceptionHandlingDelegatingAstVisitorTest {
   void test_handlerIsCalled() {
     AstVisitor exceptionThrowingVisitor = new _ExceptionThrowingVisitor();
     bool handlerInvoked = false;
@@ -2608,113 +2602,7 @@
 }
 
 @reflectiveTest
-class MultipleMapIteratorTest extends EngineTestCase {
-  void test_multipleMaps_firstEmpty() {
-    Map<String, String> map1 = new HashMap<String, String>();
-    Map<String, String> map2 = new HashMap<String, String>();
-    map2["k2"] = "v2";
-    Map<String, String> map3 = new HashMap<String, String>();
-    map3["k3"] = "v3";
-    MultipleMapIterator<String, String> iterator =
-        _iterator([map1, map2, map3]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_multipleMaps_lastEmpty() {
-    Map<String, String> map1 = new HashMap<String, String>();
-    map1["k1"] = "v1";
-    Map<String, String> map2 = new HashMap<String, String>();
-    map2["k2"] = "v2";
-    Map<String, String> map3 = new HashMap<String, String>();
-    MultipleMapIterator<String, String> iterator =
-        _iterator([map1, map2, map3]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_multipleMaps_middleEmpty() {
-    Map<String, String> map1 = new HashMap<String, String>();
-    map1["k1"] = "v1";
-    Map<String, String> map2 = new HashMap<String, String>();
-    Map<String, String> map3 = new HashMap<String, String>();
-    map3["k3"] = "v3";
-    MultipleMapIterator<String, String> iterator =
-        _iterator([map1, map2, map3]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_multipleMaps_nonEmpty() {
-    Map<String, String> map1 = new HashMap<String, String>();
-    map1["k1"] = "v1";
-    Map<String, String> map2 = new HashMap<String, String>();
-    map2["k2"] = "v2";
-    Map<String, String> map3 = new HashMap<String, String>();
-    map3["k3"] = "v3";
-    MultipleMapIterator<String, String> iterator =
-        _iterator([map1, map2, map3]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_noMap() {
-    MultipleMapIterator<String, String> iterator = _iterator([]);
-    expect(iterator.moveNext(), isFalse);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_singleMap_empty() {
-    Map<String, String> map = new HashMap<String, String>();
-    MultipleMapIterator<String, String> iterator = _iterator([map]);
-    expect(iterator.moveNext(), isFalse);
-    expect(() => iterator.key, throwsStateError);
-    expect(() => iterator.value, throwsStateError);
-    expect(() {
-      iterator.value = 'x';
-    }, throwsStateError);
-  }
-
-  void test_singleMap_multiple() {
-    Map<String, String> map = new HashMap<String, String>();
-    map["k1"] = "v1";
-    map["k2"] = "v2";
-    map["k3"] = "v3";
-    MultipleMapIterator<String, String> iterator = _iterator([map]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_singleMap_single() {
-    String key = "key";
-    String value = "value";
-    Map<String, String> map = new HashMap<String, String>();
-    map[key] = value;
-    MultipleMapIterator<String, String> iterator = _iterator([map]);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.key, same(key));
-    expect(iterator.value, same(value));
-    String newValue = "newValue";
-    iterator.value = newValue;
-    expect(iterator.value, same(newValue));
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  MultipleMapIterator<String, String> _iterator(
-      List<Map<String, String>> maps) {
-    return new MultipleMapIterator<String, String>(maps);
-  }
-}
-
-@reflectiveTest
-class NodeReplacerTest extends EngineTestCase {
+class NodeReplacerTest {
   /**
    * An empty list of tokens.
    */
@@ -3700,51 +3588,6 @@
 }
 
 @reflectiveTest
-class SingleMapIteratorTest extends EngineTestCase {
-  void test_empty() {
-    Map<String, String> map = new HashMap<String, String>();
-    SingleMapIterator<String, String> iterator =
-        new SingleMapIterator<String, String>(map);
-    expect(iterator.moveNext(), isFalse);
-    expect(() => iterator.key, throwsStateError);
-    expect(() => iterator.value, throwsStateError);
-    expect(() {
-      iterator.value = 'x';
-    }, throwsStateError);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_multiple() {
-    Map<String, String> map = new HashMap<String, String>();
-    map["k1"] = "v1";
-    map["k2"] = "v2";
-    map["k3"] = "v3";
-    SingleMapIterator<String, String> iterator =
-        new SingleMapIterator<String, String>(map);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.moveNext(), isFalse);
-  }
-
-  void test_single() {
-    String key = "key";
-    String value = "value";
-    Map<String, String> map = new HashMap<String, String>();
-    map[key] = value;
-    SingleMapIterator<String, String> iterator =
-        new SingleMapIterator<String, String>(map);
-    expect(iterator.moveNext(), isTrue);
-    expect(iterator.key, same(key));
-    expect(iterator.value, same(value));
-    String newValue = "newValue";
-    iterator.value = newValue;
-    expect(iterator.value, same(newValue));
-    expect(iterator.moveNext(), isFalse);
-  }
-}
-
-@reflectiveTest
 class SourceRangeTest {
   void test_access() {
     SourceRange r = new SourceRange(10, 1);
@@ -4148,26 +3991,6 @@
   }
 }
 
-@reflectiveTest
-class TokenMapTest {
-  void test_creation() {
-    expect(new TokenMap(), isNotNull);
-  }
-
-  void test_get_absent() {
-    TokenMap tokenMap = new TokenMap();
-    expect(tokenMap.get(TokenFactory.tokenFromType(TokenType.AT)), isNull);
-  }
-
-  void test_get_added() {
-    TokenMap tokenMap = new TokenMap();
-    Token key = TokenFactory.tokenFromType(TokenType.AT);
-    Token value = TokenFactory.tokenFromType(TokenType.AT);
-    tokenMap.put(key, value);
-    expect(tokenMap.get(key), same(value));
-  }
-}
-
 class _ExceptionThrowingVisitor extends SimpleAstVisitor {
   visitNullLiteral(NullLiteral node) {
     throw new ArgumentError('');
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index cc22d22..03fb7a6 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -31,7 +31,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../embedder_tests.dart';
-import '../../generated/test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -41,7 +40,7 @@
 }
 
 @reflectiveTest
-class ContextBuilderTest extends EngineTestCase with ResourceProviderMixin {
+class ContextBuilderTest with ResourceProviderMixin {
   /**
    * The SDK manager used by the tests;
    */
@@ -93,7 +92,6 @@
         options: builderOptions);
   }
 
-  @override
   void setUp() {
     new MockSdk(resourceProvider: resourceProvider);
     sdkManager = new DartSdkManager(convertPath('/sdk'), false);
@@ -533,6 +531,68 @@
     expect(packageSource.fullName, join(packageA, 'a.dart'));
   }
 
+  void test_createWorkspace_hasPackagesFile_hasDartToolAndPubspec() {
+    newFile('/workspace/.packages');
+    newFolder('/workspace/.dart_tool/build/generated/project/lib');
+    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
+  }
+
+  void test_createWorkspace_hasPackagesFile_hasPubspec() {
+    newFile('/workspace/.packages');
+    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<PubWorkspace>());
+  }
+
+  void test_createWorkspace_hasPackagesFile_noMarkerFiles() {
+    newFile('/workspace/.packages');
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<BasicWorkspace>());
+  }
+
+  void test_createWorkspace_noPackagesFile_hasBazelMarkerFiles() {
+    newFile('/workspace/WORKSPACE');
+    newFolder('/workspace/bazel-genfiles');
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<BazelWorkspace>());
+  }
+
+  void test_createWorkspace_noPackagesFile_hasDartToolAndPubspec() {
+    newFolder('/workspace/.dart_tool/build/generated/project/lib');
+    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
+  }
+
+  void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
+    newFolder('/workspace/.jiri_root');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib.packages');
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<GnWorkspace>());
+  }
+
+  void test_createWorkspace_noPackagesFile_hasPubspec() {
+    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<PubWorkspace>());
+  }
+
+  void test_createWorkspace_noPackagesFile_noMarkerFiles() {
+    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
+        convertPath('/workspace/project/lib/lib.dart'), builder);
+    expect(workspace, TypeMatcher<BasicWorkspace>());
+  }
+
   void test_declareVariables_emptyMap() {
     AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
     Iterable<String> expected = context.declaredVariables.variableNames;
@@ -857,68 +917,6 @@
     expect(result.path, filePath);
   }
 
-  void test_createWorkspace_hasPackagesFile_hasDartToolAndPubspec() {
-    newFile('/workspace/.packages');
-    newFolder('/workspace/.dart_tool/build/generated/project/lib');
-    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
-  }
-
-  void test_createWorkspace_hasPackagesFile_hasPubspec() {
-    newFile('/workspace/.packages');
-    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<PubWorkspace>());
-  }
-
-  void test_createWorkspace_hasPackagesFile_noMarkerFiles() {
-    newFile('/workspace/.packages');
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<BasicWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasDartToolAndPubspec() {
-    newFolder('/workspace/.dart_tool/build/generated/project/lib');
-    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasPubspec() {
-    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<PubWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_noMarkerFiles() {
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<BasicWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
-    newFolder('/workspace/.jiri_root');
-    newFile(
-        '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib.packages');
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<GnWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasBazelMarkerFiles() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-genfiles');
-    Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
-        convertPath('/workspace/project/lib/lib.dart'), builder);
-    expect(workspace, TypeMatcher<BazelWorkspace>());
-  }
-
   _defineMockLintRules() {
     _mockLintRule = new _MockLintRule('mock_lint_rule');
     Registry.ruleRegistry.register(_mockLintRule);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index dc8f58b..ef0509e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -293,6 +293,8 @@
 
     Monitor idleStatusMonitor = new Monitor();
     List<AnalysisStatus> allStatuses = [];
+    // awaiting times out.
+    // ignore: unawaited_futures
     scheduler.status.forEach((status) {
       allStatuses.add(status);
       if (status.isIdle) {
@@ -322,6 +324,8 @@
 
     Monitor idleStatusMonitor = new Monitor();
     List<AnalysisStatus> allStatuses = [];
+    // awaiting times out.
+    // ignore: unawaited_futures
     scheduler.status.forEach((status) {
       allStatuses.add(status);
       if (status.isIdle) {
@@ -2300,7 +2304,7 @@
     expect(driver.hasFilesToAnalyze, isFalse);
 
     // Request of referenced names is not analysis of a file.
-    driver.getFilesReferencingName('X');
+    await driver.getFilesReferencingName('X');
     expect(driver.hasFilesToAnalyze, isFalse);
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/results_test.dart b/pkg/analyzer/test/src/dart/analysis/results_test.dart
index 030194c..9d9c4ed 100644
--- a/pkg/analyzer/test/src/dart/analysis/results_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/results_test.dart
@@ -30,11 +30,9 @@
         sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
 
   test_extension() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 extension E on int {}
 ''');
-    await resolveTestFile();
-
     var element = findNode.extensionDeclaration('E').declaredElement;
     var result = await getElementDeclaration(element);
     ExtensionDeclaration node = result.node;
@@ -46,11 +44,9 @@
   Future<ElementDeclarationResult> getElementDeclaration(Element element);
 
   test_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 ''');
-    await resolveTestFile();
-
     var element = findNode.classDeclaration('A').declaredElement;
     var result = await getElementDeclaration(element);
     ClassDeclaration node = result.node;
@@ -58,12 +54,10 @@
   }
 
   test_class_duplicate() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {} // 1
 class A {} // 2
 ''');
-    await resolveTestFile();
-
     {
       var element = findNode.classDeclaration('A {} // 1').declaredElement;
       var result = await getElementDeclaration(element);
@@ -92,11 +86,9 @@
 part of 'test.dart';
 class A {}
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 part 'a.dart';
 ''');
-    await resolveTestFile();
-
     var library = this.result.unit.declaredElement.library;
     var element = library.getType('A');
     var result = await getElementDeclaration(element);
@@ -105,11 +97,9 @@
   }
 
   test_class_missingName() async {
-    addTestFile('''
+    await resolveTestCode('''
 class {}
 ''');
-    await resolveTestFile();
-
     var element = findNode.classDeclaration('class {}').declaredElement;
     var result = await getElementDeclaration(element);
     ClassDeclaration node = result.node;
@@ -118,13 +108,11 @@
   }
 
   test_classTypeAlias() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 mixin M {}
 class A {}
 class B = A with M;
 ''');
-    await resolveTestFile();
-
     var element = findElement.class_('B');
     var result = await getElementDeclaration(element);
     ClassTypeAlias node = result.node;
@@ -132,14 +120,12 @@
   }
 
   test_constructor() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A();
   A.named();
 }
 ''');
-    await resolveTestFile();
-
     {
       var unnamed = findNode.constructor('A();').declaredElement;
       var result = await getElementDeclaration(unnamed);
@@ -156,14 +142,12 @@
   }
 
   test_constructor_duplicate_named() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A.named(); // 1
   A.named(); // 2
 }
 ''');
-    await resolveTestFile();
-
     {
       var element = findNode.constructor('A.named(); // 1').declaredElement;
       var result = await getElementDeclaration(element);
@@ -188,14 +172,12 @@
   }
 
   test_constructor_duplicate_unnamed() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A(); // 1
   A(); // 2
 }
 ''');
-    await resolveTestFile();
-
     {
       var element = findNode.constructor('A(); // 1').declaredElement;
       var result = await getElementDeclaration(element);
@@ -220,11 +202,9 @@
   }
 
   test_constructor_synthetic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.class_('A').unnamedConstructor;
     expect(element.isSynthetic, isTrue);
 
@@ -233,11 +213,9 @@
   }
 
   test_enum() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum MyEnum {a, b, c}
 ''');
-    await resolveTestFile();
-
     var element = findElement.enum_('MyEnum');
     var result = await getElementDeclaration(element);
     EnumDeclaration node = result.node;
@@ -245,11 +223,9 @@
   }
 
   test_enum_constant() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum MyEnum {a, b, c}
 ''');
-    await resolveTestFile();
-
     var element = findElement.field('a');
     var result = await getElementDeclaration(element);
     EnumConstantDeclaration node = result.node;
@@ -257,13 +233,11 @@
   }
 
   test_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int foo;
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.field('foo');
 
     var result = await getElementDeclaration(element);
@@ -272,13 +246,11 @@
   }
 
   test_functionDeclaration_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.localFunction('foo');
 
     var result = await getElementDeclaration(element);
@@ -287,11 +259,9 @@
   }
 
   test_functionDeclaration_top() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo() {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.topFunction('foo');
 
     var result = await getElementDeclaration(element);
@@ -300,13 +270,11 @@
   }
 
   test_getter_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get x => 0;
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.getter('x');
     var result = await getElementDeclaration(element);
     MethodDeclaration node = result.node;
@@ -315,11 +283,9 @@
   }
 
   test_getter_top() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int get x => 0;
 ''');
-    await resolveTestFile();
-
     var element = findElement.topGet('x');
     var result = await getElementDeclaration(element);
     FunctionDeclaration node = result.node;
@@ -328,13 +294,11 @@
   }
 
   test_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int foo;
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.localVar('foo');
 
     var result = await getElementDeclaration(element);
@@ -343,13 +307,11 @@
   }
 
   test_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.method('foo');
 
     var result = await getElementDeclaration(element);
@@ -358,11 +320,9 @@
   }
 
   test_mixin() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 mixin M {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.mixin('M');
     var result = await getElementDeclaration(element);
     MixinDeclaration node = result.node;
@@ -370,11 +330,9 @@
   }
 
   test_parameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f(int a) {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.parameter('a');
 
     var result = await getElementDeclaration(element);
@@ -383,11 +341,9 @@
   }
 
   test_parameter_missingName_named() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f({@a}) {}
 ''');
-    await resolveTestFile();
-
     var f = findElement.topFunction('f');
     var element = f.parameters.single;
     expect(element.name, '');
@@ -399,11 +355,9 @@
   }
 
   test_parameter_missingName_required() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f(@a) {}
 ''');
-    await resolveTestFile();
-
     var f = findElement.topFunction('f');
     var element = f.parameters.single;
     expect(element.name, '');
@@ -415,13 +369,11 @@
   }
 
   test_setter_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   set x(_) {}
 }
 ''');
-    await resolveTestFile();
-
     var element = findElement.setter('x');
     var result = await getElementDeclaration(element);
     MethodDeclaration node = result.node;
@@ -430,11 +382,9 @@
   }
 
   test_setter_top() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 set x(_) {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.topSet('x');
     var result = await getElementDeclaration(element);
     FunctionDeclaration node = result.node;
@@ -443,11 +393,9 @@
   }
 
   test_topLevelVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int foo;
 ''');
-    await resolveTestFile();
-
     var element = findElement.topVar('foo');
 
     var result = await getElementDeclaration(element);
@@ -456,11 +404,9 @@
   }
 
   test_topLevelVariable_synthetic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int get foo => 0;
 ''');
-    await resolveTestFile();
-
     var element = findElement.topVar('foo');
 
     var result = await getElementDeclaration(element);
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
index 7316c24..2a39d97 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -76,11 +76,9 @@
   }
 
   test_getElementDeclaration_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 ''');
-    await resolveTestFile();
-
     var element = findElement.class_('A');
     var result = await helper.getElementDeclaration(element);
     ClassDeclaration node = result.node;
@@ -88,12 +86,10 @@
   }
 
   test_getResolvedUnitByElement() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B {}
 ''');
-    await resolveTestFile();
-
     var element = findNode.classDeclaration('A').declaredElement;
     var resolvedUnit = await helper.getResolvedUnitByElement(element);
     expect(resolvedUnit.unit.declarations, hasLength(2));
diff --git a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
index e7e1ac1..f63cc86 100644
--- a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
@@ -26,7 +24,7 @@
   }
 
   test_locate_AssignmentExpression() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 int x = 0;
 void main() {
   x += 1;
@@ -38,21 +36,21 @@
   }
 
   test_locate_BinaryExpression() async {
-    await _resolveTestCode('var x = 3 + 4');
+    await resolveTestCode('var x = 3 + 4');
     var node = findNode.binary('+');
     var element = ElementLocator.locate(node);
     expect(element, isMethodElement);
   }
 
   test_locate_ClassDeclaration() async {
-    await _resolveTestCode('class A {}');
+    await resolveTestCode('class A {}');
     var node = findNode.classDeclaration('class');
     var element = ElementLocator.locate(node);
     expect(element, isClassElement);
   }
 
   test_locate_CompilationUnit() async {
-    await _resolveTestCode('// only comment');
+    await resolveTestCode('// only comment');
 
     var unitElement = result.unit.declaredElement;
     expect(unitElement, isNotNull);
@@ -62,7 +60,7 @@
   }
 
   test_locate_ConstructorDeclaration() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {
   A.foo();
 }
@@ -73,21 +71,21 @@
   }
 
   test_locate_ExportDirective() async {
-    await _resolveTestCode("export 'dart:code';");
+    await resolveTestCode("export 'dart:code';");
     var node = findNode.export('export');
     var element = ElementLocator.locate(node);
     expect(element, isExportElement);
   }
 
   test_locate_FunctionDeclaration() async {
-    await _resolveTestCode('int f() => 3;');
+    await resolveTestCode('int f() => 3;');
     var node = findNode.functionDeclaration('f');
     var element = ElementLocator.locate(node);
     expect(element, isFunctionElement);
   }
 
   test_locate_Identifier_annotationClass_namedConstructor() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class Class {
   const Class.name();
 }
@@ -99,7 +97,7 @@
   }
 
   test_locate_Identifier_annotationClass_unnamedConstructor() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class Class {
   const Class();
 }
@@ -111,14 +109,14 @@
   }
 
   test_locate_Identifier_className() async {
-    await _resolveTestCode('class A {}');
+    await resolveTestCode('class A {}');
     var node = findNode.simple('A');
     var element = ElementLocator.locate(node);
     expect(element, isClassElement);
   }
 
   test_locate_Identifier_constructor_named() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {
   A.bar();
 }
@@ -129,7 +127,7 @@
   }
 
   test_locate_Identifier_constructor_unnamed() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {
   A();
 }
@@ -140,7 +138,7 @@
   }
 
   test_locate_Identifier_fieldName() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 class A {
   var x;
 }
@@ -151,14 +149,14 @@
   }
 
   test_locate_Identifier_libraryDirective() async {
-    await _resolveTestCode('library foo.bar;');
+    await resolveTestCode('library foo.bar;');
     var node = findNode.simple('foo');
     var element = ElementLocator.locate(node);
     expect(element, isLibraryElement);
   }
 
   test_locate_Identifier_propertyAccess() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 void main() {
  int x = 'foo'.length;
 }
@@ -169,14 +167,14 @@
   }
 
   test_locate_ImportDirective() async {
-    await _resolveTestCode("import 'dart:core';");
+    await resolveTestCode("import 'dart:core';");
     var node = findNode.import('import');
     var element = ElementLocator.locate(node);
     expect(element, isImportElement);
   }
 
   test_locate_IndexExpression() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 void main() {
   var x = [1, 2];
   var y = x[0];
@@ -188,7 +186,7 @@
   }
 
   test_locate_InstanceCreationExpression() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {}
 
 void main() {
@@ -204,7 +202,7 @@
     newFile('/test/lib/a.dart', content: r'''
 class A {}
 ''');
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as pref;
 
 void main() {
@@ -219,7 +217,7 @@
   test_locate_InstanceCreationExpression_type_simpleIdentifier() async {
     newFile('/test/lib/a.dart', content: r'''
 ''');
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {}
 
 void main() {
@@ -232,14 +230,14 @@
   }
 
   test_locate_LibraryDirective() async {
-    await _resolveTestCode('library foo;');
+    await resolveTestCode('library foo;');
     var node = findNode.library('library');
     var element = ElementLocator.locate(node);
     expect(element, isLibraryElement);
   }
 
   test_locate_MethodDeclaration() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {
   void foo() {}
 }
@@ -250,7 +248,7 @@
   }
 
   test_locate_MethodInvocation_method() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 class A {
   void foo() {}
 }
@@ -265,7 +263,7 @@
   }
 
   test_locate_MethodInvocation_topLevel() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 foo(x) {}
 
 void main() {
@@ -289,21 +287,21 @@
     driver.addFile(libPath);
     driver.addFile(partPath);
 
-    await _resolveTestCode('part of my.lib;');
+    await resolveTestCode('part of my.lib;');
     var node = findNode.partOf('part of');
     var element = ElementLocator.locate(node);
     expect(element, isLibraryElement);
   }
 
   test_locate_PostfixExpression() async {
-    await _resolveTestCode('int addOne(int x) => x++;');
+    await resolveTestCode('int addOne(int x) => x++;');
     var node = findNode.postfix('x++');
     var element = ElementLocator.locate(node);
     expect(element, isMethodElement);
   }
 
   test_locate_PrefixedIdentifier() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 import 'dart:core' as core;
 core.int value;
 ''');
@@ -313,7 +311,7 @@
   }
 
   test_locate_PrefixExpression() async {
-    await _resolveTestCode('int addOne(int x) => ++x;');
+    await resolveTestCode('int addOne(int x) => ++x;');
     var node = findNode.prefix('++x');
     var element = ElementLocator.locate(node);
     expect(element, isMethodElement);
@@ -321,14 +319,14 @@
 
   test_locate_StringLiteral_exportUri() async {
     newFile("/test/lib/foo.dart", content: '');
-    await _resolveTestCode("export 'foo.dart';");
+    await resolveTestCode("export 'foo.dart';");
     var node = findNode.stringLiteral('foo.dart');
     var element = ElementLocator.locate(node);
     expect(element, isLibraryElement);
   }
 
   test_locate_StringLiteral_expression() async {
-    await _resolveTestCode("var x = 'abc';");
+    await resolveTestCode("var x = 'abc';");
     var node = findNode.stringLiteral('abc');
     var element = ElementLocator.locate(node);
     expect(element, isNull);
@@ -336,7 +334,7 @@
 
   test_locate_StringLiteral_importUri() async {
     newFile("/test/lib/foo.dart", content: '');
-    await _resolveTestCode("import 'foo.dart';");
+    await resolveTestCode("import 'foo.dart';");
     var node = findNode.stringLiteral('foo.dart');
     var element = ElementLocator.locate(node);
     expect(element, isLibraryElement);
@@ -344,7 +342,7 @@
 
   test_locate_StringLiteral_partUri() async {
     newFile("/test/lib/foo.dart", content: 'part of lib;');
-    await _resolveTestCode('''
+    await resolveTestCode('''
 library lib;
 
 part 'foo.dart';
@@ -355,14 +353,9 @@
   }
 
   test_locate_VariableDeclaration() async {
-    await _resolveTestCode('var x = 42;');
+    await resolveTestCode('var x = 42;');
     var node = findNode.variableDeclaration('x =');
     var element = ElementLocator.locate(node);
     expect(element, isTopLevelVariableElement);
   }
-
-  Future<void> _resolveTestCode(String code) async {
-    addTestFile(code);
-    await resolveTestFile();
-  }
 }
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 88f8e7a..676ada5 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -21,7 +21,6 @@
 
 import '../../../generated/elements_types_mixin.dart';
 import '../../../generated/parser_test.dart' show ParserTestCase;
-import '../../../generated/test_support.dart';
 import '../../../util/ast_type_matchers.dart';
 
 main() {
@@ -922,7 +921,7 @@
 }
 
 @reflectiveTest
-class ToSourceVisitor2Test extends EngineTestCase {
+class ToSourceVisitor2Test {
   void test_visitAdjacentStrings() {
     _assertSource(
         "'a' 'b'",
@@ -3738,7 +3737,7 @@
 
 @deprecated
 @reflectiveTest
-class ToSourceVisitorTest extends EngineTestCase {
+class ToSourceVisitorTest {
   void test_visitAdjacentStrings() {
     _assertSource(
         "'a' 'b'",
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 8d0b13e..2abcaba 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
@@ -28,7 +27,7 @@
 @reflectiveTest
 class ConstantVisitorTest extends ConstantVisitorTestSupport {
   test_visitBinaryExpression_questionQuestion_eager_notNull_notNull() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 'a' ?? 'b';
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -37,7 +36,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_eager_null_notNull() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ?? 'b';
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -46,7 +45,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_eager_null_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ?? null;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -54,7 +53,7 @@
   }
 
   test_visitConditionalExpression_eager_false_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false ? 1 : 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -63,7 +62,7 @@
   }
 
   test_visitConditionalExpression_eager_invalid_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ? 1 : 0;
 ''');
     DartObjectImpl result = _evaluateConstant(
@@ -74,7 +73,7 @@
   }
 
   test_visitConditionalExpression_eager_true_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? 1 : 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -83,7 +82,7 @@
   }
 
   test_visitConditionalExpression_eager_true_int_invalid() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? 1 : x;
 ''');
     DartObjectImpl result = _evaluateConstant(
@@ -98,7 +97,7 @@
   }
 
   test_visitConditionalExpression_eager_true_invalid_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? x : 0;
 ''');
     DartObjectImpl result = _evaluateConstant(
@@ -109,7 +108,7 @@
   }
 
   test_visitIntegerLiteral() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const double d = 3;
 ''');
     DartObjectImpl result = _evaluateConstant('d');
@@ -118,7 +117,7 @@
   }
 
   test_visitSimpleIdentifier_className() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = C;
 class C {}
 ''');
@@ -128,7 +127,7 @@
   }
 
   test_visitSimpleIdentifier_dynamic() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = dynamic;
 ''');
     DartObjectImpl result = _evaluateConstant('a');
@@ -137,7 +136,7 @@
   }
 
   test_visitSimpleIdentifier_inEnvironment() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 const a = b;
 const b = 3;''');
     var environment = <String, DartObjectImpl>{
@@ -149,7 +148,7 @@
   }
 
   test_visitSimpleIdentifier_notInEnvironment() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 const a = b;
 const b = 3;''');
     var environment = <String, DartObjectImpl>{
@@ -161,7 +160,7 @@
   }
 
   test_visitSimpleIdentifier_withoutEnvironment() async {
-    await _resolveTestCode(r'''
+    await resolveTestCode(r'''
 const a = b;
 const b = 3;''');
     var result = _evaluateConstant('a');
@@ -202,12 +201,6 @@
     }
     return result;
   }
-
-  Future<CompilationUnit> _resolveTestCode(String code) async {
-    addTestFile(code);
-    await resolveTestFile();
-    return result.unit;
-  }
 }
 
 @reflectiveTest
@@ -221,7 +214,7 @@
     ];
 
   test_visitAsExpression_instanceOfSameClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a as A;
 class A {
@@ -234,7 +227,7 @@
   }
 
   test_visitAsExpression_instanceOfSubclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const B();
 const b = a as A;
 class A {
@@ -250,7 +243,7 @@
   }
 
   test_visitAsExpression_instanceOfSuperclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a as B;
 class A {
@@ -266,7 +259,7 @@
   }
 
   test_visitAsExpression_instanceOfUnrelatedClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a as B;
 class A {
@@ -282,7 +275,7 @@
   }
 
   test_visitAsExpression_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a as A;
 class A {}
@@ -305,7 +298,7 @@
   }
 
   test_visitBinaryExpression_and_bool_known_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false & true;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -313,7 +306,7 @@
   }
 
   test_visitBinaryExpression_and_bool_known_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const b = bool.fromEnvironment('y');
 const c = false & b;
 ''');
@@ -322,7 +315,7 @@
   }
 
   test_visitBinaryExpression_and_bool_unknown_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const c = a & true;
 ''');
@@ -331,7 +324,7 @@
   }
 
   test_visitBinaryExpression_and_bool_unknown_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const b = bool.fromEnvironment('y');
 const c = a & b;
@@ -341,7 +334,7 @@
   }
 
   test_visitBinaryExpression_and_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 & 5;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -349,7 +342,7 @@
   }
 
   test_visitBinaryExpression_and_mixed() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 & false;
 ''');
     _evaluateConstant('c',
@@ -357,7 +350,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_negative_fewerBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFFFFFFFF >>> 8;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -366,7 +359,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_negative_moreBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFFFFFFFF >>> 33;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -375,7 +368,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_negative_moreThan64Bits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFFFFFFFF >>> 65;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -384,7 +377,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_negative_negativeBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFFFFFFFF >>> -2;
 ''');
     _evaluateConstant('c',
@@ -392,7 +385,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_negative_zeroBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFFFFFFFF >>> 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -401,7 +394,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_positive_fewerBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFF >>> 3;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -410,7 +403,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_positive_moreBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFF >>> 9;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -419,7 +412,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_positive_moreThan64Bits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFF >>> 65;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -428,7 +421,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_positive_negativeBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFF >>> -2;
 ''');
     _evaluateConstant('c',
@@ -436,7 +429,7 @@
   }
 
   test_visitBinaryExpression_gtGtGt_positive_zeroBits() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 0xFF >>> 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -445,7 +438,7 @@
   }
 
   test_visitBinaryExpression_or_bool_known_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false | true;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -453,7 +446,7 @@
   }
 
   test_visitBinaryExpression_or_bool_known_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const b = bool.fromEnvironment('y');
 const c = false | b;
 ''');
@@ -462,7 +455,7 @@
   }
 
   test_visitBinaryExpression_or_bool_unknown_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const c = a | true;
 ''');
@@ -471,7 +464,7 @@
   }
 
   test_visitBinaryExpression_or_bool_unknown_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const b = bool.fromEnvironment('y');
 const c = a | b;
@@ -481,7 +474,7 @@
   }
 
   test_visitBinaryExpression_or_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 | 5;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -489,7 +482,7 @@
   }
 
   test_visitBinaryExpression_or_mixed() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 | false;
 ''');
     _evaluateConstant('c',
@@ -497,7 +490,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_lazy_notNull_invalid() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 'a' ?? new C();
 class C {}
 ''');
@@ -507,7 +500,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_lazy_notNull_notNull() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 'a' ?? 'b';
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -516,7 +509,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_lazy_null_invalid() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ?? new C();
 class C {}
 ''');
@@ -524,7 +517,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_lazy_null_notNull() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ?? 'b';
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -533,7 +526,7 @@
   }
 
   test_visitBinaryExpression_questionQuestion_lazy_null_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = null ?? null;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -541,7 +534,7 @@
   }
 
   test_visitBinaryExpression_xor_bool_known_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false ^ true;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -549,7 +542,7 @@
   }
 
   test_visitBinaryExpression_xor_bool_known_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const b = bool.fromEnvironment('y');
 const c = false ^ b;
 ''');
@@ -558,7 +551,7 @@
   }
 
   test_visitBinaryExpression_xor_bool_unknown_known() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const c = a ^ true;
 ''');
@@ -567,7 +560,7 @@
   }
 
   test_visitBinaryExpression_xor_bool_unknown_unknown() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = bool.fromEnvironment('x');
 const b = bool.fromEnvironment('y');
 const c = a ^ b;
@@ -577,7 +570,7 @@
   }
 
   test_visitBinaryExpression_xor_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 ^ 5;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -585,7 +578,7 @@
   }
 
   test_visitBinaryExpression_xor_mixed() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 ^ false;
 ''');
     _evaluateConstant('c',
@@ -593,7 +586,7 @@
   }
 
   test_visitConditionalExpression_lazy_false_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false ? 1 : 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -602,14 +595,14 @@
   }
 
   test_visitConditionalExpression_lazy_false_int_invalid() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false ? 1 : new C();
 ''');
     _evaluateConstant('c', errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
   }
 
   test_visitConditionalExpression_lazy_false_invalid_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = false ? new C() : 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c',
@@ -619,7 +612,7 @@
   }
 
   test_visitConditionalExpression_lazy_invalid_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = 3 ? 1 : 0;
 ''');
     _evaluateConstant('c',
@@ -627,7 +620,7 @@
   }
 
   test_visitConditionalExpression_lazy_true_int_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? 1 : 0;
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -636,7 +629,7 @@
   }
 
   test_visitConditionalExpression_lazy_true_int_invalid() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? 1: new C();
 ''');
     DartObjectImpl result = _evaluateConstant('c',
@@ -646,7 +639,7 @@
   }
 
   test_visitConditionalExpression_lazy_true_invalid_int() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = true ? new C() : 0;
 class C {}
 ''');
@@ -654,7 +647,7 @@
   }
 
   test_visitIsExpression_is_instanceOfSameClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is A;
 class A {
@@ -667,7 +660,7 @@
   }
 
   test_visitIsExpression_is_instanceOfSubclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const B();
 const b = a is A;
 class A {
@@ -683,7 +676,7 @@
   }
 
   test_visitIsExpression_is_instanceOfSuperclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is B;
 class A {
@@ -699,7 +692,7 @@
   }
 
   test_visitIsExpression_is_instanceOfUnrelatedClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is B;
 class A {
@@ -715,7 +708,7 @@
   }
 
   test_visitIsExpression_is_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a is A;
 class A {}
@@ -726,7 +719,7 @@
   }
 
   test_visitIsExpression_is_null_dynamic() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a is dynamic;
 class A {}
@@ -737,7 +730,7 @@
   }
 
   test_visitIsExpression_is_null_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a is Null;
 class A {}
@@ -748,7 +741,7 @@
   }
 
   test_visitIsExpression_is_null_object() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a is Object;
 class A {}
@@ -759,7 +752,7 @@
   }
 
   test_visitIsExpression_isNot_instanceOfSameClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is! A;
 class A {
@@ -772,7 +765,7 @@
   }
 
   test_visitIsExpression_isNot_instanceOfSubclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const B();
 const b = a is! A;
 class A {
@@ -788,7 +781,7 @@
   }
 
   test_visitIsExpression_isNot_instanceOfSuperclass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is! B;
 class A {
@@ -804,7 +797,7 @@
   }
 
   test_visitIsExpression_isNot_instanceOfUnrelatedClass() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = const A();
 const b = a is! B;
 class A {
@@ -820,7 +813,7 @@
   }
 
   test_visitIsExpression_isNot_null() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const a = null;
 const b = a is! A;
 class A {}
@@ -835,7 +828,7 @@
 class ConstantVisitorWithFlowControlAndSpreadCollectionsTest
     extends ConstantVisitorTestSupport {
   test_listLiteral_ifElement_false_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, if (1 < 0) 2 else 3, 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -844,7 +837,7 @@
   }
 
   test_listLiteral_ifElement_false_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, if (1 < 0) 2, 3];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -853,7 +846,7 @@
   }
 
   test_listLiteral_ifElement_true_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, if (1 > 0) 2 else 3, 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -862,7 +855,7 @@
   }
 
   test_listLiteral_ifElement_true_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, if (1 > 0) 2, 3];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -871,7 +864,7 @@
   }
 
   test_listLiteral_nested() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, if (1 > 0) if (2 > 1) 2, 3];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -882,7 +875,7 @@
   }
 
   test_listLiteral_spreadElement() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = [1, ...[2, 3], 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -891,7 +884,7 @@
   }
 
   test_mapLiteral_ifElement_false_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -904,7 +897,7 @@
   }
 
   test_mapLiteral_ifElement_false_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -917,7 +910,7 @@
   }
 
   test_mapLiteral_ifElement_true_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -930,7 +923,7 @@
   }
 
   test_mapLiteral_ifElement_true_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -945,7 +938,7 @@
   @failingTest
   test_mapLiteral_nested() async {
     // Fails because we're not yet parsing nested elements.
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) if (2 > 1) {'b' : 2}, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -958,7 +951,7 @@
   }
 
   test_mapLiteral_spreadElement() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -972,7 +965,7 @@
   }
 
   test_setLiteral_ifElement_false_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, if (1 < 0) 2 else 3, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -981,7 +974,7 @@
   }
 
   test_setLiteral_ifElement_false_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, if (1 < 0) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -990,7 +983,7 @@
   }
 
   test_setLiteral_ifElement_true_withElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, if (1 > 0) 2 else 3, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -999,7 +992,7 @@
   }
 
   test_setLiteral_ifElement_true_withoutElse() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, if (1 > 0) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -1008,7 +1001,7 @@
   }
 
   test_setLiteral_nested() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, if (1 > 0) if (2 > 1) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
@@ -1017,7 +1010,7 @@
   }
 
   test_setLiteral_spreadElement() async {
-    await _resolveTestCode('''
+    await resolveTestCode('''
 const c = {1, ...{2, 3}, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
index a18956a..b2431e5 100644
--- a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -119,17 +119,13 @@
   }
 
   Future<void> _assertConst(String code) async {
-    addTestFile(code);
-    await resolveTestFile();
-
+    await resolveTestCode(code);
     var type = findNode.variableDeclarationList('x;').type;
     expect(isConstantTypeExpression(type), isTrue);
   }
 
   Future<void> _assertNotConst(String code) async {
-    addTestFile(code);
-    await resolveTestFile();
-
+    await resolveTestCode(code);
     var type = findNode.variableDeclarationList('x;').type;
     expect(isConstantTypeExpression(type), isFalse);
   }
@@ -847,9 +843,7 @@
   }
 
   _assertConst(String code, AstNode Function() getNode) async {
-    addTestFile(code);
-    await resolveTestFile();
-
+    await resolveTestCode(code);
     var node = getNode();
     var notConstList = getNotPotentiallyConstants(node);
     expect(notConstList, isEmpty);
@@ -857,9 +851,7 @@
 
   _assertNotConst(String code, AstNode Function() getNode,
       List<AstNode> Function() getNotConstList) async {
-    addTestFile(code);
-    await resolveTestFile();
-
+    await resolveTestCode(code);
     var node = getNode();
     var notConstList = getNotPotentiallyConstants(node);
 
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index f337c05..d26101c 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -9,8 +9,6 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/test_support.dart';
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DartObjectImplTest);
@@ -23,7 +21,7 @@
     throwsA(new TypeMatcher<EvaluationException>());
 
 @reflectiveTest
-class DartObjectImplTest extends EngineTestCase {
+class DartObjectImplTest {
   TypeProvider _typeProvider = new TestTypeProvider();
 
   void test_add_knownDouble_knownDouble() {
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index a3d5a04..f0489be 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -20,7 +20,6 @@
 
 import '../../../generated/elements_types_mixin.dart';
 import '../../../generated/test_analysis_context.dart';
-import '../../../generated/test_support.dart';
 import '../resolution/driver_resolution.dart';
 
 main() {
@@ -869,7 +868,7 @@
 }
 
 @reflectiveTest
-class CompilationUnitElementImplTest extends EngineTestCase {
+class CompilationUnitElementImplTest {
   void test_getEnum_declared() {
     TestTypeProvider typeProvider = new TestTypeProvider();
     CompilationUnitElementImpl unit =
@@ -921,14 +920,12 @@
 }
 void f(@A('x') int p) {}
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 main() {
   f(3);
 }
 ''');
-    await resolveTestFile();
-
     var argument = findNode.integerLiteral('3');
     ParameterElement parameter = argument.staticParameterElement;
 
@@ -1049,7 +1046,7 @@
 }
 
 @reflectiveTest
-class ElementLocationImplTest extends EngineTestCase {
+class ElementLocationImplTest {
   void test_create_encoding() {
     String encoding = "a;b;c";
     ElementLocationImpl location = new ElementLocationImpl.con2(encoding);
@@ -1116,11 +1113,9 @@
 @reflectiveTest
 class FieldElementImplTest extends DriverResolutionTest {
   test_isEnumConstant() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum B {B1, B2, B3}
 ''');
-    await resolveTestFile();
-
     var B = findElement.enum_('B');
 
     FieldElement b2Element = B.getField('B2');
@@ -3434,16 +3429,16 @@
 }
 
 @reflectiveTest
-class LibraryElementImplTest extends EngineTestCase {
+class LibraryElementImplTest {
   void test_creation() {
     expect(
-        new LibraryElementImpl.forNode(createAnalysisContext(), null,
+        new LibraryElementImpl.forNode(TestAnalysisContext(), null,
             AstTestFactory.libraryIdentifier2(["l"]), true),
         isNotNull);
   }
 
   void test_getImportedLibraries() {
-    AnalysisContext context = createAnalysisContext();
+    AnalysisContext context = TestAnalysisContext();
     LibraryElementImpl library1 = ElementFactory.library(context, "l1");
     LibraryElementImpl library2 = ElementFactory.library(context, "l2");
     LibraryElementImpl library3 = ElementFactory.library(context, "l3");
@@ -3467,7 +3462,7 @@
   }
 
   void test_getPrefixes() {
-    AnalysisContext context = createAnalysisContext();
+    AnalysisContext context = TestAnalysisContext();
     LibraryElementImpl library = ElementFactory.library(context, "l1");
     PrefixElement prefixA =
         new PrefixElementImpl.forNode(AstTestFactory.identifier3("a"));
@@ -3492,7 +3487,7 @@
   }
 
   void test_getUnits() {
-    AnalysisContext context = createAnalysisContext();
+    AnalysisContext context = TestAnalysisContext();
     LibraryElementImpl library = ElementFactory.library(context, "test");
     CompilationUnitElement unitLib = library.definingCompilationUnit;
     CompilationUnitElementImpl unitA =
@@ -3505,7 +3500,7 @@
   }
 
   void test_setImports() {
-    AnalysisContext context = createAnalysisContext();
+    AnalysisContext context = TestAnalysisContext();
     LibraryElementImpl library = new LibraryElementImpl.forNode(
         context, null, AstTestFactory.libraryIdentifier2(["l1"]), true);
     List<ImportElementImpl> expectedImports = [
@@ -3522,7 +3517,7 @@
 }
 
 @reflectiveTest
-class PropertyAccessorElementImplTest extends EngineTestCase {
+class PropertyAccessorElementImplTest {
   void test_matchesHandle_getter() {
     CompilationUnitElementImpl compilationUnitElement =
         ElementFactory.compilationUnit('foo.dart');
@@ -3572,14 +3567,12 @@
     newFile('/test/lib/a.dart', content: r'''
 const int C = 42;
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 main() {
   print(C);
 }
 ''');
-    await resolveTestFile();
-
     SimpleIdentifier argument = findNode.simple('C);');
     PropertyAccessorElementImpl getter = argument.staticElement;
     TopLevelVariableElement constant = getter.variable;
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 6b6aa60..0b79a60 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -36,7 +36,6 @@
 @reflectiveTest
 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;
 
@@ -592,64 +591,6 @@
         throwsA(new TypeMatcher<ArgumentError>()));
   }
 
-  test_synthetic_substitute_share_returnType_and_parameters() {
-    // int Function<U extends T>(int x)
-    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], [typeParameterType(t)]);
-    basicChecks(substituted,
-        element: isNull,
-        displayName: 'int Function<U extends Object>(int)',
-        returnType: same(f.returnType),
-        typeFormals: hasLength(1),
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(intType)],
-        parameters: same(f.parameters));
-    expect(substituted.typeFormals[0].name, 'U');
-    expect(substituted.typeFormals[0].bound, same(objectType));
-  }
-
-  test_synthetic_substitute_share_returnType_and_typeFormals() {
-    // int Function<U>(T x, U y)
-    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], [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), typeParameterType(u)],
-        parameters: hasLength(2));
-  }
-
-  test_synthetic_substitute_share_typeFormals_and_parameters() {
-    // T Function<U>(U x)
-    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: [typeParameterType(u)],
-        parameters: same(f.parameters));
-  }
-
   test_synthetic_substitute_unchanged() {
     // dynamic Function<U>(U x)
     var t = typeParameter('T');
@@ -877,13 +818,8 @@
         typeFormals: hasLength(3),
         typeParameters: [same(u)],
         typeArguments: [same(objectType)]);
-    if (bug_33300_fixed) {
-      expect(substituted.displayName,
-          'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
-    } else {
-      expect(substituted.displayName,
-          'Map<S, V> Function<S extends T extends Object,T extends Object,V extends T>()');
-    }
+    expect(substituted.displayName,
+        'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
     var v2 = substituted.typeFormals[2];
@@ -933,13 +869,8 @@
         typeFormals: hasLength(3),
         typeParameters: [same(u)],
         typeArguments: [same(objectType)]);
-    if (bug_33300_fixed) {
-      expect(substituted.displayName,
-          'void Function<S extends T,T extends Object,V extends T>(S, V)');
-    } else {
-      expect(substituted.displayName,
-          'void Function<S extends T extends Object,T extends Object,V extends T>(S, V)');
-    }
+    expect(substituted.displayName,
+        'void Function<S extends T,T extends Object,V extends T>(S, V)');
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
     var v2 = substituted.typeFormals[2];
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 71b0757..b2da098 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
@@ -30,7 +30,7 @@
   }
 
   test_getInherited_closestSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -43,8 +43,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -53,7 +51,7 @@
   }
 
   test_getInherited_interfaces() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo();
 }
@@ -66,8 +64,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -76,7 +72,7 @@
   }
 
   test_getInherited_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -89,8 +85,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -99,7 +93,7 @@
   }
 
   test_getInherited_preferImplemented() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -112,8 +106,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -122,85 +114,75 @@
   }
 
   test_getInheritedConcreteMap_accessor_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedConcreteMap_accessor_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_accessor_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int get foo => 0;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedConcreteMap_implicitExtends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 ''');
-    await resolveTestFile();
     _assertInheritedConcreteMap('A', '');
   }
 
   test_getInheritedConcreteMap_method_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedConcreteMap_method_extends_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_method_extends_invalidForImplements() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo(int x, {int y});
   void bar(String s);
@@ -212,43 +194,37 @@
 
 class C extends A implements I {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('C', r'''
 A.foo: void Function(int)
 ''');
   }
 
   test_getInheritedConcreteMap_method_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_method_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedConcreteMap_method_with2() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
@@ -259,8 +235,6 @@
 
 class C extends Object with A, B {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('C', r'''
 A.foo: void Function()
 B.bar: void Function()
@@ -268,52 +242,46 @@
   }
 
   test_getInheritedMap_accessor_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_accessor_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_accessor_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int get foo => 0;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_closestSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -324,23 +292,19 @@
 
 class X extends B {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('X', r'''
 B.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_field_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -348,15 +312,13 @@
   }
 
   test_getInheritedMap_field_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -364,15 +326,13 @@
   }
 
   test_getInheritedMap_field_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int foo;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -380,61 +340,53 @@
   }
 
   test_getInheritedMap_implicitExtendsObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', '');
   }
 
   test_getInheritedMap_method_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_method_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_method_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_preferImplemented() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -447,15 +399,13 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('X', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_union_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int foo();
   void bar();
@@ -468,15 +418,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.bar: void Function()
 ''');
   }
 
   test_getInheritedMap_union_differentNames() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int foo();
 }
@@ -487,8 +435,6 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I.foo: int Function()
 J.bar: double Function()
@@ -496,7 +442,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_getters() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int get foo;
 }
@@ -507,15 +453,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo();
 }
@@ -526,15 +470,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_setters() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void set foo(num _);
 }
@@ -546,8 +488,6 @@
 abstract class A implements I, J {}
 abstract class B implements J, I {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I.foo=: void Function(num)
 ''');
@@ -558,7 +498,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_getters() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -578,8 +518,6 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I3.foo: C Function()
 ''');
@@ -590,7 +528,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -610,15 +548,13 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I1.foo: void Function(A)
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_setters() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -638,8 +574,6 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I1.foo=: void Function(A)
 ''');
@@ -650,7 +584,7 @@
   }
 
   test_getInheritedMap_union_oneSubtype_2_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   int foo();
 }
@@ -662,8 +596,6 @@
 abstract class A implements I1, I2 {}
 abstract class B implements I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I2.foo: int Function([int])
 ''');
@@ -674,7 +606,7 @@
   }
 
   test_getInheritedMap_union_oneSubtype_3_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   int foo();
 }
@@ -690,8 +622,6 @@
 abstract class A implements I1, I2, I3 {}
 abstract class B implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I3.foo: int Function([int, int])
 ''');
@@ -702,7 +632,7 @@
   }
 
   test_getMember() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   void f(int i);
 }
@@ -713,8 +643,6 @@
 
 abstract class C implements I1, I2 {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'C',
       name: 'f',
@@ -723,13 +651,11 @@
   }
 
   test_getMember_concrete() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -739,13 +665,11 @@
   }
 
   test_getMember_concrete_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -754,15 +678,13 @@
   }
 
   test_getMember_concrete_fromMixedClass() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class X with A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -772,7 +694,7 @@
   }
 
   test_getMember_concrete_fromMixedClass2() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -781,8 +703,6 @@
 
 class X with B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -792,7 +712,7 @@
   }
 
   test_getMember_concrete_fromMixedClass_skipObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   String toString() => 'A';
 }
@@ -801,8 +721,6 @@
 
 class X extends A with B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'toString',
@@ -812,15 +730,13 @@
   }
 
   test_getMember_concrete_fromMixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin M {
   void foo() {}
 }
 
 class X with M {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -830,7 +746,7 @@
   }
 
   test_getMember_concrete_fromSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -839,8 +755,6 @@
 
 abstract class C extends B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -857,11 +771,9 @@
   }
 
   test_getMember_concrete_missing() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -870,7 +782,7 @@
   }
 
   test_getMember_concrete_noSuchMethod() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -881,8 +793,6 @@
 
 abstract class C extends B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -899,7 +809,7 @@
   }
 
   test_getMember_concrete_noSuchMethod_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo();
 
@@ -908,9 +818,7 @@
 
 abstract class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
-    // noSuchMethod forwarders are not mixed-in.
+// noSuchMethod forwarders are not mixed-in.
     // https://github.com/dart-lang/sdk/issues/33553#issuecomment-424638320
     _assertGetMember(
       className: 'B',
@@ -920,7 +828,7 @@
   }
 
   test_getMember_concrete_noSuchMethod_moreSpecificSignature() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -933,8 +841,6 @@
   void foo([int a]);
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'C',
       name: 'foo',
@@ -944,7 +850,7 @@
   }
 
   test_getMember_preferLatest_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -963,8 +869,6 @@
 
 class X extends A with M1, M2 implements I {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -973,7 +877,7 @@
   }
 
   test_getMember_preferLatest_superclass() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -988,8 +892,6 @@
 
 class X extends B implements I {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -998,7 +900,7 @@
   }
 
   test_getMember_preferLatest_this() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -1011,8 +913,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -1021,7 +921,7 @@
   }
 
   test_getMember_super_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
@@ -1030,8 +930,6 @@
   noSuchMethod(_) {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1040,15 +938,13 @@
   }
 
   test_getMember_super_forMixin_interface() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 mixin M implements A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'M',
       name: 'foo',
@@ -1057,15 +953,13 @@
   }
 
   test_getMember_super_forMixin_superclassConstraint() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 mixin M on A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'M',
       name: 'foo',
@@ -1075,7 +969,7 @@
   }
 
   test_getMember_super_fromMixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin M {
   void foo() {}
 }
@@ -1084,8 +978,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -1095,7 +987,7 @@
   }
 
   test_getMember_super_fromSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -1104,8 +996,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1115,13 +1005,11 @@
   }
 
   test_getMember_super_missing() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1130,7 +1018,7 @@
   }
 
   test_getMember_super_noSuchMember() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo();
   noSuchMethod(_) {}
@@ -1140,8 +1028,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
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 3a5221c..f8901a3 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -31,7 +31,7 @@
   }
 
   test_getInherited_closestSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -44,8 +44,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -54,7 +52,7 @@
   }
 
   test_getInherited_interfaces() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo();
 }
@@ -67,8 +65,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -77,7 +73,7 @@
   }
 
   test_getInherited_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -90,8 +86,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -100,7 +94,7 @@
   }
 
   test_getInherited_preferImplemented() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -113,8 +107,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetInherited(
       className: 'X',
       name: 'foo',
@@ -123,85 +115,75 @@
   }
 
   test_getInheritedConcreteMap_accessor_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedConcreteMap_accessor_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_accessor_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int get foo => 0;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedConcreteMap_implicitExtends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 ''');
-    await resolveTestFile();
     _assertInheritedConcreteMap('A', '');
   }
 
   test_getInheritedConcreteMap_method_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedConcreteMap_method_extends_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_method_extends_invalidForImplements() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo(int x, {int y});
   void bar(String s);
@@ -213,43 +195,37 @@
 
 class C extends A implements I {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('C', r'''
 A.foo: void Function(int)
 ''');
   }
 
   test_getInheritedConcreteMap_method_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', '');
   }
 
   test_getInheritedConcreteMap_method_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedConcreteMap_method_with2() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
@@ -260,8 +236,6 @@
 
 class C extends Object with A, B {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedConcreteMap('C', r'''
 A.foo: void Function()
 B.bar: void Function()
@@ -269,52 +243,46 @@
   }
 
   test_getInheritedMap_accessor_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_accessor_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo => 0;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_accessor_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int get foo => 0;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_closestSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -325,23 +293,19 @@
 
 class X extends B {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('X', r'''
 B.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_field_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo;
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -349,15 +313,13 @@
   }
 
   test_getInheritedMap_field_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo;
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -365,15 +327,13 @@
   }
 
   test_getInheritedMap_field_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   int foo;
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: int Function()
 A.foo=: void Function(int)
@@ -381,61 +341,53 @@
   }
 
   test_getInheritedMap_implicitExtendsObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', '');
   }
 
   test_getInheritedMap_method_extends() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_method_implements() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 abstract class B implements A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_method_with() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A {
   void foo() {}
 }
 
 class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('B', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_preferImplemented() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -448,15 +400,13 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('X', r'''
 A.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_union_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int foo();
   void bar();
@@ -469,15 +419,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.bar: void Function()
 ''');
   }
 
   test_getInheritedMap_union_differentNames() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int foo();
 }
@@ -488,8 +436,6 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I.foo: int Function()
 J.bar: double Function()
@@ -497,7 +443,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_getters() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   int get foo;
 }
@@ -508,15 +454,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.foo: int Function()
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void foo();
 }
@@ -527,15 +471,13 @@
 
 abstract class A implements I, J {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 J.foo: void Function()
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_2_setters() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I {
   void set foo(num _);
 }
@@ -547,8 +489,6 @@
 abstract class A implements I, J {}
 abstract class B implements J, I {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I.foo=: void Function(num)
 ''');
@@ -559,7 +499,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_getters() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -579,8 +519,6 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I3.foo: C Function()
 ''');
@@ -591,7 +529,7 @@
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -611,15 +549,13 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I1.foo: void Function(A)
 ''');
   }
 
   test_getInheritedMap_union_multipleSubtypes_3_setters() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B extends A {}
 class C extends B {}
@@ -639,8 +575,6 @@
 abstract class D implements I1, I2, I3 {}
 abstract class E implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('D', r'''
 I1.foo=: void Function(A)
 ''');
@@ -651,7 +585,7 @@
   }
 
   test_getInheritedMap_union_oneSubtype_2_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   int foo();
 }
@@ -663,8 +597,6 @@
 abstract class A implements I1, I2 {}
 abstract class B implements I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I2.foo: int Function([int])
 ''');
@@ -675,7 +607,7 @@
   }
 
   test_getInheritedMap_union_oneSubtype_3_methods() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   int foo();
 }
@@ -691,8 +623,6 @@
 abstract class A implements I1, I2, I3 {}
 abstract class B implements I3, I2, I1 {}
 ''');
-    await resolveTestFile();
-
     _assertInheritedMap('A', r'''
 I3.foo: int Function([int, int])
 ''');
@@ -703,7 +633,7 @@
   }
 
   test_getMember() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class I1 {
   void f(int i);
 }
@@ -714,8 +644,6 @@
 
 abstract class C implements I1, I2 {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'C',
       name: 'f',
@@ -724,13 +652,11 @@
   }
 
   test_getMember_concrete() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -740,13 +666,11 @@
   }
 
   test_getMember_concrete_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -755,15 +679,13 @@
   }
 
   test_getMember_concrete_fromMixedClass() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
 
 class X with A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -773,7 +695,7 @@
   }
 
   test_getMember_concrete_fromMixedClass2() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -782,8 +704,6 @@
 
 class X with B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -793,7 +713,7 @@
   }
 
   test_getMember_concrete_fromMixedClass_skipObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   String toString() => 'A';
 }
@@ -802,8 +722,6 @@
 
 class X extends A with B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'toString',
@@ -813,15 +731,13 @@
   }
 
   test_getMember_concrete_fromMixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin M {
   void foo() {}
 }
 
 class X with M {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -831,7 +747,7 @@
   }
 
   test_getMember_concrete_fromSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -840,8 +756,6 @@
 
 abstract class C extends B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -858,11 +772,9 @@
   }
 
   test_getMember_concrete_missing() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'A',
       name: 'foo',
@@ -871,7 +783,7 @@
   }
 
   test_getMember_concrete_noSuchMethod() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -882,8 +794,6 @@
 
 abstract class C extends B {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -900,7 +810,7 @@
   }
 
   test_getMember_concrete_noSuchMethod_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo();
 
@@ -909,9 +819,7 @@
 
 abstract class B extends Object with A {}
 ''');
-    await resolveTestFile();
-
-    // noSuchMethod forwarders are not mixed-in.
+// noSuchMethod forwarders are not mixed-in.
     // https://github.com/dart-lang/sdk/issues/33553#issuecomment-424638320
     _assertGetMember(
       className: 'B',
@@ -921,7 +829,7 @@
   }
 
   test_getMember_concrete_noSuchMethod_moreSpecificSignature() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -934,8 +842,6 @@
   void foo([int a]);
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'C',
       name: 'foo',
@@ -945,7 +851,7 @@
   }
 
   test_getMember_preferLatest_mixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -964,8 +870,6 @@
 
 class X extends A with M1, M2 implements I {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -974,7 +878,7 @@
   }
 
   test_getMember_preferLatest_superclass() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -989,8 +893,6 @@
 
 class X extends B implements I {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -999,7 +901,7 @@
   }
 
   test_getMember_preferLatest_this() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -1012,8 +914,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -1022,7 +922,7 @@
   }
 
   test_getMember_super_abstract() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
@@ -1031,8 +931,6 @@
   noSuchMethod(_) {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1041,15 +939,13 @@
   }
 
   test_getMember_super_forMixin_interface() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 mixin M implements A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'M',
       name: 'foo',
@@ -1058,15 +954,13 @@
   }
 
   test_getMember_super_forMixin_superclassConstraint() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo();
 }
 
 mixin M on A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'M',
       name: 'foo',
@@ -1076,7 +970,7 @@
   }
 
   test_getMember_super_fromMixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin M {
   void foo() {}
 }
@@ -1085,8 +979,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'X',
       name: 'foo',
@@ -1096,7 +988,7 @@
   }
 
   test_getMember_super_fromSuper() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -1105,8 +997,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1116,13 +1006,11 @@
   }
 
   test_getMember_super_missing() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 class B extends A {}
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
@@ -1131,7 +1019,7 @@
   }
 
   test_getMember_super_noSuchMember() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo();
   noSuchMethod(_) {}
@@ -1141,8 +1029,6 @@
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-
     _assertGetMember(
       className: 'B',
       name: 'foo',
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 93095da..17352e4 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -7,6 +7,7 @@
 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:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -256,6 +257,11 @@
     _assertIdenticalType(type, {U: doubleType});
   }
 
+  test_unknownInferredType() async {
+    var T = typeParameter('T');
+    _assertIdenticalType(UnknownInferredType.instance, {T: intType});
+  }
+
   test_void() async {
     var T = typeParameter('T');
     _assertIdenticalType(typeProvider.voidType, {T: intType});
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index e556a7f..ea4bd89 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -19,14 +19,12 @@
 @reflectiveTest
 class AssignmentDriverResolutionTest extends DriverResolutionTest {
   test_compound_indexExpression() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var x = <num>[1, 2, 3];
   x[0] += 4;
 }
 ''');
-    await resolveTestFile();
-
     AssignmentExpression assignment = findNode.assignment('+= 4');
     assertElement(assignment, numElement.getMethod('+'));
     assertType(assignment, 'num'); // num + int = num
@@ -47,14 +45,12 @@
   }
 
   test_compound_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   num v = 0;
   v += 3;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('v += 3');
     assertElement(assignment, numElement.getMethod('+'));
     assertType(assignment, 'num'); // num + int = num
@@ -68,7 +64,7 @@
   }
 
   test_compound_prefixedIdentifier() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var c = new C();
   c.f += 2;
@@ -77,8 +73,6 @@
   num f;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('c.f += 2');
     assertElement(assignment, numElement.getMethod('+'));
     assertType(assignment, 'num'); // num + int = num
@@ -99,7 +93,7 @@
   }
 
   test_compound_propertyAccess() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   new C().f += 2;
 }
@@ -107,8 +101,6 @@
   num f;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f += 2');
     assertElement(assignment, numElement.getMethod('+'));
     assertType(assignment, 'num'); // num + int = num
@@ -186,12 +178,11 @@
   }
 
   test_in_const_context() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   const [x = y];
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x =');
@@ -204,13 +195,11 @@
   }
 
   test_indexExpression_cascade() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   <int, double>{}..[1] = 2.0;
 }
 ''');
-    await resolveTestFile();
-
     var cascade = findNode.cascade('<int, double>');
     assertType(cascade, 'Map<int, double>');
 
@@ -233,14 +222,13 @@
   }
 
   test_notLValue_parenthesized() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int a, b;
 double c = 0.0;
 main() {
   (a + b) = c;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var parenthesized = findNode.parenthesized('(a + b)');
@@ -256,14 +244,12 @@
   }
 
   test_nullAware_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   String v;
   v ??= 'test';
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('v ??=');
     assertElementNull(assignment);
     assertType(assignment, 'String');
@@ -277,7 +263,7 @@
   }
 
   test_propertyAccess_forwardingStub() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int f;
 }
@@ -289,8 +275,6 @@
   new B().f = 1;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f = 1');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -311,14 +295,12 @@
   }
 
   test_simple_indexExpression() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var x = <int>[1, 2, 3];
   x[0] = 4;
 }
 ''');
-    await resolveTestFile();
-
     AssignmentExpression assignment = findNode.assignment('= 4');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -339,7 +321,7 @@
   }
 
   test_simple_instanceField_unqualified() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   num f = 0;
   foo() {
@@ -347,8 +329,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f = 2;');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -362,14 +342,12 @@
   }
 
   test_simple_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   num v = 0;
   v = 2;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('v = 2;');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -383,7 +361,7 @@
   }
 
   test_simple_prefixedIdentifier() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var c = new C();
   c.f = 2;
@@ -392,8 +370,6 @@
   num f;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('c.f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -414,7 +390,7 @@
   }
 
   test_simple_prefixedIdentifier_staticField() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   C.f = 2;
 }
@@ -423,8 +399,6 @@
 }
 ''');
 
-    await resolveTestFile();
-
     var assignment = findNode.assignment('C.f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -446,7 +420,7 @@
   }
 
   test_simple_propertyAccess() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   new C().f = 2;
 }
@@ -454,8 +428,6 @@
   num f;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -476,7 +448,7 @@
   }
 
   test_simple_propertyAccess_chained() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var a = new A();
   a.b.f = 2;
@@ -488,8 +460,6 @@
   num f;
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('a.b.f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -517,7 +487,7 @@
   }
 
   test_simple_propertyAccess_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   new C().f = 2;
 }
@@ -525,8 +495,6 @@
   void set f(num _) {}
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -547,7 +515,7 @@
   }
 
   test_simple_staticField_unqualified() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static num f = 0;
   foo() {
@@ -555,8 +523,6 @@
   }
 }
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('f = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -570,14 +536,12 @@
   }
 
   test_simple_topLevelVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   v = 2;
 }
 num v = 0;
 ''');
-    await resolveTestFile();
-
     var assignment = findNode.assignment('v = 2');
     assertElementNull(assignment);
     assertType(assignment, 'int');
@@ -591,13 +555,12 @@
   }
 
   test_to_class() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {}
 void f(int x) {
   C = x;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var cRef = findNode.simple('C =');
@@ -612,14 +575,13 @@
   test_to_class_ambiguous() async {
     newFile('/test/lib/a.dart', content: 'class C {}');
     newFile('/test/lib/b.dart', content: 'class C {}');
-    addTestFile('''
+    await resolveTestCode('''
 import 'a.dart';
 import 'b.dart';
 void f(int x) {
   C = x;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x;');
@@ -628,12 +590,11 @@
   }
 
   test_to_final_parameter() async {
-    addTestFile('''
+    await resolveTestCode('''
 f(final int x) {
   x += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -642,13 +603,12 @@
   }
 
   test_to_final_variable_local() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   final x = 1;
   x += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -657,7 +617,7 @@
   }
 
   test_to_getter_instance_direct() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   int get x => 0;
 }
@@ -665,7 +625,6 @@
   c.x += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -674,7 +633,7 @@
   }
 
   test_to_getter_instance_via_implicit_this() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   int get x => 0;
   f() {
@@ -682,7 +641,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -691,7 +649,7 @@
   }
 
   test_to_getter_static_direct() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   static int get x => 0;
 }
@@ -699,7 +657,6 @@
   C.x += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -708,7 +665,7 @@
   }
 
   test_to_getter_static_via_scope() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   static int get x => 0;
   f() {
@@ -716,7 +673,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -725,13 +681,12 @@
   }
 
   test_to_getter_top_level() async {
-    addTestFile('''
+    await resolveTestCode('''
 int get x => 0;
 main() {
   x += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -740,12 +695,11 @@
   }
 
   test_to_non_lvalue() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(int x, double y, String z) {
   x + y = z;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +');
@@ -762,12 +716,11 @@
   }
 
   test_to_postfix_increment() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   x++ = y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x++');
@@ -780,12 +733,11 @@
   }
 
   test_to_postfix_increment_compound() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   x++ += y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x++');
@@ -798,12 +750,11 @@
   }
 
   test_to_postfix_increment_null_aware() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   x++ ??= y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x++');
@@ -819,13 +770,12 @@
     newFile('/test/lib/a.dart', content: '''
 var x = 0;
 ''');
-    addTestFile('''
+    await resolveTestCode('''
 import 'a.dart' as p;
 main() {
   p += 2;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var pRef = findNode.simple('p +=');
@@ -834,12 +784,11 @@
   }
 
   test_to_prefix_increment() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   ++x = y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x =');
@@ -852,12 +801,11 @@
   }
 
   test_to_prefix_increment_compound() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   ++x += y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x +=');
@@ -870,12 +818,11 @@
   }
 
   test_to_prefix_increment_null_aware() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(num x, int y) {
   ++x ??= y;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x ??=');
@@ -888,14 +835,13 @@
   }
 
   test_types_local() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int a;
 bool b;
 main() {
   a = b;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a = b');
@@ -907,11 +853,10 @@
   }
 
   test_types_top() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int a = 0;
 bool b = a;
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var bDeclaration = findNode.variableDeclaration('b =');
@@ -926,11 +871,10 @@
   }
 
   test_types_top_const() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 const int a = 0;
 const bool b = a;
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var bDeclaration = findNode.variableDeclaration('b =');
@@ -945,13 +889,12 @@
   }
 
   test_unresolved_left_identifier_compound() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int b;
 main() {
   a += b;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a += b');
@@ -966,13 +909,12 @@
   }
 
   test_unresolved_left_identifier_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int b;
 main() {
   a = b;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a = b');
@@ -987,13 +929,12 @@
   }
 
   test_unresolved_left_indexed1_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int c;
 main() {
   a[b] = c;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a[b] = c');
@@ -1015,7 +956,7 @@
   }
 
   test_unresolved_left_indexed2_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 A a;
 int c;
 main() {
@@ -1023,7 +964,6 @@
 }
 class A {}
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a[b] = c');
@@ -1045,7 +985,7 @@
   }
 
   test_unresolved_left_indexed3_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 A a;
 int c;
 main() {
@@ -1055,7 +995,6 @@
   operator[]=(double b) {}
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a[b] = c');
@@ -1077,14 +1016,13 @@
   }
 
   test_unresolved_left_indexed4_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 double b;
 int c;
 main() {
   a[b] = c;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a[b] = c');
@@ -1106,13 +1044,12 @@
   }
 
   test_unresolved_left_prefixed1_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int c;
 main() {
   a.b = c;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a.b = c');
@@ -1134,7 +1071,7 @@
   }
 
   test_unresolved_left_prefixed2_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 A a;
 int c;
@@ -1142,7 +1079,6 @@
   a.b = c;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a.b = c');
@@ -1164,13 +1100,12 @@
   }
 
   test_unresolved_left_property1_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int d;
 main() {
   a.b.c = d;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a.b.c = d');
@@ -1198,7 +1133,7 @@
   }
 
   test_unresolved_left_property2_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 A a;
 int d;
 main() {
@@ -1206,7 +1141,6 @@
 }
 class A {}
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var assignment = findNode.assignment('a.b.c = d');
@@ -1234,7 +1168,7 @@
   }
 
   test_unresolved_left_property3_simple() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 A a;
 int d;
 main() {
@@ -1243,7 +1177,6 @@
 class A { B b; }
 class B {}
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
     var bElement = findElement.field('b');
 
@@ -1272,12 +1205,11 @@
   }
 
   test_with_synthetic_lhs() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(int x) {
   = x;
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x;');
@@ -1286,14 +1218,13 @@
   }
 
   test_with_synthetic_lhs_in_method() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   void f(int x) {
     = x;
   }
 }
 ''');
-    await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
     var xRef = findNode.simple('x;');
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 1cb1ed5..689444f 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -15,25 +15,23 @@
 @reflectiveTest
 class ClassAliasDriverResolutionTest extends DriverResolutionTest {
   test_defaultConstructor() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class M {}
 class X = A with M;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertConstructors(findElement.class_('X'), ['X X()']);
   }
 
   test_element() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B {}
 class C {}
 
 class X = A with B implements C;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var x = findElement.class_('X');
@@ -49,7 +47,7 @@
 
   @failingTest
   test_implicitConstructors_const() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   const A();
 }
@@ -60,13 +58,12 @@
 
 const x = const C();
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     // TODO(scheglov) add also negative test with fields
   }
 
   test_implicitConstructors_dependencies() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A(int i);
 }
@@ -76,7 +73,6 @@
 class C2 = C1 with M2;
 class C1 = A with M1;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertConstructors(findElement.class_('C1'), ['C1 C1(int i)']);
@@ -84,7 +80,7 @@
   }
 
   test_implicitConstructors_optionalParameters() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   A.c1(int a);
   A.c2(int a, [int b, int c]);
@@ -95,7 +91,6 @@
 
 class C = A with M;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertConstructors(
@@ -109,7 +104,7 @@
   }
 
   test_implicitConstructors_requiredParameters() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A<T extends num> {
   A(T x, T y);
 }
@@ -118,7 +113,6 @@
 
 class B<E extends num> = A<E> with M;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertConstructors(findElement.class_('B'), ['B<E> B(E x, E y)']);
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index aaa8176..752cb6f 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -19,7 +19,7 @@
 class ClassDriverResolutionTest extends DriverResolutionTest
     with ElementsTypesMixin {
   test_abstractSuperMemberReference_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   get foo;
 }
@@ -29,14 +29,13 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
     assertElement(findNode.simple('foo; // ref'), findElement.getter('foo'));
   }
 
   test_abstractSuperMemberReference_getter2() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class Foo {
   String get foo;
 }
@@ -48,7 +47,6 @@
   String get foo => super.foo; // ref
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
     assertElement(
@@ -58,7 +56,7 @@
   }
 
   test_abstractSuperMemberReference_method_reference() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   foo();
 }
@@ -68,14 +66,13 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
     assertElement(findNode.simple('foo; // ref'), findElement.method('foo'));
   }
 
   test_abstractSuperMemberReference_OK_superHasConcrete_mixinHasAbstract_method() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {}
 }
@@ -90,7 +87,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertElement(
       findNode.simple('foo(); // ref'),
@@ -99,7 +95,7 @@
   }
 
   test_abstractSuperMemberReference_OK_superSuperHasConcrete_getter() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   int get foo => 0;
 }
@@ -112,7 +108,6 @@
   int get bar => super.foo; // ref
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertElement(
       findNode.simple('foo; // ref'),
@@ -121,7 +116,7 @@
   }
 
   test_abstractSuperMemberReference_OK_superSuperHasConcrete_setter() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void set foo(_) {}
 }
@@ -136,7 +131,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertElement(
       findNode.simple('foo = 0;'),
@@ -145,7 +139,7 @@
   }
 
   test_abstractSuperMemberReference_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   set foo(_);
 }
@@ -155,38 +149,35 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
     assertElement(findNode.simple('foo = 0;'), findElement.setter('foo'));
   }
 
   test_conflictingGenericInterfaces_simple() async {
-    addTestFile('''
+    await resolveTestCode('''
 class I<T> {}
 class A implements I<int> {}
 class B implements I<String> {}
 class C extends A implements B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
   }
 
   test_conflictingGenericInterfaces_viaMixin() async {
-    addTestFile('''
+    await resolveTestCode('''
 class I<T> {}
 class A implements I<int> {}
 class B implements I<String> {}
 class C extends A with B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
   }
 
   test_element_allSupertypes() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B {}
 class C {}
@@ -199,7 +190,6 @@
 class X4 extends A with B implements C {}
 class X5 extends A with B, C implements D, E {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var a = findElement.class_('A');
@@ -237,7 +227,7 @@
   }
 
   test_element_allSupertypes_generic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A<T> {}
 class B<T, U> {}
 class C<T> extends B<int, T> {}
@@ -246,7 +236,6 @@
 class X2 extends B<String, List<int>> {}
 class X3 extends C<double> {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var a = findElement.class_('A');
@@ -280,14 +269,13 @@
   }
 
   test_element_allSupertypes_recursive() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A extends B {}
 class B extends C {}
 class C extends A {}
 
 class X extends A {}
 ''');
-    await resolveTestFile();
     assertHasTestErrors();
 
     var a = findElement.class_('A');
@@ -300,33 +288,31 @@
   }
 
   test_error_conflictingConstructorAndStaticField_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   static int foo;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD,
     ]);
   }
 
   test_error_conflictingConstructorAndStaticField_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   static int get foo => 0;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD,
     ]);
   }
 
   test_error_conflictingConstructorAndStaticField_OK_notSameClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   static int foo;
 }
@@ -334,49 +320,45 @@
   B.foo();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_error_conflictingConstructorAndStaticField_OK_notStatic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   int foo;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_error_conflictingConstructorAndStaticField_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   static void set foo(_) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD,
     ]);
   }
 
   test_error_conflictingConstructorAndStaticMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   static void foo() {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
     ]);
   }
 
   test_error_conflictingConstructorAndStaticMethod_OK_notSameClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   static void foo() {}
 }
@@ -384,23 +366,21 @@
   B.foo();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_error_conflictingConstructorAndStaticMethod_OK_notStatic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   void foo() {}
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_error_conflictingFieldAndMethod_inSuper_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   foo() {}
 }
@@ -408,13 +388,12 @@
   int foo;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD]);
   }
 
   test_error_conflictingFieldAndMethod_inSuper_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   foo() {}
 }
@@ -422,13 +401,12 @@
   get foo => 0;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD]);
   }
 
   test_error_conflictingFieldAndMethod_inSuper_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   foo() {}
 }
@@ -436,13 +414,12 @@
   set foo(_) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD]);
   }
 
   test_error_conflictingMethodAndField_inSuper_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int foo;
 }
@@ -450,13 +427,12 @@
   foo() {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD]);
   }
 
   test_error_conflictingMethodAndField_inSuper_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   get foo => 0;
 }
@@ -464,13 +440,12 @@
   foo() {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD]);
   }
 
   test_error_conflictingMethodAndField_inSuper_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   set foo(_) {}
 }
@@ -478,42 +453,38 @@
   foo() {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD]);
   }
 
   test_error_duplicateConstructorDefault() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C();
   C();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
     ]);
   }
 
   test_error_duplicateConstructorName() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   C.foo();
   C.foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
     ]);
   }
 
   test_error_extendsNonClass_dynamic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A extends dynamic {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.EXTENDS_NON_CLASS,
     ]);
@@ -523,11 +494,10 @@
   }
 
   test_error_extendsNonClass_enum() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum E { ONE }
 class A extends E {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.EXTENDS_NON_CLASS,
     ]);
@@ -540,11 +510,10 @@
   }
 
   test_error_extendsNonClass_mixin() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 mixin M {}
 class A extends M {} // ref
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.EXTENDS_NON_CLASS,
     ]);
@@ -557,11 +526,10 @@
   }
 
   test_error_extendsNonClass_variable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 int v;
 class A extends v {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.EXTENDS_NON_CLASS,
     ]);
@@ -571,11 +539,10 @@
   }
 
   test_error_implementsRepeated() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B implements A, A {} // ref
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.IMPLEMENTS_REPEATED]);
 
     var a = findElement.class_('A');
@@ -584,10 +551,9 @@
   }
 
   test_error_implementsRepeated_3times() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {} class C{}
 class B implements A, A, A, A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.IMPLEMENTS_REPEATED,
       CompileTimeErrorCode.IMPLEMENTS_REPEATED,
@@ -596,22 +562,20 @@
   }
 
   test_error_memberWithClassName_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int get C => null;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
   }
 
   test_error_memberWithClassName_getter_static() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static int get C => null;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
 
     var method = findNode.methodDeclaration('C =>');
@@ -621,22 +585,20 @@
   }
 
   test_error_memberWithClassName_setter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   set C(_) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
   }
 
   test_error_memberWithClassName_setter_static() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static set C(_) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
 
     var method = findNode.methodDeclaration('C(_)');
@@ -645,20 +607,19 @@
   }
 
   test_error_mismatchedGetterAndSetterTypes_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int get foo => 0;
   set foo(String _) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
     ]);
   }
 
   test_error_mismatchedGetterAndSetterTypes_interfaces() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get foo {
     return 0;
@@ -671,7 +632,6 @@
 
 abstract class X implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
     ]);
@@ -683,14 +643,13 @@
   int get _foo => 0;
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 class B extends A {
   set _foo(String _) {}
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
@@ -705,13 +664,12 @@
   set _foo(String _) {}
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 import 'b.dart';
 
 class X implements A, B {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
@@ -725,12 +683,11 @@
   set _foo(String _) {}
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 class X implements A, B {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
@@ -740,45 +697,42 @@
   set _foo(String _) {}
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 class B extends A {
   int get _foo => 0;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_error_mismatchedGetterAndSetterTypes_OK_setterParameter_0() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int get foo => 0;
   set foo() {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
     ]);
   }
 
   test_error_mismatchedGetterAndSetterTypes_OK_setterParameter_2() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   int get foo => 0;
   set foo(String p1, String p2) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
     ]);
   }
 
   test_error_mismatchedGetterAndSetterTypes_superGetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get foo => 0;
 }
@@ -787,14 +741,13 @@
   set foo(String _) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
     ]);
   }
 
   test_error_mismatchedGetterAndSetterTypes_superSetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   set foo(String _) {}
 }
@@ -803,14 +756,13 @@
   int get foo => 0;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
     ]);
   }
 
   test_inconsistentInheritance_parameterType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   x(int i);
 }
@@ -819,14 +771,13 @@
 }
 abstract class C implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
     ]);
   }
 
   test_inconsistentInheritance_requiredParameters() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   x();
 }
@@ -835,14 +786,13 @@
 }
 abstract class C implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
     ]);
   }
 
   test_inconsistentInheritance_returnType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   int x();
 }
@@ -851,14 +801,13 @@
 }
 abstract class C implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_getter_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   int get x;
 }
@@ -867,14 +816,13 @@
 }
 abstract class C implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_method_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   int x();
 }
@@ -883,14 +831,13 @@
 }
 abstract class C implements A, B {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
     ]);
   }
 
   test_issue32815() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A<T> extends B<T> {}
 class B<T> extends A<T> {}
 class C<T> extends B<T> implements I<T> {}
@@ -901,15 +848,13 @@
   Iterable<I<int>> x = [new C()];
 }
 ''');
-    await resolveTestFile();
     assertHasTestErrors();
   }
 
   test_recursiveInterfaceInheritance_extends() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A extends B {}
 class B extends A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -917,10 +862,9 @@
   }
 
   test_recursiveInterfaceInheritance_extends_implements() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A extends B {}
 class B implements A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -928,10 +872,9 @@
   }
 
   test_recursiveInterfaceInheritance_implements() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A implements B {}
 class B implements A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -939,10 +882,9 @@
   }
 
   test_recursiveInterfaceInheritance_mixin() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class M1 = Object with M2;
 class M2 = Object with M1;''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -952,12 +894,11 @@
   test_recursiveInterfaceInheritance_mixin_superclass() async {
     // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in
     // addition--that would just be confusing.
-    addTestFile('''
+    await resolveTestCode('''
 class C = D with M;
 class D = C with M;
 class M {}
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
@@ -965,20 +906,18 @@
   }
 
   test_recursiveInterfaceInheritance_tail() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A implements A {}
 class B implements A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS]);
   }
 
   test_recursiveInterfaceInheritance_tail2() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A implements B {}
 abstract class B implements A {}
 class C implements A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -986,12 +925,11 @@
   }
 
   test_recursiveInterfaceInheritance_tail3() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A implements B {}
 abstract class B implements C {}
 abstract class C implements A {}
 class D implements A {}''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
@@ -1000,95 +938,86 @@
   }
 
   test_recursiveInterfaceInheritanceExtends() async {
-    addTestFile("class A extends A {}");
-    await resolveTestFile();
+    await resolveTestCode("class A extends A {}");
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS]);
   }
 
   test_recursiveInterfaceInheritanceExtends_abstract() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C extends C {
   var bar = 0;
   m();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS,
     ]);
   }
 
   test_recursiveInterfaceInheritanceImplements() async {
-    addTestFile("class A implements A {}");
-    await resolveTestFile();
+    await resolveTestCode("class A implements A {}");
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS]);
   }
 
   test_recursiveInterfaceInheritanceImplements_typeAlias() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class M {}
 class B = A with M implements B;''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS]);
   }
 
   test_recursiveInterfaceInheritanceWith() async {
-    addTestFile("class M = Object with M;");
-    await resolveTestFile();
+    await resolveTestCode("class M = Object with M;");
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH,
     ]);
   }
 
   test_undefinedSuperGetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   get g {
     return super.g;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_GETTER]);
   }
 
   test_undefinedSuperMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   m() {
     return super.m();
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_METHOD]);
   }
 
   test_undefinedSuperOperator_binaryExpression() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   operator +(value) {
     return super + value;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
   test_undefinedSuperOperator_indexBoth() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   operator [](index) {
     return super[index]++;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
       StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
@@ -1096,38 +1025,35 @@
   }
 
   test_undefinedSuperOperator_indexGetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   operator [](index) {
     return super[index + 1];
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
   test_undefinedSuperOperator_indexSetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   operator []=(index, value) {
     super[index] = 0;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
   test_undefinedSuperSetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 class B extends A {
   f() {
     super.m = 0;
   }
 }''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_SETTER]);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index fec0505..d09efd3 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -24,11 +24,10 @@
   const A({int p});
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 const a = const A();
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var aLib = findElement.import('package:test/a.dart').importedLibrary;
@@ -42,7 +41,7 @@
   }
 
   test_constFactoryRedirection_super() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class I {
   const factory I(int f) = B;
 }
@@ -60,7 +59,6 @@
 @I(42)
 main() {}
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var node = findNode.annotation('@I');
@@ -69,7 +67,7 @@
   }
 
   test_constNotInitialized() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class B {
   const B(_);
 }
@@ -79,7 +77,6 @@
   const C() : super(a);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.CONST_NOT_INITIALIZED,
       CompileTimeErrorCode.CONST_NOT_INITIALIZED,
@@ -95,12 +92,11 @@
   const C();
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 const v = a;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var v = findElement.topVar('v') as ConstVariableElement;
diff --git a/pkg/analyzer/test/src/dart/resolution/constructor_test.dart b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
index b91fbda..db7428a 100644
--- a/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
@@ -15,24 +15,22 @@
 @reflectiveTest
 class ConstructorResolutionTest extends DriverResolutionTest {
   test_initializer_field_functionExpression_expressionBody() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   final int x;
   C(int a) : x = (() => a + 1)();
 }
 ''');
-    await resolveTestFile();
     assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
   }
 
   test_initializer_field_functionExpression_blockBody() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   var x;
   C(int a) : x = (() {return a + 1;})();
 }
 ''');
-    await resolveTestFile();
     assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index f204d72..3354370 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -16,13 +16,12 @@
 @reflectiveTest
 class EnumDriverResolutionTest extends DriverResolutionTest {
   test_inference_listLiteral() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum E1 {a, b}
 enum E2 {a, b}
 
 var v = [E1.a, E2.b];
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var v = findElement.topVar('v');
@@ -30,12 +29,11 @@
   }
 
   test_isConstantEvaluated() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 enum E {
   aaa, bbb
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     expect(findElement.field('aaa').isConstantEvaluated, isTrue);
diff --git a/pkg/analyzer/test/src/dart/resolution/export_test.dart b/pkg/analyzer/test/src/dart/resolution/export_test.dart
index 565f72d..5a4455a 100644
--- a/pkg/analyzer/test/src/dart/resolution/export_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/export_test.dart
@@ -21,10 +21,9 @@
 get f => null;
 set f(_) {}
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 export 'a.dart';
 ''');
-    await resolveTestFile();
     var exportNamespace = result.libraryElement.exportNamespace;
     expect(exportNamespace.get('f'), isNotNull);
     expect(exportNamespace.get('f='), isNotNull);
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
index 54f31ff..b8b7e2a 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -16,13 +16,12 @@
 @reflectiveTest
 class ForEachElementTest extends DriverResolutionTest {
   test_declaredIdentifierScope() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   <int>[for (var i in [1, 2, 3]) i]; // 1
   <double>[for (var i in [1.1, 2.2, 3.3]) i]; // 2
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertElement(
@@ -39,13 +38,12 @@
 @reflectiveTest
 class ForLoopElementTest extends DriverResolutionTest {
   test_declaredVariableScope() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   <int>[for (var i = 1; i < 10; i += 3) i]; // 1
   <double>[for (var i = 1.1; i < 10; i += 5) i]; // 2
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertElement(
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 5b83f62..a32bf70 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
@@ -18,14 +18,13 @@
   test_importPrefix_asIterable() async {
     // TODO(scheglov) Remove this test (already tested as import prefix).
     // TODO(scheglov) Move other for-in tests here.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async' as p;
 
 main() {
   for (var x in p) {}
 }
 ''');
-    await resolveTestFile();
     assertHasTestErrors();
 
     var xRef = findNode.simple('x in');
diff --git a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
index c233a3d..3d89872 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
@@ -17,13 +17,11 @@
 @reflectiveTest
 class FunctionTypeAliasResolutionTest extends DriverResolutionTest {
   test_type_element() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 G<int> g;
 
 typedef T G<T>();
 ''');
-    await resolveTestFile();
-
     FunctionType type = findElement.topVar('g').type;
     assertElementTypeString(type, 'int Function()');
 
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
index 5dde449..e88a6bc 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
@@ -18,61 +18,57 @@
 @reflectiveTest
 class GenericTypeAliasDriverResolutionTest extends DriverResolutionTest {
   test_genericFunctionTypeCannotBeTypeArgument_def_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T> {}
 
 typedef G = Function<S>();
 
 C<G> x;
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_literal_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T> {}
 
 C<Function<S>()> x;
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_literal_function() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 T f<T>(T) => null;
 
 main() {
   f<Function<S>()>(null);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_literal_functionType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 T Function<T>(T) f;
 
 main() {
   f<Function<S>()>(null);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_literal_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   T f<T>(T) => null;
 }
@@ -81,54 +77,48 @@
   new C().f<Function<S>()>(null);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_literal_typedef() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef T F<T>(T t);
 
 F<Function<S>()> x;
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
       [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT],
     );
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_OK_def_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T> {}
 
 typedef G = Function();
 
 C<G> x;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_genericFunctionTypeCannotBeTypeArgument_OK_literal_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T> {}
 
 C<Function()> x;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_type_element() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 G<int> g;
 
 typedef G<T> = T Function(double);
 ''');
-    await resolveTestFile();
-
     FunctionType type = findElement.topVar('g').type;
     assertElementTypeString(type, 'int Function(double)');
 
@@ -142,15 +132,13 @@
   }
 
   test_typeParameters() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 
 class B {}
 
 typedef F<T extends A> = B<T> Function<U extends B>(T a, U b);
 ''');
-    await resolveTestFile();
-
     var f = findElement.genericTypeAlias('F');
     expect(f.typeParameters, hasLength(1));
 
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 c514779..44a4dce 100644
--- a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
@@ -17,14 +17,13 @@
 @reflectiveTest
 class ImportPrefixDriverResolutionTest extends DriverResolutionTest {
   test_asExpression_expressionStatement() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async' as p;
 
 main() {
   p; // use
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -35,14 +34,13 @@
   }
 
   test_asExpression_forIn_iterable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async' as p;
 
 main() {
   for (var x in p) {}
 }
 ''');
-    await resolveTestFile();
     assertHasTestErrors();
 
     var xRef = findNode.simple('x in');
@@ -54,7 +52,7 @@
   }
 
   test_asExpression_instanceCreation_argument() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async' as p;
 
 class C<T> {
@@ -65,7 +63,6 @@
   var x = new C(p);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -76,14 +73,13 @@
   }
 
   test_asPrefix_methodInvocation() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' as p;
 
 main() {
   p.max(0, 0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var pRef = findNode.simple('p.max');
@@ -92,14 +88,13 @@
   }
 
   test_asPrefix_prefixedIdentifier() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:async' as p;
 
 main() {
   p.Future;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var pRef = findNode.simple('p.Future');
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 962eb5d..3fdea94 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -16,10 +16,9 @@
 @reflectiveTest
 class InstanceCreationDriverResolutionTest extends DriverResolutionTest {
   test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 final foo = Map<int>();
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS,
     ]);
@@ -35,7 +34,7 @@
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class Foo<X> {
   Foo.bar();
 }
@@ -44,7 +43,6 @@
   new Foo.bar<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
     ]);
@@ -66,14 +64,13 @@
   Foo.bar();
 }
 ''');
-    addTestFile('''
+    await resolveTestCode('''
 import 'a.dart' as p;
 
 main() {
   new p.Foo.bar<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
     ]);
@@ -92,7 +89,7 @@
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_implicitNew() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class Foo<X> {
   Foo.bar();
 }
@@ -101,7 +98,6 @@
   Foo.bar<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
     ]);
@@ -127,14 +123,13 @@
   Foo.bar();
 }
 ''');
-    addTestFile('''
+    await resolveTestCode('''
 import 'a.dart' as p;
 
 main() {
   p.Foo.bar<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
     ]);
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 44c13fe..1de534c 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
@@ -16,16 +16,15 @@
 class InstanceMemberInferenceClassDriverResolutionTest
     extends DriverResolutionTest {
   test_invalid_inheritanceCycle() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A extends C {}
 class B extends A {}
 class C extends B {}
 ''');
-    await resolveTestFile();
   }
 
   test_method_parameter_multiple_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo(int p) => 0;
 }
@@ -36,14 +35,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_named_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -54,14 +51,12 @@
   foo({p}) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_named_same() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -72,14 +67,12 @@
   foo({p}) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeString(p.type, 'int');
   }
 
   test_method_parameter_multiple_namedAndRequired() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -90,14 +83,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_optionalAndRequired() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo(int p) => 0;
 }
@@ -108,14 +99,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeString(p.type, 'int');
   }
 
   test_method_parameter_single_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   foo(E p) => 0;
 }
@@ -123,14 +112,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'C').parameters[0];
     assertElementTypeString(p.type, 'T');
   }
 
   test_method_return_multiple_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -141,14 +128,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_different_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => null;
 }
@@ -159,14 +144,12 @@
   foo() => null;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_different_void() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -177,14 +160,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -195,14 +176,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_same_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => 0;
 }
@@ -213,14 +192,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeString(foo.returnType, 'T');
   }
 
   test_method_return_multiple_same_nonVoid() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -231,14 +208,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeString(foo.returnType, 'int');
   }
 
   test_method_return_multiple_same_void() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {};
 }
@@ -249,14 +224,12 @@
   foo() {};
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'C');
     assertElementTypeString(foo.returnType, 'void');
   }
 
   test_method_return_single() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -264,14 +237,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'B');
     assertElementTypeString(foo.returnType, 'int');
   }
 
   test_method_return_single_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => 0;
 }
@@ -279,8 +250,6 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'B');
     assertElementTypeString(foo.returnType, 'T');
   }
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 0368dd9..9d188eb 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
@@ -16,16 +16,15 @@
 class InstanceMemberInferenceMixinDriverResolutionTest
     extends DriverResolutionTest {
   test_invalid_inheritanceCycle() async {
-    addTestFile('''
+    await resolveTestCode('''
 mixin A on C {}
 mixin B on A {}
 mixin C on B {}
 ''');
-    await resolveTestFile();
   }
 
   test_method_parameter_multiple_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo(int p) => 0;
 }
@@ -36,14 +35,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_named_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -54,14 +51,12 @@
   foo({p}) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_named_same() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -72,14 +67,12 @@
   foo({p}) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeString(p.type, 'int');
   }
 
   test_method_parameter_multiple_namedAndRequired() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo({int p}) => 0;
 }
@@ -90,14 +83,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeDynamic(p.type);
   }
 
   test_method_parameter_multiple_optionalAndRequired() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   foo(int p) => 0;
 }
@@ -108,14 +99,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeString(p.type, 'int');
   }
 
   test_method_parameter_single_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   foo(E p) => 0;
 }
@@ -123,14 +112,12 @@
   foo(p) => 0;
 }
 ''');
-    await resolveTestFile();
-
     var p = findElement.method('foo', of: 'M').parameters[0];
     assertElementTypeString(p.type, 'T');
   }
 
   test_method_return_multiple_different() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -141,14 +128,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_different_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => null;
 }
@@ -159,14 +144,12 @@
   foo() => null;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_different_void() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -177,14 +160,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -195,14 +176,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeDynamic(foo.returnType);
   }
 
   test_method_return_multiple_same_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => 0;
 }
@@ -213,14 +192,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeString(foo.returnType, 'T');
   }
 
   test_method_return_multiple_same_nonVoid() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -231,14 +208,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeString(foo.returnType, 'int');
   }
 
   test_method_return_multiple_same_void() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   void foo() {};
 }
@@ -249,14 +224,12 @@
   foo() {};
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeString(foo.returnType, 'void');
   }
 
   test_method_return_single() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo() => 0;
 }
@@ -264,14 +237,12 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeString(foo.returnType, 'int');
   }
 
   test_method_return_single_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E> {
   E foo() => 0;
 }
@@ -279,8 +250,6 @@
   foo() => 0;
 }
 ''');
-    await resolveTestFile();
-
     var foo = findElement.method('foo', of: 'M');
     assertElementTypeString(foo.returnType, 'T');
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index 14dc87d..c2520f8 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class MetadataResolutionTest extends DriverResolutionTest {
-  test_constructor_named() async {
+  test_otherLibrary_constructor_named() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
   final int f;
@@ -30,22 +30,21 @@
 class B {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'b.dart';
 
 B b;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var classB = findNode.typeName('B b;').name.staticElement;
     var annotation = classB.metadata.single;
     var value = annotation.computeConstantValue();
-    expect(value, isNotNull);
+    assertElementTypeString(value.type, 'A');
     expect(value.getField('f').toIntValue(), 42);
   }
 
-  test_constructor_unnamed() async {
+  test_otherLibrary_constructor_unnamed() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
   final int f;
@@ -60,22 +59,21 @@
 class B {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'b.dart';
 
 B b;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var classB = findNode.typeName('B b;').name.staticElement;
     var annotation = classB.metadata.single;
     var value = annotation.computeConstantValue();
-    expect(value, isNotNull);
+    assertElementTypeString(value.type, 'A');
     expect(value.getField('f').toIntValue(), 42);
   }
 
-  test_implicitConst() async {
+  test_otherLibrary_implicitConst() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
   final int f;
@@ -91,18 +89,33 @@
 class C {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 C c;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var classC = findNode.typeName('C c;').name.staticElement;
     var annotation = classC.metadata.single;
     var value = annotation.computeConstantValue();
-    expect(value, isNotNull);
+    assertElementTypeString(value.type, 'B');
     expect(value.getField('a').getField('f').toIntValue(), 42);
   }
+
+  test_sameLibrary_genericClass_constructor_unnamed() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+@A(42)
+class B {}
+''');
+    var annotation = findElement.class_('B').metadata.single;
+    var value = annotation.computeConstantValue();
+    assertElementTypeString(value.type, 'A<int>');
+    expect(value.getField('f').toIntValue(), 42);
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index c31ff84..f600ea3 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -18,7 +18,7 @@
 @reflectiveTest
 class MethodInvocationResolutionTest extends DriverResolutionTest {
   test_error_abstractSuperMemberReference() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class A {
   void foo(int _);
 }
@@ -30,7 +30,6 @@
   void foo(int _) {} // does not matter
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
 
@@ -44,7 +43,7 @@
   }
 
   test_error_abstractSuperMemberReference_mixin_implements() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void foo(int _) {}
 }
@@ -55,7 +54,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
 
@@ -69,7 +67,7 @@
   }
 
   test_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int foo();
   noSuchMethod(im) => 42;
@@ -80,7 +78,6 @@
   noSuchMethod(im) => 87;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
 
@@ -94,7 +91,7 @@
   }
 
   test_error_abstractSuperMemberReference_OK_mixinHasConcrete() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 class M {
@@ -109,7 +106,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -122,7 +118,7 @@
   }
 
   test_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int foo();
   noSuchMethod(im) => 42;
@@ -133,7 +129,6 @@
   noSuchMethod(im) => 87;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('super.foo(); // ref');
@@ -146,7 +141,7 @@
   }
 
   test_error_abstractSuperMemberReference_OK_superSuperHasConcrete() async {
-    addTestFile('''
+    await resolveTestCode('''
 abstract class A {
   void foo(int _) {}
 }
@@ -161,7 +156,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -181,7 +175,7 @@
 void foo(int _) {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 import 'b.dart';
 
@@ -189,7 +183,6 @@
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.AMBIGUOUS_IMPORT,
     ]);
@@ -207,7 +200,7 @@
 void foo(int _) {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as p;
 import 'b.dart' as p;
 
@@ -215,7 +208,6 @@
   p.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.AMBIGUOUS_IMPORT,
     ]);
@@ -226,7 +218,7 @@
   }
 
   test_error_instanceAccessToStaticMember_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   static void foo(int _) {}
 }
@@ -235,7 +227,6 @@
   a.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
     ]);
@@ -247,7 +238,7 @@
   }
 
   test_error_invocationOfNonFunction_interface_hasCall_field() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void Function() call;
 }
@@ -256,7 +247,6 @@
   c();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
     ]);
@@ -267,13 +257,12 @@
   }
 
   test_error_invocationOfNonFunction_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   Object foo;
   foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
     ]);
@@ -285,19 +274,18 @@
   }
 
   test_error_invocationOfNonFunction_OK_dynamic_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var foo;
   foo();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation('foo();', findElement.localVar('foo'));
   }
 
   test_error_invocationOfNonFunction_OK_dynamicGetter_instance() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   var foo;
 }
@@ -306,7 +294,6 @@
   c.foo();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation(
       'c.foo();',
@@ -316,7 +303,7 @@
   }
 
   test_error_invocationOfNonFunction_OK_dynamicGetter_superClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   var foo;
 }
@@ -327,7 +314,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation(
       'foo();',
@@ -337,7 +323,7 @@
   }
 
   test_error_invocationOfNonFunction_OK_dynamicGetter_thisClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   var foo;
 
@@ -346,7 +332,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation(
       'foo();',
@@ -356,18 +341,17 @@
   }
 
   test_error_invocationOfNonFunction_OK_Function() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 f(Function foo) {
   foo(1, 2);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation('foo(1, 2);', findElement.parameter('foo'));
   }
 
   test_error_invocationOfNonFunction_OK_functionTypeTypeParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 typedef MyFunction = double Function(int _);
 
 class C<T extends MyFunction> {
@@ -378,7 +362,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertMethodInvocation(
       findNode.methodInvocation('foo(0)'),
@@ -389,7 +372,7 @@
   }
 
   test_error_invocationOfNonFunction_static_hasTarget() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static int foo;
 }
@@ -398,7 +381,6 @@
   C.foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
     ]);
@@ -410,7 +392,7 @@
   }
 
   test_error_invocationOfNonFunction_static_noTarget() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static int foo;
   
@@ -419,7 +401,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
     ]);
@@ -431,7 +412,7 @@
   }
 
   test_error_invocationOfNonFunction_super_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get foo => 0;
 }
@@ -442,7 +423,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
     ]);
@@ -458,14 +438,13 @@
 void foo() {}
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as prefix;
 
 main() {
   prefix?.foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -482,14 +461,13 @@
   }
 
   test_error_prefixIdentifierNotFollowedByDot_deferred() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' deferred as math;
 
 main() {
   math?.loadLibrary();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -506,14 +484,13 @@
   }
 
   test_error_prefixIdentifierNotFollowedByDot_invoke() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' as foo;
 
 main() {
   foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -525,12 +502,11 @@
   }
 
   test_error_undefinedFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_FUNCTION,
     ]);
@@ -538,14 +514,13 @@
   }
 
   test_error_undefinedFunction_hasTarget_importPrefix() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' as math;
 
 main() {
   math.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_FUNCTION,
     ]);
@@ -553,12 +528,11 @@
   }
 
   test_error_undefinedIdentifier_target() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   bar.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.UNDEFINED_IDENTIFIER,
     ]);
@@ -566,13 +540,12 @@
   }
 
   test_error_undefinedMethod_hasTarget_class() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {}
 main() {
   C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -580,7 +553,7 @@
   }
 
   test_error_undefinedMethod_hasTarget_class_arguments() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {}
 
 int x;
@@ -588,7 +561,6 @@
   C.foo(x);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -598,7 +570,7 @@
   }
 
   test_error_undefinedMethod_hasTarget_class_inSuperclass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class S {
   static void foo(int _) {}
 }
@@ -609,7 +581,6 @@
   C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -617,14 +588,13 @@
   }
 
   test_error_undefinedMethod_hasTarget_class_typeArguments() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {}
 
 main() {
   C.foo<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -637,12 +607,11 @@
   }
 
   test_error_undefinedMethod_hasTarget_class_typeParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T> {
   static main() => C.T();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -650,12 +619,11 @@
   }
 
   test_error_undefinedMethod_hasTarget_instance() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   42.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -663,13 +631,12 @@
   }
 
   test_error_undefinedMethod_hasTarget_localVariable_function() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var v = () {};
   v.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -677,14 +644,13 @@
   }
 
   test_error_undefinedMethod_noTarget() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   main() {
     foo(0);
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -692,24 +658,22 @@
   }
 
   test_error_undefinedMethod_object_call() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main(Object o) {
   o.call();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
   }
 
   test_error_undefinedMethod_OK_null() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   null.foo();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertUnresolvedMethodInvocation('foo();');
   }
@@ -720,7 +684,7 @@
   void _foo(int _) {}
 }
 ''');
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart';
 
 class B extends A {
@@ -729,7 +693,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -737,7 +700,7 @@
   }
 
   test_error_undefinedMethod_typeLiteral_cascadeTarget() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static void foo() {}
 }
@@ -746,7 +709,6 @@
   C..foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
@@ -755,20 +717,19 @@
   test_error_undefinedMethod_typeLiteral_conditional() async {
     // When applied to a type literal, the conditional access operator '?.'
     // cannot be used to access instance methods of Type.
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 main() {
   A?.toString();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
   }
 
   test_error_undefinedSuperMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {}
 
 class B extends A {
@@ -777,7 +738,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
     ]);
@@ -786,7 +746,7 @@
   }
 
   test_error_unqualifiedReferenceToNonLocalStaticMember_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   static void foo() {}
 }
@@ -797,7 +757,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
     ]);
@@ -813,7 +772,7 @@
   /// single error generated when the only problem is that an imported file
   /// does not exist.
   test_error_uriDoesNotExist_prefixed() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'missing.dart' as p;
 
 main() {
@@ -821,7 +780,6 @@
   p.bar(2);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
     ]);
@@ -833,7 +791,7 @@
   /// single error generated when the only problem is that an imported file
   /// does not exist.
   test_error_uriDoesNotExist_show() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'missing.dart' show foo, bar;
 
 main() {
@@ -841,7 +799,6 @@
   bar(2);
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
     ]);
@@ -850,7 +807,7 @@
   }
 
   test_error_useOfVoidResult_name_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C<T>{
   T foo;
 }
@@ -859,7 +816,6 @@
   c.foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -872,13 +828,12 @@
   }
 
   test_error_useOfVoidResult_name_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo;
   foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -890,14 +845,13 @@
   }
 
   test_error_useOfVoidResult_name_topFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo() {}
 
 main() {
   foo()();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -909,14 +863,13 @@
   }
 
   test_error_useOfVoidResult_name_topVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo;
 
 main() {
   foo();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -929,13 +882,12 @@
   }
 
   test_error_useOfVoidResult_receiver() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo;
   foo.toString();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -948,13 +900,12 @@
   }
 
   test_error_useOfVoidResult_receiver_cascade() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo;
   foo..toString();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -967,13 +918,12 @@
   }
 
   test_error_useOfVoidResult_receiver_withNull() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo;
   foo?.toString();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticWarningCode.USE_OF_VOID_RESULT,
     ]);
@@ -986,14 +936,13 @@
   }
 
   test_error_wrongNumberOfTypeArgumentsMethod_01() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo() {}
 
 main() {
   foo<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
     ]);
@@ -1006,14 +955,13 @@
   }
 
   test_error_wrongNumberOfTypeArgumentsMethod_21() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 Map<T, U> foo<T extends num, U>() => null;
 
 main() {
   foo<int>();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
     ]);
@@ -1027,7 +975,7 @@
   }
 
   test_hasReceiver_class_staticGetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static double Function(int) get foo => null;
 }
@@ -1036,7 +984,6 @@
   C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1050,7 +997,7 @@
   }
 
   test_hasReceiver_class_staticMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   static void foo(int _) {}
 }
@@ -1059,7 +1006,6 @@
   C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1072,14 +1018,13 @@
   }
 
   test_hasReceiver_deferredImportPrefix_loadLibrary() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' deferred as math;
 
 main() {
   math.loadLibrary();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var import = findElement.importFind('dart:math');
@@ -1094,14 +1039,13 @@
   }
 
   test_hasReceiver_functionTyped_call() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo(int _) {}
 
 main() {
   foo.call(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('call(0)');
@@ -1119,14 +1063,13 @@
 T foo<T extends num>(T a, T b) => a;
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as prefix;
 
 main() {
   prefix.foo(1, 2);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var import = findElement.importFind('package:test/a.dart');
@@ -1146,14 +1089,13 @@
 T Function<T>(T a, T b) get foo => null;
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as prefix;
 
 main() {
   prefix.foo(1, 2);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var import = findElement.importFind('package:test/a.dart');
@@ -1170,33 +1112,31 @@
   }
 
   test_hasReceiver_instance_Function_call_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void main() {
   Function foo;
 
   foo.call(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation('call(0)', null);
   }
 
   test_hasReceiver_instance_Function_call_topVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 Function foo;
 
 void main() {
   foo.call(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertInvalidInvocation('call(0)', null);
   }
 
   test_hasReceiver_instance_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   double Function(int) get foo => null;
 }
@@ -1205,7 +1145,6 @@
   c.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1218,7 +1157,7 @@
   }
 
   test_hasReceiver_instance_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void foo(int _) {}
 }
@@ -1227,7 +1166,6 @@
   c.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1241,7 +1179,7 @@
   }
 
   test_hasReceiver_instance_method_generic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   T foo<T>(T a) {
     return a;
@@ -1252,7 +1190,6 @@
   c.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1267,7 +1204,7 @@
   }
 
   test_hasReceiver_instance_method_issue30552() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 abstract class I1 {
   void foo(int i);
 }
@@ -1286,7 +1223,6 @@
   c.foo('hi');
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation("foo('hi')");
@@ -1298,7 +1234,7 @@
   }
 
   test_hasReceiver_instance_typeParameter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void foo(int _) {}
 }
@@ -1311,7 +1247,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1329,14 +1264,13 @@
 }
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as prefix;
 
 main() {
   prefix.C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var import = findElement.importFind('package:test/a.dart');
@@ -1361,14 +1295,13 @@
 }
 ''');
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'a.dart' as prefix;
 
 main() {
   prefix.C.foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var import = findElement.importFind('package:test/a.dart');
@@ -1386,7 +1319,7 @@
   }
 
   test_hasReceiver_super_getter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   double Function(int) get foo => null;
 }
@@ -1397,7 +1330,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1411,7 +1343,7 @@
   }
 
   test_hasReceiver_super_method() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void foo(int _) {}
 }
@@ -1422,7 +1354,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0);');
@@ -1435,14 +1366,13 @@
   }
 
   test_namedArgument() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo({int a, bool b}) {}
 
 main() {
   foo(b: false, a: 0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(b:');
@@ -1456,7 +1386,7 @@
   }
 
   test_noReceiver_getter_superClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   double Function(int) get foo => null;
 }
@@ -1467,7 +1397,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1480,7 +1409,7 @@
   }
 
   test_noReceiver_getter_thisClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   double Function(int) get foo => null;
 
@@ -1489,7 +1418,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1502,14 +1430,13 @@
   }
 
   test_noReceiver_importPrefix() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'dart:math' as math;
 
 main() {
   math();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
@@ -1517,14 +1444,13 @@
   }
 
   test_noReceiver_localFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void foo(int _) {}
 
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1536,14 +1462,13 @@
   }
 
   test_noReceiver_localVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   void Function(int) foo;
 
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1555,7 +1480,7 @@
   }
 
   test_noReceiver_localVariable_call() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void call(int _) {}
 }
@@ -1564,7 +1489,6 @@
   c(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('c(0);');
@@ -1576,7 +1500,7 @@
   }
 
   test_noReceiver_localVariable_promoted() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var foo;
   if (foo is void Function(int)) {
@@ -1584,7 +1508,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1596,7 +1519,7 @@
   }
 
   test_noReceiver_method_superClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   void foo(int _) {}
 }
@@ -1607,7 +1530,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1619,7 +1541,7 @@
   }
 
   test_noReceiver_method_thisClass() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   void foo(int _) {}
 
@@ -1628,7 +1550,6 @@
   }
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1640,14 +1561,13 @@
   }
 
   test_noReceiver_topFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo(int _) {}
 
 main() {
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1660,14 +1580,13 @@
   }
 
   test_noReceiver_topGetter() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 double Function(int) get foo => null;
 
 main() {
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1680,14 +1599,13 @@
   }
 
   test_noReceiver_topVariable() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void Function(int) foo;
 
 main() {
   foo(0);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(0)');
@@ -1700,26 +1618,24 @@
   }
 
   test_objectMethodOnDynamic() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   var v;
   v.toString(42);
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     _assertUnresolvedMethodInvocation('toString(42);');
   }
 
   test_objectMethodOnFunction() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void f() {}
 
 main() {
   f.toString();
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('toString();');
@@ -1757,29 +1673,25 @@
   }
 
   test_typeArgumentTypes_generic_typeArguments_notBounds() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo<T extends num>() {}
 
 main() {
   foo<bool>();
 }
 ''');
-    await resolveTestFile();
-
     var invocation = findNode.methodInvocation('foo<bool>();');
     assertTypeArgumentTypes(invocation, ['bool']);
   }
 
   test_typeArgumentTypes_generic_typeArguments_wrongNumber() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 void foo<T>() {}
 
 main() {
   foo<int, double>();
 }
 ''');
-    await resolveTestFile();
-
     var invocation = findNode.methodInvocation('foo<int, double>();');
     assertTypeArgumentTypes(invocation, ['dynamic']);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 8ebd753..b69b39a 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -857,14 +857,13 @@
   }
 
   test_error_mixinInstantiate_default() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 mixin M {}
 
 main() {
   new M();
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([CompileTimeErrorCode.MIXIN_INSTANTIATE]);
 
     var creation = findNode.instanceCreation('M();');
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 35f6532..68665ba 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -27,14 +27,13 @@
   bool get typeToStringWithNullability => true;
 
   test_class_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 class X1 extends A {} // 1
 class X2 implements A {} // 2
 class X3 with A {} // 3
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A {} // 1'), 'A');
@@ -43,14 +42,13 @@
   }
 
   test_classTypeAlias_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B {}
 class C {}
 
 class X = A with B implements C;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A with'), 'A');
@@ -59,26 +57,24 @@
   }
 
   test_local_getterNullAwareAccess_interfaceType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int? x;
   return x?.isEven;
 }
 ''');
 
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
   }
 
   test_local_interfaceType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   int? a = 0;
   int b = 0;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('int? a'), 'int?');
@@ -86,7 +82,7 @@
   }
 
   test_local_interfaceType_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   List<int?>? a = [];
   List<int>? b = [];
@@ -94,7 +90,6 @@
   List<int> d = [];
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
@@ -104,7 +99,7 @@
   }
 
   test_local_methodNullAwareCall_interfaceType() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   bool x() => true;
 }
@@ -115,69 +110,63 @@
 }
 ''');
 
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.methodInvocation('c?.x()'), 'bool?');
   }
 
   test_local_nullCoalesce_nullableInt_int() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int? x;
   int y = 0;
   x ?? y;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.binary('x ?? y'), 'int');
   }
 
   test_local_nullCoalesce_nullableInt_nullableInt() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int? x;
   x ?? x;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.binary('x ?? x'), 'int?');
   }
 
   test_local_nullCoalesceAssign_nullableInt_int() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int? x;
   int y = 0;
   x ??= y;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.assignment('x ??= y'), 'int');
   }
 
   test_local_nullCoalesceAssign_nullableInt_nullableInt() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main() {
   int? x;
   x ??= x;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.assignment('x ??= x'), 'int?');
   }
 
   test_local_typeParameter() async {
-    addTestFile('''
+    await resolveTestCode('''
 main<T>(T a) {
   T x = a;
   T? y;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('T x'), 'T');
@@ -186,12 +175,11 @@
 
   @failingTest
   test_local_variable_genericFunctionType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   int? Function(bool, String?)? a;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(
@@ -201,12 +189,11 @@
   }
 
   test_localFunction_parameter_interfaceType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   f(int? a, int b) {}
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('int? a'), 'int?');
@@ -214,13 +201,12 @@
   }
 
   test_localFunction_returnType_interfaceType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   int? f() => 0;
   int g() => 0;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('int? f'), 'int?');
@@ -228,25 +214,23 @@
   }
 
   test_member_potentiallyNullable_called() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 m<T extends Function>() {
   List<T?> x;
   x.first();
 }
 ''');
-    await resolveTestFile();
-    // Do not assert no test errors. Deliberately invokes nullable type.
+// Do not assert no test errors. Deliberately invokes nullable type.
     assertType(findNode.methodInvocation('first').methodName, 'Function?');
   }
 
   test_mixin_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 mixin X1 on A {} // 1
 mixin X2 implements A {} // 2
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A {} // 1'), 'A');
@@ -254,36 +238,33 @@
   }
 
   test_null_assertion_operator_changes_null_to_never() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   Null x = null;
   x!;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.postfix('x!'), 'Never');
   }
 
   test_null_assertion_operator_removes_nullability() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   Object? x = null;
   x!;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.postfix('x!'), 'Object');
   }
 
   @failingTest
   test_parameter_genericFunctionType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main(int? Function(bool, String?)? a) {
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(
@@ -293,23 +274,21 @@
   }
 
   test_parameter_getterNullAwareAccess_interfaceType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 main(int? x) {
   return x?.isEven;
 }
 ''');
 
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
   }
 
   test_parameter_interfaceType() async {
-    addTestFile('''
+    await resolveTestCode('''
 main(int? a, int b) {
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('int? a'), 'int?');
@@ -317,11 +296,10 @@
   }
 
   test_parameter_interfaceType_generic() async {
-    addTestFile('''
+    await resolveTestCode('''
 main(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
@@ -331,7 +309,7 @@
   }
 
   test_parameter_methodNullAwareCall_interfaceType() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 class C {
   bool x() => true;
 }
@@ -341,61 +319,55 @@
 }
 ''');
 
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.methodInvocation('c?.x()'), 'bool?');
   }
 
   test_parameter_nullCoalesce_nullableInt_int() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main(int? x, int y) {
   x ?? y;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.binary('x ?? y'), 'int');
   }
 
   test_parameter_nullCoalesce_nullableInt_nullableInt() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main(int? x) {
   x ?? x;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.binary('x ?? x'), 'int?');
   }
 
   test_parameter_nullCoalesceAssign_nullableInt_int() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main(int? x, int y) {
   x ??= y;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.assignment('x ??= y'), 'int');
   }
 
   test_parameter_nullCoalesceAssign_nullableInt_nullableInt() async {
-    await addTestFile(r'''
+    await resolveTestCode(r'''
 main(int? x) {
   x ??= x;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
     assertType(findNode.assignment('x ??= x'), 'int?');
   }
 
   test_parameter_typeParameter() async {
-    addTestFile('''
+    await resolveTestCode('''
 main<T>(T a, T? b) {
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('T a'), 'T');
@@ -403,14 +375,13 @@
   }
 
   test_typedef_classic() async {
-    addTestFile('''
+    await resolveTestCode('''
 typedef int? F(bool a, String? b);
 
 main() {
   F? a;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
@@ -418,14 +389,13 @@
 
   @failingTest
   test_typedef_function() async {
-    addTestFile('''
+    await resolveTestCode('''
 typedef F<T> = int? Function(bool, T, T?);
 
 main() {
   F<String>? a;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(
@@ -441,14 +411,13 @@
   bool get typeToStringWithNullability => true;
 
   test_class_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 class X1 extends A {} // 1
 class X2 implements A {} // 2
 class X3 with A {} // 3
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A {} // 1'), 'A*');
@@ -457,14 +426,13 @@
   }
 
   test_classTypeAlias_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 class B {}
 class C {}
 
 class X = A with B implements C;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A with'), 'A*');
@@ -473,13 +441,12 @@
   }
 
   test_local_variable_interfaceType_notMigrated() async {
-    addTestFile('''
+    await resolveTestCode('''
 main() {
   int? a = 0;
   int b = 0;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([ParserErrorCode.EXPERIMENT_NOT_ENABLED]);
 
     assertType(findNode.typeName('int? a'), 'int*');
@@ -487,13 +454,12 @@
   }
 
   test_mixin_hierarchy() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {}
 
 mixin X1 on A {} // 1
 mixin X2 implements A {} // 2
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertType(findNode.typeName('A {} // 1'), 'A*');
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 287b10c..5fbe1d7 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -197,11 +197,10 @@
 ''');
     }
 
-    addTestFile(r'''
+    await resolveTestCode(r'''
 import 'b.dart';
 var v = a;
 ''');
-    await resolveTestFile();
     _fillLibraries();
 
     PropertyAccessorElement vg = findNode.simple('a;').staticElement;
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index dcc2d69..ab9db42 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class PropertyAccessResolutionTest extends DriverResolutionTest {
   test_get_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   int get foo;
   noSuchMethod(im) => 1;
@@ -27,7 +27,6 @@
   noSuchMethod(im) => 2;
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
 
@@ -37,7 +36,7 @@
   }
 
   test_get_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   int get foo;
   noSuchMethod(im) => 1;
@@ -48,7 +47,6 @@
   noSuchMethod(im) => 2;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var access = findNode.propertyAccess('super.foo; // ref');
@@ -57,7 +55,7 @@
   }
 
   test_set_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A {
   set foo(int a);
   noSuchMethod(im) {}
@@ -68,7 +66,6 @@
   noSuchMethod(im) {}
 }
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
 
@@ -82,7 +79,7 @@
   }
 
   test_set_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   set foo(int a);
   noSuchMethod(im) => 1;
@@ -93,7 +90,6 @@
   noSuchMethod(im) => 2;
 }
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     var access = findNode.propertyAccess('foo = v; // ref');
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 332bcca..aa18ac4 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -169,14 +169,6 @@
     expect(element.enclosingElement, expectedEnclosing);
   }
 
-  @Deprecated('Use assertErrorsInCode')
-  Future<void> assertErrorCodesInCode(
-      String code, List<ErrorCode> errors) async {
-    addTestFile(code);
-    await resolveTestFile();
-    assertTestErrorsWithCodes(errors);
-  }
-
   Future<void> assertErrorsInCode(
       String code, List<ExpectedError> expectedErrors) async {
     addTestFile(code);
@@ -513,6 +505,12 @@
 
   Future<ResolvedUnitResult> resolveFile(String path);
 
+  /// Put the [code] into the test file, and resolve it.
+  Future<void> resolveTestCode(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+  }
+
   Future<void> resolveTestFile() async {
     var path = convertPath('/test/lib/test.dart');
     result = await resolveFile(path);
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 5e56cac..9233974 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
@@ -16,13 +16,12 @@
 @reflectiveTest
 class TopTypeInferenceDriverResolutionTest extends DriverResolutionTest {
   test_referenceInstanceVariable_withDeclaredType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   final int a = b + 1;
 }
 final b = new A().a;
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
 
     assertElementTypeString(findElement.field('a').type, 'int');
@@ -30,13 +29,12 @@
   }
 
   test_referenceInstanceVariable_withoutDeclaredType() async {
-    addTestFile(r'''
+    await resolveTestCode(r'''
 class A {
   final a = b + 1;
 }
 final b = new A().a;
 ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes([StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
 
     assertElementTypeDynamic(findElement.field('a').type);
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
index 0b07098..ed4f95f 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
@@ -28,204 +28,189 @@
 
   @failingTest
   test_list_awaitForIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int>[await for (var e in a()) e];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
   @failingTest
   test_list_awaitForIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int>[await for (int e in a()) e];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
   @failingTest
   test_list_for_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>[for (int i = 0; a(); i++) i];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_list_forIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>[for (var e in a()) e];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
   @failingTest
   test_list_forIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>[for (int e in a()) e];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
   @failingTest
   test_map_awaitForIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int, int>{await for (var e in a()) e : e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
   @failingTest
   test_map_awaitForIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int, int>{await for (int e in a()) e : e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
   @failingTest
   test_map_for_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int, int>{for (int i = 0; a(); i++) i : i};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_map_forIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int, int>{for (var e in a()) e : e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
   @failingTest
   test_map_forIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int, int>{for (int e in a()) e : e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
   @failingTest
   test_set_awaitForIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int>{await for (var e in a()) e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
   @failingTest
   test_set_awaitForIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   var b = <int>{await for (int e in a()) e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
   @failingTest
   test_set_for_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>{for (int i = 0; a(); i++) i};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_set_forIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>{for (var e in a()) e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
   @failingTest
   test_set_forIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>{for (int e in a()) e};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
@@ -243,40 +228,37 @@
 
   @failingTest
   test_list_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>[if (a()) 1];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_map_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <String, int>{if (a()) 'a' : 1};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_set_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>{if (a()) 1};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
@@ -293,42 +275,39 @@
 
   @failingTest
   test_list_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>[...a()];
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
   @failingTest
   test_map_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <String, int>{...a()};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Map<String, int> Function()');
   }
 
   @failingTest
   test_set_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   var b = <int>{...a()};
   print(b);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index 72ebc03..ec7660c 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -18,13 +18,12 @@
 @reflectiveTest
 class ConditionalExpressionTest extends DriverResolutionTest {
   test_upward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(bool a, int b, int c) {
   var d = a ? b : c;
   print(d);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('d)'), 'int');
   }
 }
@@ -41,14 +40,13 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(int b, int c) {
   var d = a() ? b : c;
   print(d);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart
index d0bf2ff..9997f16 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart
@@ -20,13 +20,12 @@
 @reflectiveTest
 class EqualTest extends DriverResolutionTest {
   test_simple() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(Object a, Object b) {
   var c = a == b;
   print(c);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('c)'), 'bool');
   }
 }
@@ -45,13 +44,12 @@
 @reflectiveTest
 class NotEqualTest extends DriverResolutionTest {
   test_simple() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(Object a, Object b) {
   var c = a != b;
   print(c);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('c)'), 'bool');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index daf22e8..a2f10f6 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -15,62 +15,55 @@
 @reflectiveTest
 class ListLiteralTest extends DriverResolutionTest {
   test_context_noTypeArgs_expression_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> a = ['a'];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_context_noTypeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> a = [1];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_context_noTypeArgs_noElements() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = [];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
   test_context_noTypeArgs_noElements_typeParameter() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends List<int>> {
   E a = [];
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
   test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends List<dynamic>> {
   E a = [];
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
   test_context_typeArgs_expression_conflictingContext() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <int>[0];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_context_typeArgs_expression_conflictingExpression() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <String>[0];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
@@ -78,242 +71,215 @@
   test_context_typeArgs_expression_conflictingTypeArgs() async {
     // Context type and element types both suggest `String`, so this should
     // override the explicit type argument.
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <int>['a'];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
   test_context_typeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <String>['a'];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
   test_context_typeArgs_noElements_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <int>[];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_context_typeArgs_noElements_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<String> a = <String>[];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = [1, 2, 3];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = [1, 2.3, 4];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<num>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = [1, '2', 3];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<Object>');
   }
 
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 var a = [for (int e in c) e * 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[for'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 int b;
 var a = [for (b in c) b * 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[for'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_forWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = [for (var i = 0; i < 2; i++) i * 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[for'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_forWithExpression() async {
-    addTestFile('''
+    await resolveTestCode('''
 int i;
 var a = [for (i = 0; i < 2; i++) i * 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[for'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_if() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = [if (c) 1];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = [if (c) 1 else 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = [if (c) 1 else 2.3];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<num>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = [if (c) 1 else '2'];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<Object>');
   }
 
   test_noContext_noTypeArgs_noElements() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = [];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
   test_noContext_noTypeArgs_spread() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 var a = [...c];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<int> b;
 var a = [...b, ...c];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<int>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<double> b;
 var a = [...b, ...c];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<num>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<String> b;
 var a = [...b, ...c];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<Object>');
   }
 
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 dynamic d;
 var a = [if (0 < 1) ...c else ...d];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
   test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   var futureNull = Future.value(null);
   var a = [1, ...?await futureNull, 2];
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
   test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   var futureNull = Future.value(null);
   var a = [...?await futureNull];
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<Null>');
   }
 
   test_noContext_typeArgs_expression_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <String>[1];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
   test_noContext_typeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int>[1];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   @failingTest
   test_noContext_typeArgs_expressions_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int, String>[1, 2];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
   test_noContext_typeArgs_noElements() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <num>[];
 ''');
-    await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<num>');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
index bf31077..764822a 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
@@ -20,13 +20,12 @@
 @reflectiveTest
 class LogicalAndTest extends DriverResolutionTest {
   test_upward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(bool a, bool b) {
   var c = a && b;
   print(c);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('c)'), 'bool');
   }
 }
@@ -43,7 +42,7 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(b) {
   var c = a() && b();
   print(c);
@@ -51,7 +50,6 @@
 T a<T>() => throw '';
 T b<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
     assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
   }
@@ -60,13 +58,12 @@
 @reflectiveTest
 class LogicalOrTest extends DriverResolutionTest {
   test_upward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(bool a, bool b) {
   var c = a || b;
   print(c);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('c)'), 'bool');
   }
 }
@@ -83,7 +80,7 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(b) {
   var c = a() || b();
   print(c);
@@ -91,7 +88,6 @@
 T a<T>() => throw '';
 T b<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
     assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index d09d57f..9ed2abc 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -18,346 +18,307 @@
   AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
 
   test_context_noTypeArgs_entry_conflictingKey() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> a = {'a' : 1};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_context_noTypeArgs_entry_conflictingValue() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> a = {1 : 'a'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_context_noTypeArgs_entry_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> a = {1 : 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_context_noTypeArgs_noEntries() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = {};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
   test_context_noTypeArgs_noEntries_typeParameters() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends Map<int, String>> {
   E a = {};
 }
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
   }
 
   test_context_noTypeArgs_noEntries_typeParameters_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends Map<dynamic, dynamic>> {
   E a = {};
 }
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
   }
 
   test_context_typeArgs_entry_conflictingKey() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = <String, String>{0 : 'a'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
   test_context_typeArgs_entry_conflictingValue() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = <String, String>{'a' : 1};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
   test_context_typeArgs_entry_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = <String, String>{'a' : 'b'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
   test_context_typeArgs_noEntries_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = <int, int>{};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_context_typeArgs_noEntries_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, String> a = <String, String>{};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
   test_default_constructor_param_typed() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   const C({x = const <String, int>{}});
 }
 ''');
-    await resolveTestFile();
   }
 
   test_default_constructor_param_untyped() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   const C({x = const {}});
 }
 ''');
-    await resolveTestFile();
   }
 
   test_noContext_noTypeArgs_expressions_lubOfIntAndString() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1 : 'a', 2 : 'b', 3 : 'c'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, String>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfNumAndNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1 : 2, 3.0 : 4, 5 : 6.0};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<num, num>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfObjectAndObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1 : '1', '2' : 2, 3 : '3'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
   }
 
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 var a = {for (int e in c) e : e * 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{for'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 int b;
 var a = {for (b in c) b * 2 : b};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{for'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_forWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {for (var i = 0; i < 2; i++) i : i * 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{for'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_forWithExpression() async {
-    addTestFile('''
+    await resolveTestCode('''
 int i;
 var a = {for (i = 0; i < 2; i++) i * 2 : i};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{for'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_if() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 : 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfIntAndInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 : 3 else 2 : 4};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfNumAndNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1.0 : 3 else 2 : 4.0};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<num, num>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfObjectAndObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 : '1' else '2': 2 };
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
   }
 
   test_noContext_noTypeArgs_noEntries() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
   }
 
   test_noContext_noTypeArgs_spread() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> c;
 var a = {...c};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_spread_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 var c = {};
 var a = {...c};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<dynamic, dynamic>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfIntAndInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> c;
 Map<int, int> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<int, int>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfNumAndNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, double> c;
 Map<double, int> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<num, num>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfObjectObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<int, int> c;
 Map<String, String> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<Object, Object>');
   }
 
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
-    addTestFile('''
+    await resolveTestCode('''
 Map<String, int> c;
 dynamic d;
 var a = {if (0 < 1) ...c else ...d};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
   }
 
   @failingTest
   test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   var futureNull = Future.value(null);
   var a = {1 : 'a', ...?await futureNull, 2 : 'b'};
 }
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{1'), 'Map<int, String>');
   }
 
   test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   var futureNull = Future.value(null);
   var a = {...?await futureNull};
 }
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'dynamic');
   }
 
   test_noContext_typeArgs_entry_conflictingKey() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <String, int>{1 : 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, int>');
   }
 
   test_noContext_typeArgs_entry_conflictingValue() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <String, int>{'a' : 'b'};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, int>');
   }
 
   test_noContext_typeArgs_entry_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int, int>{1 : 2};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_noContext_typeArgs_expression_conflictingElement() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int, String>{1};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, String>');
   }
 
   @failingTest
   test_noContext_typeArgs_expressions_conflictingTypeArgs() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int>{1 : 2, 3 : 4};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
   test_noContext_typeArgs_noEntries() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <num, String>{};
 ''');
-    await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<num, String>');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
index 60335c4..93067e4 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
@@ -18,13 +18,12 @@
 @reflectiveTest
 class NotTest extends DriverResolutionTest {
   test_upward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(bool a) {
   var b = !a;
   print(b);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('b)'), 'bool');
   }
 }
@@ -41,14 +40,13 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(b) {
   var c = !a();
   print(c);
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index a6a6664..a880513 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -18,277 +18,246 @@
   AstNode setLiteral(String search) => findNode.setOrMapLiteral(search);
 
   test_context_noTypeArgs_expression_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<int> a = {'a'};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_context_noTypeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<int> a = {1};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_context_noTypeArgs_noElements() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = {};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   test_context_noTypeArgs_noElements_typeParameter() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends Set<int>> {
   E a = {};
 }
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{}'), 'Set<dynamic>');
   }
 
   test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
-    addTestFile('''
+    await resolveTestCode('''
 class A<E extends Set<dynamic>> {
   E a = {};
 }
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{}'), 'Set<dynamic>');
   }
 
   test_context_typeArgs_expression_conflictingExpression() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = <String>{0};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   @failingTest
   test_context_typeArgs_expression_conflictingTypeArgs() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = <int>{'a'};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   test_context_typeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = <String>{'a'};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   test_context_typeArgs_noElements_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = <int>{};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_context_typeArgs_noElements_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 Set<String> a = <String>{};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1, 2, 3};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1, 2.3, 4};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<num>');
   }
 
   test_noContext_noTypeArgs_expressions_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {1, '2', 3};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<Object>');
   }
 
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 var a = {for (int e in c) e * 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{for'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 int b;
 var a = {for (b in c) b * 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{for'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_forWithDeclaration() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = {for (var i = 0; i < 2; i++) i * 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{for'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_forWithExpression() async {
-    addTestFile('''
+    await resolveTestCode('''
 int i;
 var a = {for (i = 0; i < 2; i++) i * 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{for'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_if() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 else 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 else 2.3};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<num>');
   }
 
   test_noContext_noTypeArgs_ifElse_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 bool c = true;
 var a = {if (c) 1 else '2'};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<Object>');
   }
 
   test_noContext_noTypeArgs_spread() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 var a = {...c};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfInt() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<int> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<int>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfNum() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<double> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<num>');
   }
 
   test_noContext_noTypeArgs_spread_lubOfObject() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 List<String> b;
 var a = {...b, ...c};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<Object>');
   }
 
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
-    addTestFile('''
+    await resolveTestCode('''
 List<int> c;
 dynamic d;
 var a = {if (0 < 1) ...c else ...d};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<dynamic>');
   }
 
   @failingTest
   test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
-    addTestFile('''
+    await resolveTestCode('''
 f() {
   var futureNull = Future.value(null);
   var a = {1, ...?await futureNull, 2};
 }
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{1'), 'Set<int>');
   }
 
   test_noContext_typeArgs_expression_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <String>{1};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<String>');
   }
 
   test_noContext_typeArgs_expression_noConflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int>{1};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   @failingTest
   test_noContext_typeArgs_expressions_conflict() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <int, String>{1, 2};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
   test_noContext_typeArgs_noElements() async {
-    addTestFile('''
+    await resolveTestCode('''
 var a = <num>{};
 ''');
-    await resolveTestFile();
     assertType(setLiteral('{'), 'Set<num>');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
index 6137756..cab7d7b 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
@@ -30,13 +30,12 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   assert(a());
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
@@ -53,13 +52,12 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   do {} while(a())
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
@@ -76,63 +74,58 @@
 
   @failingTest
   test_awaitForIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   await for (var e in a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
   @failingTest
   test_awaitForIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() async {
   await for (int e in a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
   @failingTest
   test_for_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   for (int i = 0; a(); i++) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
   @failingTest
   test_forIn_dynamic_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   for (var e in a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
   @failingTest
   test_forIn_int_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   for (int e in a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
@@ -150,13 +143,12 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   if (a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
@@ -173,13 +165,12 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   while (a()) {}
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
index 8cdfe3a..60e9a36 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
@@ -26,13 +26,12 @@
 
   @failingTest
   test_downward() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f() {
   throw a();
 }
 T a<T>() => throw '';
 ''');
-    await resolveTestFile();
     assertInvokeType(findNode.methodInvocation('a('), 'dynamic Function()');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart
index 9dd6039..641ffb6 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart
@@ -20,13 +20,12 @@
 @reflectiveTest
 class IsNotTest extends DriverResolutionTest {
   test_simple() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(Object a) {
   var b = a is! String;
   print(b);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('b)'), 'bool');
   }
 }
@@ -45,13 +44,12 @@
 @reflectiveTest
 class IsTest extends DriverResolutionTest {
   test_simple() async {
-    addTestFile('''
+    await resolveTestCode('''
 void f(Object a) {
   var b = a is String;
   print(b);
 }
 ''');
-    await resolveTestFile();
     assertType(findNode.simple('b)'), 'bool');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
index 457e913..43bfb89 100644
--- a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
+++ b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
@@ -15,7 +15,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../embedder_tests.dart';
-import '../../../generated/test_support.dart';
 import '../../../resource_utils.dart';
 
 main() {
@@ -164,8 +163,8 @@
   void test_fromFile_library_firstExact() {
     FolderBasedDartSdk sdk = _createDartSdk();
     Folder dirHtml = sdk.libraryDirectory.getChildAssumingFolder("html");
-    Folder dirDartium = dirHtml.getChildAssumingFolder("dartium");
-    File file = dirDartium.getChildAssumingFile("html_dartium.dart");
+    Folder dirDartium = dirHtml.getChildAssumingFolder("dart2js");
+    File file = dirDartium.getChildAssumingFile("html_dart2js.dart");
     Source source = sdk.fromFileUri(file.toUri());
     expect(source, isNotNull);
     expect(source.isInSystemLibrary, isTrue);
@@ -180,7 +179,7 @@
     Source source = sdk.fromFileUri(file.toUri());
     expect(source, isNotNull);
     expect(source.isInSystemLibrary, isTrue);
-    expect(source.uri.toString(), "dart:html_common/html_common_dart2js.dart");
+    expect(source.uri.toString(), "dart:html_common");
   }
 
   void test_fromFile_part() {
@@ -264,9 +263,11 @@
     _createFile(sdkDirectory, ['lib', 'async', 'async.dart']);
     _createFile(sdkDirectory, ['lib', 'core', 'core.dart']);
     _createFile(sdkDirectory, ['lib', 'core', 'num.dart']);
+    _createFile(
+        sdkDirectory, ['lib', 'html', 'html_common', 'html_common.dart']);
     _createFile(sdkDirectory,
         ['lib', 'html', 'html_common', 'html_common_dart2js.dart']);
-    _createFile(sdkDirectory, ['lib', 'html', 'dartium', 'html_dartium.dart']);
+    _createFile(sdkDirectory, ['lib', 'html', 'dart2js', 'html_dart2js.dart']);
     _createFile(
         sdkDirectory, ['bin', (OSUtilities.isWindows() ? 'pub.bat' : 'pub')]);
     return new FolderBasedDartSdk(resourceProvider, sdkDirectory);
@@ -298,10 +299,9 @@
       dart2jsPatchPath: "_internal/js_runtime/lib/core_patch.dart"),
 
   "html": const LibraryInfo(
-      "html/dartium/html_dartium.dart",
+      "html/dart2js/html_dart2js.dart",
       categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      dart2jsPath: "html/dart2js/html_dart2js.dart"),
+      maturity: Maturity.WEB_STABLE),
 
   "html_common": const LibraryInfo(
       "html/html_common/html_common.dart",
@@ -356,41 +356,17 @@
 }
 
 @reflectiveTest
-class SdkLibrariesReaderTest extends EngineTestCase with ResourceProviderMixin {
-  void test_readFrom_dart2js() {
-    LibraryMap libraryMap =
-        new SdkLibrariesReader(true).readFromFile(getFile("/libs.dart"), r'''
-final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
-  'first' : const LibraryInfo(
-    'first/first.dart',
-    categories: 'Client',
-    documented: true,
-    platforms: VM_PLATFORM,
-    dart2jsPath: 'first/first_dart2js.dart'),
-};''');
-    expect(libraryMap, isNotNull);
-    expect(libraryMap.size(), 1);
-    SdkLibrary first = libraryMap.getLibrary("dart:first");
-    expect(first, isNotNull);
-    expect(first.category, "Client");
-    expect(first.path, "first/first_dart2js.dart");
-    expect(first.shortName, "dart:first");
-    expect(first.isDart2JsLibrary, false);
-    expect(first.isDocumented, true);
-    expect(first.isImplementation, false);
-    expect(first.isVmLibrary, true);
-  }
-
+class SdkLibrariesReaderTest with ResourceProviderMixin {
   void test_readFrom_empty() {
     LibraryMap libraryMap =
-        new SdkLibrariesReader(false).readFromFile(getFile("/libs.dart"), "");
+        new SdkLibrariesReader().readFromFile(getFile("/libs.dart"), "");
     expect(libraryMap, isNotNull);
     expect(libraryMap.size(), 0);
   }
 
   void test_readFrom_normal() {
     LibraryMap libraryMap =
-        new SdkLibrariesReader(false).readFromFile(getFile("/libs.dart"), r'''
+        new SdkLibrariesReader().readFromFile(getFile("/libs.dart"), r'''
 final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
   'first' : const LibraryInfo(
     'first/first.dart',
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
index a6894c5..e9b7c6c 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
@@ -168,7 +168,7 @@
     ]);
   }
 
-  test_operator_index() async {
+  test_operator_index_index() async {
     await assertErrorsInCode('''
 class A {}
 
@@ -186,6 +186,24 @@
     ]);
   }
 
+  test_operator_index_indexEq() async {
+    await assertErrorsInCode('''
+extension E1 on int {
+  int operator[](int index) => 0;
+}
+
+extension E2 on int {
+  void operator[]=(int index, int value) {}
+}
+
+f() {
+  0[1] += 2;
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS, 136, 1),
+    ]);
+  }
+
   test_operator_unary() async {
     await assertErrorsInCode('''
 class A {}
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_param_type_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_param_type_mismatch_test.dart
index 1c179be..b6f90a5 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_param_type_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_param_type_mismatch_test.dart
@@ -18,13 +18,6 @@
 @reflectiveTest
 class ConstConstructorParamTypeMismatchTest extends DriverResolutionTest {
   test_int_to_double_reference_from_other_library_other_file_after() async {
-    addTestFile('''
-class C {
-  final double d;
-  const C(this.d);
-}
-const C constant = const C(0);
-''');
     newFile('/test/lib/other.dart', content: '''
 import 'test.dart';
 class D {
@@ -33,7 +26,13 @@
 }
 const D constant2 = const D(constant);
 ''');
-    await resolveTestFile();
+    await resolveTestCode('''
+class C {
+  final double d;
+  const C(this.d);
+}
+const C constant = const C(0);
+''');
     assertNoTestErrors();
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
@@ -41,7 +40,7 @@
   }
 
   test_int_to_double_reference_from_other_library_other_file_before() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   final double d;
   const C(this.d);
@@ -59,37 +58,34 @@
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_int_to_double_single_library() async {
-    addTestFile('''
+    await resolveTestCode('''
 class C {
   final double d;
   const C(this.d);
 }
 const C constant = const C(0);
 ''');
-    await resolveTestFile();
     assertNoTestErrors();
   }
 
   test_int_to_double_via_default_value_other_file_after() async {
-    addTestFile('''
-import 'other.dart';
-
-void main() {
-  const c = C();
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class C {
   final double x;
   const C([this.x = 0]);
 }
 ''');
-    await resolveTestFile();
+    await resolveTestCode('''
+import 'other.dart';
+
+void main() {
+  const c = C();
+}
+''');
     assertNoTestErrors();
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
@@ -97,13 +93,6 @@
   }
 
   test_int_to_double_via_default_value_other_file_before() async {
-    addTestFile('''
-import 'other.dart';
-
-void main() {
-  const c = C();
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class C {
   final double x;
@@ -113,7 +102,14 @@
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
-    await resolveTestFile();
+
+    await resolveTestCode('''
+import 'other.dart';
+
+void main() {
+  const c = C();
+}
+''');
     assertNoTestErrors();
   }
 }
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
index 0bcdf0a..263cebb 100644
--- 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
@@ -26,7 +26,7 @@
     ..strictInference = true;
 
   test_extensionMethod() async {
-    assertErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 extension E on List {
   e() {
     return 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 736554b..846fd9c 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
@@ -20,111 +20,21 @@
 class InferenceFailureOnUninitializedVariableTest
     extends StaticTypeAnalyzer2TestShared {
   @override
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.strictInference = true;
-    resetWith(options: options);
-  }
-
-  test_localVariable() async {
-    String code = r'''
-void f() {
-  var a;
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
-  }
-
-  test_localVariable_withInitializer() async {
-    String code = r'''
-void f() {
-  var a = 7;
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_localVariable_withType() async {
-    String code = r'''
-void f() {
-  int a;
-  dynamic b;
-  Object c;
-  Null d;
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_topLevelVariable() async {
-    String code = r'''
-var a;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
-  }
-
-  test_topLevelVariable_withInitializer() async {
-    String code = r'''
-var a = 7;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_topLevelVariable_withType() async {
-    String code = r'''
-int a;
-dynamic b;
-Object c;
-Null d;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..strictInference = true;
 
   test_field() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C {
   var a;
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
-  }
-
-  test_finalField() async {
-    String code = r'''
-class C {
-  final a;
-  C(this.a);
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
-  }
-
-  test_staticField() async {
-    String code = r'''
-class C {
-  static var a;
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, 16, 1),
+    ]);
   }
 
   test_field_withInitializer() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C {
   static var c = 3;
   static final d = 5;
@@ -132,13 +42,11 @@
   var a = 7;
   final b = 9;
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
   }
 
   test_field_withType() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C {
   static int c;
   static final int d = 5;
@@ -148,8 +56,87 @@
 
   C(this.b);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
+  }
+
+  test_finalField() async {
+    await assertErrorsInCode(r'''
+class C {
+  final a;
+  C(this.a);
+}
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, 18, 1),
+    ]);
+  }
+
+  test_localVariable() async {
+    await assertErrorsInCode(r'''
+void f() {
+  var a;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, 17, 1),
+    ]);
+  }
+
+  test_localVariable_withInitializer() async {
+    await assertErrorsInCode(r'''
+void f() {
+  var a = 7;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+    ]);
+  }
+
+  test_localVariable_withType() async {
+    await assertErrorsInCode(r'''
+void f() {
+  int a;
+  dynamic b;
+  Object c;
+  Null d;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 42, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 52, 1),
+    ]);
+  }
+
+  test_staticField() async {
+    await assertErrorsInCode(r'''
+class C {
+  static var a;
+}
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, 23, 1),
+    ]);
+  }
+
+  test_topLevelVariable() async {
+    await assertErrorsInCode(r'''
+var a;
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, 4, 1),
+    ]);
+  }
+
+  test_topLevelVariable_withInitializer() async {
+    await assertNoErrorsInCode(r'''
+var a = 7;
+''');
+  }
+
+  test_topLevelVariable_withType() async {
+    await assertNoErrorsInCode(r'''
+int a;
+dynamic b;
+Object c;
+Null d;
+''');
   }
 }
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 e1cf255..5428deb 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
@@ -20,104 +20,135 @@
 class InferenceFailureOnUntypedParameterTest
     extends StaticTypeAnalyzer2TestShared {
   @override
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.strictInference = true;
-    resetWith(options: options);
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..strictInference = true;
+
+  test_fieldParameter() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int a;
+  C(this.a) {}
+}
+''');
   }
 
-  test_parameter() async {
-    String code = r'''
-void fn(a) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
+  test_functionTypedFormalParameter_withType() async {
+    await assertNoErrorsInCode(r'''
+void fn(String cb(int x)) => print(cb(7));
+''');
   }
 
-  test_parameter_withVar() async {
-    String code = r'''
-void fn(var a) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
-
-  test_parameter_withType() async {
-    String code = r'''
-void fn(int a) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_parameter_inGenericFunction_withType() async {
-    String code = r'''
-void fn<T>(T a) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_parameter_withVarAndDefault() async {
-    String code = r'''
-void fn([var a = 7]) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
-
-  test_parameter_withTypeAndDefault() async {
-    String code = r'''
-void fn([int a = 7]) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_namedParameter_withVar() async {
-    String code = r'''
-void fn({var a}) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
+  test_functionTypedFormalParameter_withVar() async {
+    await assertErrorsInCode(r'''
+void fn(String cb(var x)) => print(cb(7));
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 18, 5),
+    ]);
   }
 
   test_namedParameter_withType() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 void fn({int a}) => print(a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
+  }
+
+  test_namedParameter_withVar() async {
+    await assertErrorsInCode(r'''
+void fn({var a}) => print(a);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 9, 5),
+    ]);
+  }
+
+  test_parameter() async {
+    await assertErrorsInCode(r'''
+void fn(a) => print(a);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 1),
+    ]);
+  }
+
+  test_parameter_inConstructor() async {
+    await assertErrorsInCode(r'''
+class C {
+  C(var a) {}
+}
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 14, 5),
+    ]);
+  }
+
+  test_parameter_inConstructor_withType() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C(int a) {}
+}
+''');
+  }
+
+  test_parameter_inFunctionLiteral() async {
+    await assertErrorsInCode(r'''
+void fn() {
+  var f = (var a) {};
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 23, 5),
+    ]);
+  }
+
+  test_parameter_inFunctionLiteral_inferredType() async {
+    await assertNoErrorsInCode(r'''
+void fn() {
+  g((a, b) => print('$a$b'));
+}
+
+void g(void cb(int a, dynamic b)) => cb(7, "x");
+''');
+  }
+
+  test_parameter_inFunctionLiteral_inferredType_viaReturn() async {
+    await assertNoErrorsInCode(r'''
+void Function(int, dynamic) fn() {
+  return (a, b) => print('$a$b');
+}
+''');
+  }
+
+  test_parameter_inFunctionLiteral_withType() async {
+    await assertNoErrorsInCode(r'''
+void fn() {
+  var f = (int a) {};
+}
+''');
+  }
+
+  test_parameter_inGenericFunction_withType() async {
+    await assertNoErrorsInCode(r'''
+void fn<T>(T a) => print(a);
+''');
   }
 
   test_parameter_inMethod() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C {
   void fn(var a) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 20, 5),
+    ]);
   }
 
   test_parameter_inMethod_withType() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C {
   void fn(String a) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
   }
 
   test_parameter_inOverridingMethod() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C {
   void fn(int a) => print(a);
 }
@@ -126,29 +157,13 @@
   @override
   void fn(var a) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
-
-  test_parameter_inOverridingMethod_withType() async {
-    String code = r'''
-class C {
-  void fn(int a) => print(a);
-}
-
-class D extends C {
-  @override
-  void fn(num a) => print(a);
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 85, 5),
+    ]);
   }
 
   test_parameter_inOverridingMethod_withDefault() async {
-    String code = r'''
+    await assertErrorsInCode(r'''
 class C {
   void fn([int a = 7]) => print(a);
 }
@@ -157,14 +172,13 @@
   @override
   void fn([var a = 7]) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 92, 5),
+    ]);
   }
 
   test_parameter_inOverridingMethod_withDefaultAndType() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 class C {
   void fn([int a = 7]) => print(a);
 }
@@ -173,86 +187,61 @@
   @override
   void fn([num a = 7]) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
   }
 
-  test_parameter_inConstructor() async {
-    String code = r'''
+  test_parameter_inOverridingMethod_withType() async {
+    await assertNoErrorsInCode(r'''
 class C {
-  C(var a) {}
+  void fn(int a) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
 
-  test_parameter_inConstructor_withType() async {
-    String code = r'''
-class C {
-  C(int a) {}
+class D extends C {
+  @override
+  void fn(num a) => print(a);
 }
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_fieldParameter() async {
-    String code = r'''
-class C {
-  int a;
-  C(this.a) {}
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_parameter_inFunctionLiteral() async {
-    String code = r'''
-void fn() {
-  var f = (var a) {};
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
-
-  test_parameter_inFunctionLiteral_withType() async {
-    String code = r'''
-void fn() {
-  var f = (int a) {};
-}
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_functionTypeParameter_withVar() async {
-    String code = r'''
-void fn(String cb(var x)) => print(cb(7));
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER]);
-  }
-
-  test_functionTypeParameter_withType() async {
-    String code = r'''
-void fn(String cb(int x)) => print(cb(7));
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
   }
 
   test_parameter_inTypedef_withType() async {
-    String code = r'''
+    await assertNoErrorsInCode(r'''
 typedef cb = void Function(int a);
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
+''');
+  }
+
+  test_parameter_withoutKeyword() async {
+    await assertErrorsInCode(r'''
+void fn(a) => print(a);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 1),
+    ]);
+  }
+
+  test_parameter_withType() async {
+    await assertNoErrorsInCode(r'''
+void fn(int a) => print(a);
+''');
+  }
+
+  test_parameter_withTypeAndDefault() async {
+    await assertNoErrorsInCode(r'''
+void fn([int a = 7]) => print(a);
+''');
+  }
+
+  test_parameter_withVar() async {
+    await assertErrorsInCode(r'''
+void fn(var a) => print(a);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 5),
+    ]);
+  }
+
+  test_parameter_withVarAndDefault() async {
+    await assertErrorsInCode(r'''
+void fn([var a = 7]) => print(a);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 9, 5),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invocation_of_extension_without_call_test.dart b/pkg/analyzer/test/src/diagnostics/invocation_of_extension_without_call_test.dart
new file mode 100644
index 0000000..8708381
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invocation_of_extension_without_call_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/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(InvocationOfExtensionWithoutCallTest);
+  });
+}
+
+@reflectiveTest
+class InvocationOfExtensionWithoutCallTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_instance_differentKind() async {
+    await assertErrorsInCode('''
+extension E on Object {}
+f() {
+  E(null)();
+}
+''', [
+      error(CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL, 33, 7),
+    ]);
+  }
+}
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 b9b0063..f117889 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
@@ -88,7 +88,7 @@
         sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
 
   test_getter() async {
-    assertErrorsInCode('''
+    await assertErrorsInCode('''
 extension E on int {
   int get g => 0;
 }
@@ -101,7 +101,7 @@
   }
 
   test_method() async {
-    assertErrorsInCode('''
+    await assertErrorsInCode('''
 extension E on int {
   void m() {}
 }
@@ -114,7 +114,7 @@
   }
 
   test_setter() async {
-    assertErrorsInCode('''
+    await assertErrorsInCode('''
 extension E on int {
   void set s(int i) {}
 }
diff --git a/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart b/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart
index 3a50c22..90f4c84 100644
--- a/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart
@@ -27,20 +27,20 @@
     ..strictRawTypes = true;
 
   test_typeOnExtendedType_anonymous_missing() async {
-    assertErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 extension on List {}
 ''', [error(HintCode.STRICT_RAW_TYPE, 13, 4)]);
   }
 
   test_typeOnExtendedType_missing() async {
-    assertErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 extension E on List {}
 ''', [error(HintCode.STRICT_RAW_TYPE, 15, 4)]);
   }
 
   test_typeOnExtendedType_optionalTypeArgs() async {
     addMetaPackage();
-    assertNoErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @optionalTypeArgs
 class C<T> {}
@@ -50,7 +50,7 @@
   }
 
   test_typeOnExtendedType_present() async {
-    assertNoErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 extension E<T> on List<T> {}
 extension F on List<int> {}
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 5dbd49a..fd2ef4e 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -149,6 +149,8 @@
     as invalid_use_of_visible_for_testing_member;
 import 'invalid_visibility_annotation_test.dart'
     as invalid_visibility_annotation;
+import 'invocation_of_extension_without_call_test.dart'
+    as invocation_of_extension_without_call;
 import 'is_double_test.dart' as is_double;
 import 'is_int_test.dart' as is_int;
 import 'is_not_double_test.dart' as is_not_double;
@@ -293,6 +295,7 @@
 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_operator_test.dart' as undefined_extension_operator;
 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;
@@ -427,6 +430,7 @@
     invalid_use_of_visible_for_template_member.main();
     invalid_use_of_visible_for_testing_member.main();
     invalid_visibility_annotation.main();
+    invocation_of_extension_without_call.main();
     is_double.main();
     is_int.main();
     is_not_double.main();
@@ -527,6 +531,7 @@
     undefined_class.main();
     undefined_extension_getter.main();
     undefined_extension_method.main();
+    undefined_extension_operator.main();
     undefined_extension_setter.main();
     undefined_getter.main();
     undefined_hidden_name.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_method_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_method_test.dart
index 38ea384..4ac7029 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_extension_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_method_test.dart
@@ -51,32 +51,6 @@
     );
   }
 
-  test_operator_defined() async {
-    await assertNoErrorsInCode('''
-extension E on String {
-  void operator +(int offset) {}
-}
-f() {
-  E('a') + 1;
-}
-''');
-  }
-
-  test_operator_undefined() async {
-    await assertErrorsInCode('''
-extension E on String {}
-f() {
-  E('a') + 1;
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD, 40, 1),
-    ]);
-    var binaryExpression = findNode.binary('+ 1');
-    assertElementNull(binaryExpression);
-    assertInvokeTypeNull(binaryExpression);
-    assertTypeDynamic(binaryExpression);
-  }
-
   test_static_withInference() async {
     await assertErrorsInCode('''
 extension E on Object {}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart
new file mode 100644
index 0000000..36fe2ea
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart
@@ -0,0 +1,200 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All 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(UndefinedExtensionMethodTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedExtensionMethodTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_binary_defined() async {
+    await assertNoErrorsInCode('''
+extension E on String {
+  void operator +(int offset) {}
+}
+f() {
+  E('a') + 1;
+}
+''');
+  }
+
+  test_binary_undefined() async {
+    await assertErrorsInCode('''
+extension E on String {}
+f() {
+  E('a') + 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 40, 1),
+    ]);
+    var binaryExpression = findNode.binary('+ 1');
+    assertElementNull(binaryExpression);
+    assertInvokeTypeNull(binaryExpression);
+    assertTypeDynamic(binaryExpression);
+  }
+
+  test_index_get_hasGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  int operator[](int index) => 0;
+}
+
+f(A a) {
+  E(a)[0];
+}
+''');
+  }
+
+  test_index_get_hasNone() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {}
+
+f(A a) {
+  E(a)[0];
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 48, 3),
+    ]);
+  }
+
+  test_index_get_hasSetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  E(a)[0];
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 93, 3),
+    ]);
+  }
+
+  test_index_getSet_hasBoth() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  int operator[](int index) => 0;
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  E(a)[0] += 1;
+}
+''');
+  }
+
+  test_index_getSet_hasGetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  int operator[](int index) => 0;
+}
+
+f(A a) {
+  E(a)[0] += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 83, 3),
+    ]);
+  }
+
+  test_index_getSet_hasNone() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {}
+
+f(A a) {
+  E(a)[0] += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 48, 3),
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 48, 3),
+    ]);
+  }
+
+  test_index_getSet_hasSetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  E(a)[0] += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 93, 3),
+    ]);
+  }
+
+  test_index_set_hasGetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  int operator[](int index) => 0;
+}
+
+f(A a) {
+  E(a)[0] = 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 83, 3),
+    ]);
+  }
+
+  test_index_set_hasNone() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {}
+
+f(A a) {
+  E(a)[0] = 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 48, 3),
+    ]);
+  }
+
+  test_index_set_hasSetter() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  E(a)[0] = 1;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
index ee6452d..188e474 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UndefinedOperatorTest);
+    defineReflectiveTests(UndefinedOperatorTestWithExtensionMethodsTest);
   });
 }
 
@@ -44,103 +47,50 @@
     ]);
   }
 
+  test_index_both() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+f(A a) {
+  a[0]++;
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 24, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 24, 3),
+    ]);
+  }
+
+  test_index_getter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+f(A a) {
+  a[0];
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 24, 3),
+    ]);
+  }
+
   test_index_null() async {
     await assertErrorsInCode(r'''
-m() {
-  Null x;
+f(Null x) {
   x[0];
 }
 ''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 19, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 15, 3),
     ]);
   }
 
-  test_indexBoth() async {
+  test_index_setter() async {
     await assertErrorsInCode(r'''
 class A {}
-f(var a) {
-  if (a is A) {
-    a[0]++;
-  }
-}
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
-    ]);
-  }
 
-  test_indexBoth_inSubtype() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator [](int index) {}
-}
-f(var a) {
-  if (a is A) {
-    a[0]++;
-  }
+f(A a) {
+  a[0] = 1;
 }
 ''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
-    ]);
-  }
-
-  test_indexGetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-f(var a) {
-  if (a is A) {
-    a[0];
-  }
-}
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
-    ]);
-  }
-
-  test_indexGetter_inSubtype() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator [](int index) {}
-}
-f(var a) {
-  if (a is A) {
-    a[0];
-  }
-}
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
-    ]);
-  }
-
-  test_indexSetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-f(var a) {
-  if (a is A) {
-    a[0] = 1;
-  }
-}
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
-    ]);
-  }
-
-  test_indexSetter_inSubtype() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator []=(i, v) {}
-}
-f(var a) {
-  if (a is A) {
-    a[0] = 1;
-  }
-}
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 89, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 24, 3),
     ]);
   }
 
@@ -300,3 +250,76 @@
     ]);
   }
 }
+
+@reflectiveTest
+class UndefinedOperatorTestWithExtensionMethodsTest
+    extends UndefinedOperatorTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_index_get_extendedHasNone_extensionHasGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  int operator[](int index) => 0;
+}
+
+f(A a) {
+  a[0];
+}
+''');
+  }
+
+  test_index_get_extendedHasSetter_extensionHasGetter() async {
+    await assertErrorsInCode(r'''
+class A {
+  void operator[]=(int index, int value) {}
+}
+
+extension E on A {
+  int operator[](int index) => 0;
+}
+
+f(A a) {
+  a[0];
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 125, 3),
+    ]);
+  }
+
+  test_index_set_extendedHasGetter_extensionHasSetter() async {
+    await assertErrorsInCode(r'''
+class A {
+  int operator[](int index) => 0;
+}
+
+extension E on A {
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  a[0] = 1;
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 125, 3),
+    ]);
+  }
+
+  test_index_set_extendedHasNone_extensionHasSetter() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  void operator[]=(int index, int value) {}
+}
+
+f(A a) {
+  a[0] = 1;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/variable_type_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/variable_type_mismatch_test.dart
index e366f23..1cd6641 100644
--- a/pkg/analyzer/test/src/diagnostics/variable_type_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/variable_type_mismatch_test.dart
@@ -22,11 +22,10 @@
     // Note: in the following code, the declaration of `y` should produce an
     // error because we should only promote literal ints to doubles; we
     // shouldn't promote the reference to the variable `x`.
-    addTestFile('''
+    await resolveTestCode('''
 const Object x = 0;
 const double y = x;
     ''');
-    await resolveTestFile();
     assertTestErrorsWithCodes(
         [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
   }
diff --git a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
index deb16fa..e189d2c 100644
--- a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/extra_code_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/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:test/test.dart';
@@ -16,6 +17,7 @@
     defineReflectiveTests(ModifiersTest);
     defineReflectiveTests(MultipleTypeTest);
     defineReflectiveTests(PunctuationTest);
+    defineReflectiveTests(VarianceModifierTest);
   });
 }
 
@@ -307,3 +309,21 @@
 ''');
   }
 }
+
+/**
+ * Test how well the parser recovers when there is extra variance modifiers.
+ */
+@reflectiveTest
+class VarianceModifierTest extends AbstractRecoveryTest {
+  void test_extraModifier_inClass() {
+    testRecovery('''
+class A<in out X> {}
+''', [ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS], '''
+class A<in X> {}
+''',
+        featureSet: FeatureSet.forTesting(
+          sdkVersion: '2.5.0',
+          additionalFeatures: [Feature.variance],
+        ));
+  }
+}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 2d07417..06b49c5 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -23,9 +23,7 @@
   LinterContextImpl context;
 
   Future<void> resolve(String content) async {
-    addTestFile(content);
-    await resolveTestFile();
-
+    await resolveTestCode(content);
     var contextUnit = LinterContextUnit(result.content, result.unit);
     context = new LinterContextImpl(
       [contextUnit],
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index 2ec431a6..275c530 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -4,15 +4,13 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/resolver_test_case.dart';
-import '../../../generated/test_support.dart';
+import '../../dart/resolution/driver_resolution.dart';
 
 void main() {
   defineReflectiveSuite(() {
@@ -24,42 +22,35 @@
 ///
 /// https://github.com/dart-lang/sdk/issues/31638
 @reflectiveTest
-class Dart2InferenceTest extends ResolverTestCase {
-  @override
-  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
-
+class Dart2InferenceTest extends DriverResolutionTest {
   test_bool_assert() async {
     var code = r'''
-T f<T>() => null;
+T f<T>(int _) => null;
 
 main() {
-  assert(f()); // 1
-  assert(f(), f()); // 2
+  assert(f(1));
+  assert(f(2), f(3));
 }
 
 class C {
-  C() : assert(f()), // 3
-        assert(f(), f()); // 4
+  C() : assert(f(4)),
+        assert(f(5), f(6));
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    String getType(String prefix) {
-      var invocation = _findMethodInvocation(unit, code, prefix);
-      return invocation.staticInvokeType.toString();
+    await resolveTestCode(code);
+    MethodInvocation invocation(String search) {
+      return findNode.methodInvocation(search);
     }
 
-    expect(getType('f()); // 1'), 'bool Function()');
+    assertInvokeType(invocation('f(1));'), 'bool Function(int)');
 
-    expect(getType('f(), '), 'bool Function()');
-    expect(getType('f()); // 2'), 'dynamic Function()');
+    assertInvokeType(invocation('f(2)'), 'bool Function(int)');
+    assertInvokeType(invocation('f(3)'), 'dynamic Function(int)');
 
-    expect(getType('f()), // 3'), 'bool Function()');
+    assertInvokeType(invocation('f(4)'), 'bool Function(int)');
 
-    expect(getType('f(), '), 'bool Function()');
-    expect(getType('f()); // 4'), 'dynamic Function()');
+    assertInvokeType(invocation('f(5)'), 'bool Function(int)');
+    assertInvokeType(invocation('f(6)'), 'dynamic Function(int)');
   }
 
   test_bool_logical() async {
@@ -74,12 +65,9 @@
   var v2 = f() && f(); // 4
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
+    await resolveTestCode(code);
     void assertType(String prefix) {
-      var invocation = _findMethodInvocation(unit, code, prefix);
+      var invocation = findNode.methodInvocation(prefix);
       expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
@@ -105,12 +93,9 @@
   for (; f(); ) {} // 4
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
+    await resolveTestCode(code);
     void assertType(String prefix) {
-      var invocation = _findMethodInvocation(unit, code, prefix);
+      var invocation = findNode.methodInvocation(prefix);
       expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
@@ -127,11 +112,8 @@
   g = () => 42;
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    Expression closure = _findExpression(unit, code, '() => 42');
+    await resolveTestCode(code);
+    Expression closure = findNode.expression('() => 42');
     expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
@@ -144,16 +126,13 @@
   };
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    Expression closure = _findExpression(unit, code, '() { // mark');
+    await resolveTestCode(code);
+    Expression closure = findNode.expression('() { // mark');
     expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
   test_compoundAssignment_index() async {
-    var code = r'''
+    await resolveTestCode(r'''
 int getInt() => 0;
 num getNum() => 0;
 double getDouble() => 0.0;
@@ -273,15 +252,12 @@
   var /*@type=double*/ v10 = ++t['x'];
   var /*@type=double*/ v11 = t['x']++;
 }
-''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-    _assertTypeAnnotations(code, unit);
+''');
+    _assertTypeAnnotations();
   }
 
   test_compoundAssignment_prefixedIdentifier() async {
-    var code = r'''
+    await assertNoErrorsInCode(r'''
 int getInt() => 0;
 num getNum() => 0;
 double getDouble() => 0.0;
@@ -355,13 +331,8 @@
   var /*@type=double*/ v10 = ++t.x;
   var /*@type=double*/ v11 = t.x++;
 }
-''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-
-    var unit = analysisResult.unit;
-    _assertTypeAnnotations(code, unit);
+''');
+    _assertTypeAnnotations();
   }
 
   test_compoundAssignment_propertyAccess() async {
@@ -370,7 +341,7 @@
     var t5 = 'new Test<num, num>()';
     var t8 = 'new Test<double, num>()';
     var t9 = 'new Test<double, double>()';
-    var code = '''
+    await assertNoErrorsInCode('''
 int getInt() => 0;
 num getNum() => 0;
 double getDouble() => 0.0;
@@ -444,17 +415,12 @@
   var /*@type=double*/ v10 = ++$t9.x;
   var /*@type=double*/ v11 = $t9.x++;
 }
-''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-
-    var unit = analysisResult.unit;
-    _assertTypeAnnotations(code, unit);
+''');
+    _assertTypeAnnotations();
   }
 
   test_compoundAssignment_simpleIdentifier() async {
-    var code = r'''
+    await assertNoErrorsInCode(r'''
 int getInt() => 0;
 num getNum() => 0;
 double getDouble() => 0.0;
@@ -538,17 +504,12 @@
     var /*@type=double*/ v11 = x++;
   }
 }
-''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-
-    var unit = analysisResult.unit;
-    _assertTypeAnnotations(code, unit);
+''');
+    _assertTypeAnnotations();
   }
 
   test_compoundAssignment_simpleIdentifier_topLevel() async {
-    var code = r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 
 class B extends A {
@@ -562,13 +523,8 @@
 main() {
   var /*@type=B*/ v = topLevel += 1;
 }
-''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-
-    var unit = analysisResult.unit;
-    _assertTypeAnnotations(code, unit);
+''');
+    _assertTypeAnnotations();
   }
 
   test_forIn_identifier() async {
@@ -592,12 +548,9 @@
     for (aTopLevelSetter in f()) {} // top setter
   }
 }''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
+    await resolveTestCode(code);
     void assertType(String prefix) {
-      var invocation = _findMethodInvocation(unit, code, prefix);
+      var invocation = findNode.methodInvocation(prefix);
       expect(invocation.staticType.toString(), 'Iterable<A>');
     }
 
@@ -618,35 +571,32 @@
   for (num y in f()) {} // 3
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
+    await resolveTestCode(code);
     {
-      var node = EngineTestCase.findSimpleIdentifier(unit, code, 'w in');
+      var node = findNode.simple('w in');
       VariableElement element = node.staticElement;
       expect(node.staticType, typeProvider.dynamicType);
       expect(element.type, typeProvider.dynamicType);
 
-      var invocation = _findMethodInvocation(unit, code, 'f()) {} // 1');
+      var invocation = findNode.methodInvocation('f()) {} // 1');
       expect(invocation.staticType.toString(), 'Iterable<dynamic>');
     }
 
     {
-      var node = EngineTestCase.findSimpleIdentifier(unit, code, 'x in');
+      var node = findNode.simple('x in');
       VariableElement element = node.staticElement;
       expect(node.staticType, typeProvider.numType);
       expect(element.type, typeProvider.numType);
     }
 
     {
-      var node = EngineTestCase.findSimpleIdentifier(unit, code, 'y in');
+      var node = findNode.simple('y in');
       VariableElement element = node.staticElement;
 
       expect(node.staticType, typeProvider.numType);
       expect(element.type, typeProvider.numType);
 
-      var invocation = _findMethodInvocation(unit, code, 'f()) {} // 3');
+      var invocation = findNode.methodInvocation('f()) {} // 3');
       expect(invocation.staticType.toString(), 'Iterable<num>');
     }
   }
@@ -666,16 +616,13 @@
   for (B b3 in f(listB)) {} // 5
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
+    await resolveTestCode(code);
     void assertTypes(
         String vSearch, String vType, String fSearch, String fType) {
-      var node = EngineTestCase.findSimpleIdentifier(unit, code, vSearch);
+      var node = findNode.simple(vSearch);
       expect(node.staticType.toString(), vType);
 
-      var invocation = _findMethodInvocation(unit, code, fSearch);
+      var invocation = findNode.methodInvocation(fSearch);
       expect(invocation.staticType.toString(), fType);
     }
 
@@ -693,11 +640,8 @@
   operator []=(int index, double value) => null;
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    ClassElement c = unit.declaredElement.getType('C');
+    await resolveTestCode(code);
+    ClassElement c = findElement.class_('C');
 
     PropertyAccessorElement x = c.accessors[0];
     expect(x.returnType, VoidTypeImpl.instance);
@@ -717,11 +661,8 @@
   set x(_) {}
   operator[]=(int x, int y) {}
 }''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    ClassElement c = unit.declaredElement.getType('Derived');
+    await resolveTestCode(code);
+    ClassElement c = findElement.class_('Derived');
 
     PropertyAccessorElement x = c.accessors[0];
     expect(x.returnType, VoidTypeImpl.instance);
@@ -738,10 +679,8 @@
   f((x) {});
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-    var xNode = EngineTestCase.findSimpleIdentifier(unit, code, 'x) {}');
+    await resolveTestCode(code);
+    var xNode = findNode.simple('x) {}');
     VariableElement xElement = xNode.staticElement;
     expect(xNode.staticType, typeProvider.objectType);
     expect(xElement.type, typeProvider.objectType);
@@ -752,14 +691,11 @@
 var x = [];
 var y = {};
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    SimpleIdentifier x = _findExpression(unit, code, 'x = ');
+    await resolveTestCode(code);
+    SimpleIdentifier x = findNode.expression('x = ');
     expect(x.staticType.toString(), 'List<dynamic>');
 
-    SimpleIdentifier y = _findExpression(unit, code, 'y = ');
+    SimpleIdentifier y = findNode.expression('y = ');
     expect(y.staticType.toString(), 'Map<dynamic, dynamic>');
   }
 
@@ -768,14 +704,11 @@
 var x = [null];
 var y = {null: null};
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    SimpleIdentifier x = _findExpression(unit, code, 'x = ');
+    await resolveTestCode(code);
+    SimpleIdentifier x = findNode.expression('x = ');
     expect(x.staticType.toString(), 'List<Null>');
 
-    SimpleIdentifier y = _findExpression(unit, code, 'y = ');
+    SimpleIdentifier y = findNode.expression('y = ');
     expect(y.staticType.toString(), 'Map<Null, Null>');
   }
 
@@ -793,11 +726,8 @@
       break;
   }
 }''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    var node = _findInstanceCreation(unit, code, 'const C():');
+    await resolveTestCode(code);
+    var node = findNode.instanceCreation('const C():');
     expect(node.staticType.toString(), 'C<int>');
   }
 
@@ -811,14 +741,11 @@
   var y = new C().m();
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    SimpleIdentifier x = _findExpression(unit, code, 'x = ');
+    await resolveTestCode(code);
+    SimpleIdentifier x = findNode.expression('x = ');
     expect(x.staticType, VoidTypeImpl.instance);
 
-    SimpleIdentifier y = _findExpression(unit, code, 'y = ');
+    SimpleIdentifier y = findNode.expression('y = ');
     expect(y.staticType, VoidTypeImpl.instance);
   }
 
@@ -830,18 +757,18 @@
   var y = f();
 }
 ''';
-    var source = addSource(code);
-    var analysisResult = await computeAnalysisResult(source);
-    var unit = analysisResult.unit;
-
-    SimpleIdentifier x = _findExpression(unit, code, 'x = ');
+    await resolveTestCode(code);
+    SimpleIdentifier x = findNode.expression('x = ');
     expect(x.staticType, VoidTypeImpl.instance);
 
-    SimpleIdentifier y = _findExpression(unit, code, 'y = ');
+    SimpleIdentifier y = findNode.expression('y = ');
     expect(y.staticType, VoidTypeImpl.instance);
   }
 
-  void _assertTypeAnnotations(String code, CompilationUnit unit) {
+  void _assertTypeAnnotations() {
+    var code = result.content;
+    var unit = result.unit;
+
     var types = <int, String>{};
     {
       int lastIndex = 0;
@@ -858,43 +785,18 @@
         lastIndex = closeIndex;
       }
     }
-    unit.accept(new _TypeAnnotationsValidator(types));
-  }
 
-  Expression _findExpression(AstNode root, String code, String prefix) {
-    return EngineTestCase.findNode(root, code, prefix, (n) {
-      return n is Expression;
-    });
-  }
-
-  InstanceCreationExpression _findInstanceCreation(
-      AstNode root, String code, String prefix) {
-    return EngineTestCase.findNode(root, code, prefix, (n) {
-      return n is InstanceCreationExpression;
-    });
-  }
-
-  MethodInvocation _findMethodInvocation(
-      AstNode root, String code, String prefix) {
-    return EngineTestCase.findNode(root, code, prefix, (n) {
-      return n is MethodInvocation;
-    });
-  }
-}
-
-class _TypeAnnotationsValidator extends RecursiveAstVisitor {
-  final Map<int, String> types;
-
-  _TypeAnnotationsValidator(this.types);
-
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    Token comment = node.token.precedingComments;
-    if (comment != null) {
-      String expectedType = types[comment.offset];
-      if (expectedType != null) {
-        String actualType = node.staticType.toString();
-        expect(actualType, expectedType, reason: '@${comment.offset}');
-      }
-    }
+    unit.accept(FunctionAstVisitor(
+      simpleIdentifier: (node) {
+        Token comment = node.token.precedingComments;
+        if (comment != null) {
+          String expectedType = types[comment.offset];
+          if (expectedType != null) {
+            String actualType = node.staticType.toString();
+            expect(actualType, expectedType, reason: '@${comment.offset}');
+          }
+        }
+      },
+    ));
   }
 }
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 1340172..b881193 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -14,38 +14,15 @@
 import 'package:path/path.dart';
 import 'package:pub_semver/src/version_constraint.dart';
 import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../tool/diagnostics/generate.dart';
 import 'src/dart/resolution/driver_resolution.dart';
 
-/// 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.
-  //
-  DocumentationValidator validator = DocumentationValidator(codePaths);
-  await validator.validate();
-  //
-  // Validate that the generator has been run.
-  //
-  if (pathContext.style != Style.windows) {
-    String actualContent = PhysicalResourceProvider.INSTANCE
-        .getFile(computeOutputPath())
-        .readAsStringSync();
-
-    StringBuffer sink = StringBuffer();
-    DocumentationGenerator generator = DocumentationGenerator(codePaths);
-    generator.writeDocumentation(sink);
-    String expectedContent = sink.toString();
-
-    if (actualContent != expectedContent) {
-      fail('The diagnostic documentation needs to be regenerated.\n'
-          'Please run tool/diagnostics/generate.dart.');
-    }
-  }
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(VerifyDiagnosticsTest);
+  });
 }
 
 /// A class used to validate diagnostic documentation.
@@ -313,6 +290,39 @@
   }
 }
 
+/// Validate the documentation associated with the declarations of the error
+/// codes.
+@reflectiveTest
+class VerifyDiagnosticsTest {
+  test_diagnostics() async {
+    Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+    List<CodePath> codePaths = computeCodePaths();
+    //
+    // Validate that the input to the generator is correct.
+    //
+    DocumentationValidator validator = DocumentationValidator(codePaths);
+    await validator.validate();
+    //
+    // Validate that the generator has been run.
+    //
+    if (pathContext.style != Style.windows) {
+      String actualContent = PhysicalResourceProvider.INSTANCE
+          .getFile(computeOutputPath())
+          .readAsStringSync();
+
+      StringBuffer sink = StringBuffer();
+      DocumentationGenerator generator = DocumentationGenerator(codePaths);
+      generator.writeDocumentation(sink);
+      String expectedContent = sink.toString();
+
+      if (actualContent != expectedContent) {
+        fail('The diagnostic documentation needs to be regenerated.\n'
+            'Please run tool/diagnostics/generate.dart.');
+      }
+    }
+  }
+}
+
 /// A data holder used to return multiple values when extracting an error range
 /// from a snippet.
 class _SnippetData {
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 46b5264..daa7d2a 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -62,6 +62,34 @@
 doesn't conform to the language specification or
 that might work in unexpected ways.
 
+### abstract_super_member_reference
+
+_The {0} '{1}' is always abstract in the supertype._
+
+#### Description
+
+The analyzer produces this diagnostic when an inherited member is
+referenced using `super`, but there is no concrete implementation of the
+member in the superclass chain. Abstract members can't be invoked.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+abstract class A {
+  int get a;
+}
+class B extends A {
+  int get a => super.[!a!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the invocation of the abstract member, possibly replacing it with an
+invocation of a concrete member.
+
 ### ambiguous_extension_member_access
 
 _A member named '{0}' is defined in extensions '{1}' and '{2}' and neither is
@@ -302,6 +330,54 @@
 String g(num y) => f(y as String);
 {% endprettify %}
 
+### built_in_identifier_as_extension_name
+
+_The built-in identifier '{0}' can't be used as an extension name._
+
+#### Description
+
+The analyzer produces this diagnostic when the name of an extension is a
+built-in identifier. Built-in identifiers can’t be used as extension names.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension [!mixin!] on int {}
+{% endprettify %}
+
+#### Common fixes
+
+Choose a different name for the extension.
+
+### cast_to_non_type
+
+_The name '{0}' isn't a type, so it can't be used in an 'as' expression._
+
+#### Description
+
+The analyzer produces this diagnostic when the name following the `as` in a
+cast expression is defined to be something other than a type.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+num x = 0;
+int y = x as [!x!];
+{% endprettify %}
+
+#### Common fixes
+
+Replace the name with the name of a type:
+
+{% prettify dart %}
+num x = 0;
+int y = x as int;
+{% endprettify %}
+
 ### const_initialized_with_non_constant_value
 
 _Const variables must be initialized with a constant value._
@@ -340,6 +416,96 @@
 final y = x;
 {% endprettify %}
 
+### const_spread_expected_list_or_set
+
+_A list or a set is expected in this spread._
+
+#### Description
+
+The analyzer produces this diagnostic when the expression of a spread
+operator in a constant list or set evaluates to something other than a list
+or a set.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+const List<int> list1 = null;
+const List<int> list2 = [...[!list1!]];
+{% endprettify %}
+
+#### Common fixes
+
+Change the expression to something that evaluates to either a constant list
+or a constant set:
+
+{% prettify dart %}
+const List<int> list1 = [];
+const List<int> list2 = [...list1];
+{% endprettify %}
+
+### const_spread_expected_map
+
+_A map is expected in this spread._
+
+#### Description
+
+The analyzer produces this diagnostic when the expression of a spread
+operator in a constant map evaluates to something other than a map.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+const Map<String, int> map1 = null;
+const Map<String, int> map2 = {...[!map1!]};
+{% endprettify %}
+
+#### Common fixes
+
+Change the expression to something that evaluates to a constant map:
+
+{% prettify dart %}
+const Map<String, int> map1 = {};
+const Map<String, int> map2 = {...map1};
+{% endprettify %}
+
+### const_with_non_constant_argument
+
+_Arguments of a constant creation must be constant expressions._
+
+#### Description
+
+The analyzer produces this diagnostic when a const constructor is invoked
+with an argument that isn't a constant expression.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+class C {
+  final int i;
+  const C(this.i);
+}
+C f(int i) => const C([!i!]);
+{% endprettify %}
+
+#### Common fixes
+
+Either make all of the arguments constant expressions, or remove the
+`const` keyword to use the non-constant form of the constructor:
+
+{% prettify dart %}
+class C {
+  final int i;
+  const C(this.i);
+}
+C f(int i) => C(i);
+{% endprettify %}
+
 ### deprecated_member_use
 
 _'{0}' is deprecated and shouldn't be used._
@@ -390,6 +556,63 @@
 documentation for deprecated declarations should indicate what code to use
 in place of the deprecated code.
 
+### duplicate_definition
+
+_The name '{0}' is already defined._
+
+#### Description
+
+The analyzer produces this diagnostic when a name is declared, and there is
+a previous declaration with the same name in the same scope.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+int x = 0;
+int [!x!] = 1;
+{% endprettify %}
+
+#### Common fixes
+
+Choose a different name for one of the declarations.
+
+{% prettify dart %}
+int x = 0;
+int y = 1;
+{% endprettify %}
+
+### equal_elements_in_const_set
+
+_Two values in a constant set can't be equal._
+
+#### Description
+
+The analyzer produces this diagnostic when two elements in a constant set
+literal have the same value. The set can only contain each value once,
+which means that one of the values is unnecessary.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+const Set<String> set = {'a', [!'a'!]};
+{% endprettify %}
+
+#### Common fixes
+
+Remove one of the duplicate values:
+
+{% prettify dart %}
+const Set<String> set = {'a'};
+{% endprettify %}
+
+Note that literal sets preserve the order of their elements, so the choice
+of which element to remove might affect the order in which elements are
+returned by an iterator.
+
 ### equal_keys_in_const_map
 
 _Two keys in a constant map literal can't be equal._
@@ -411,18 +634,24 @@
 
 #### Common fixes
 
-If one of the keys was supposed to be different, then replace it:
+If both entries should be included in the map, then change one of the keys
+to be different:
 
 {% prettify dart %}
 const map = <int, String>{1: 'a', 2: 'b', 3: 'c', 4: 'd'};
 {% endprettify %}
 
-Otherwise, remove the key/value pair that isn't intended to be in the map:
+If only one of the entries is needed, then remove the one that isn't
+needed:
 
 {% prettify dart %}
 const map = <int, String>{1: 'a', 2: 'b', 4: 'd'};
 {% endprettify %}
 
+Note that literal maps preserve the order of their entries, so the choice
+of which entry to remove might affect the order in which keys and values
+are returned by an iterator.
+
 ### expression_in_map
 
 _Expressions can't be used in a map literal._
@@ -450,6 +679,41 @@
 var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
 {% endprettify %}
 
+### extension_as_expression
+
+_Extension '{0}' can't be used as an expression._
+
+#### Description
+
+The analyzer produces this diagnostic when the name of an extension is used
+in an expression other than in an extension override or to qualify an
+access to a static member of the extension.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on int {
+  static String m() => '';
+}
+
+var x = [!E!];
+{% endprettify %}
+
+#### Common fixes
+
+Replace the name of the extension with a name that can be referenced, such
+as a static member defined on the extension:
+
+{% prettify dart %}
+extension E on int {
+  static String m() => '';
+}
+
+var x = E.m();
+{% endprettify %}
+
 ### extension_conflicting_static_and_instance
 
 _Extension '{0}' can't define static member '{1}' and an instance member with
@@ -726,6 +990,240 @@
 }
 {% endprettify %}
 
+### extension_override_with_cascade
+
+_Extension overrides have no value so they can't be used as the target of a
+cascade expression._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is used as
+the target of a cascade expression.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on int {
+  void m() {}
+}
+f() {
+  E(3)[!..!]m();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Use '.' rather than '..':
+
+{% prettify dart %}
+extension E on int {
+  void m() {}
+}
+f() {
+  E(3).m();
+}
+{% endprettify %}
+
+If there are multiple cascaded accesses, you'll need to duplicate the
+extension override for each one.
+
+### extra_positional_arguments
+
+_Too many positional arguments: {0} expected, but {1} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function invocation
+has more positional arguments than the method or function allows.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f(int a, int b) {}
+void g() {
+  f[!(1, 2, 3)!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the arguments that don't correspond to parameters:
+
+{% prettify dart %}
+void f(int a, int b) {}
+void g() {
+  f(1, 2);
+}
+{% endprettify %}
+
+### extra_positional_arguments_could_be_named
+
+_Too many positional arguments: {0} expected, but {1} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function invocation
+has more positional arguments than the method or function allows, but the
+method or function defines named parameters.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f(int a, int b, {int c}) {}
+void g() {
+  f[!(1, 2, 3)!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If some of the arguments should be values for named parameters, then add
+the names before the arguments:
+
+{% prettify dart %}
+void f(int a, int b, {int c}) {}
+void g() {
+  f(1, 2, c: 3);
+}
+{% endprettify %}
+
+Otherwise, remove the arguments that don't correspond to positional
+parameters:
+
+{% prettify dart %}
+void f(int a, int b, {int c}) {}
+void g() {
+  f(1, 2);
+}
+{% endprettify %}
+
+### final_not_initialized
+
+_The final variable '{0}' must be initialized._
+
+#### Description
+
+The analyzer produces this diagnostic when a final field or variable isn't
+initialized.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+final [!x!];
+{% endprettify %}
+
+#### Common fixes
+
+For variables and static fields, you can add an initializer:
+
+{% prettify dart %}
+final x = 0;
+{% endprettify %}
+
+For instance fields, you can add an initializer as shown in the previous
+example, or you can initialize the field in every constructor. You can
+initialize the field by using a field formal parameter:
+
+{% prettify dart %}
+class C {
+  final int x;
+  C(this.x);
+}
+{% endprettify %}
+
+You can also initialize the field by using an initializer in the
+constructor:
+
+{% prettify dart %}
+class C {
+  final int x;
+  C(int y) : x = y * 2;
+}
+{% endprettify %}
+
+### implements_non_class
+
+_Classes and mixins can only implement other classes and mixins._
+
+#### Description
+
+The analyzer produces this diagnostic when a name used in the implements
+clause of a class or mixin declaration is defined to be something other
+than a class or mixin.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+var x;
+class C implements [!x!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If the name is the name of an existing class or mixin that's already being
+imported, then add a prefix to the import so that the local definition of
+the name doesn't shadow the imported name.
+
+If the name is the name of an existing class or mixin that isn't being
+imported, then add an import, with a prefix, for the library in which it’s
+declared.
+
+Otherwise, either replace the name in the implements clause with the name
+of an existing class or mixin, or remove the name from the implements
+clause.
+
+### invalid_assignment
+
+_A value of type '{0}' can't be assigned to a variable of type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the static type of an expression
+that is assigned to a variable isn't assignable to the type of the
+variable.
+
+#### Example
+
+The following code produces this diagnostic because the type of the
+initializer (`int`) isn't assignable to the type of the variable
+(`String`):
+
+{% prettify dart %}
+int i = 0;
+String s = [!i!];
+{% endprettify %}
+
+#### Common fixes
+
+If the value being assigned is always assignable at runtime, even though
+the static types don't reflect that, then add an explicit cast.
+
+Otherwise, change the value being assigned so that it has the expected
+type. In the previous example, this might look like:
+
+{% prettify dart %}
+int i = 0;
+String s = i.toString();
+{% endprettify %}
+
+If you can’t change the value, then change the type of the variable to be
+compatible with the type of the value being assigned:
+
+{% prettify dart %}
+int i = 0;
+int s = i;
+{% endprettify %}
+
 ### invalid_extension_argument_count
 
 _Extension overrides must have exactly one argument: the value of 'this' in the
@@ -864,6 +1362,44 @@
 
 Replace the name with the name of a function.
 
+### map_entry_not_in_map
+
+_Map entries can only be used in a map literal._
+
+#### Description
+
+The analyzer produces this diagnostic when a map entry (a key/value pair)
+is found in a set literal.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+const collection = <String>{[!'a' : 'b'!]};
+{% endprettify %}
+
+#### Common fixes
+
+If you intended for the collection to be a map, then change the code so
+that it is a map. In the previous example, you could do this by adding
+another type argument:
+
+{% prettify dart %}
+const collection = <String, String>{'a' : 'b'};
+{% endprettify %}
+
+In other cases, you might need to change the explicit type from `Set` to
+`Map`.
+
+If you intended for the collection to be a set, then remove the map entry,
+possibly by replacing the colon with a comma if both values should be
+included in the set:
+
+{% prettify dart %}
+const collection = <String>{'a', 'b'};
+{% endprettify %}
+
 ### missing_return
 
 _This function has a return type of '{0}', but doesn't end with a return
@@ -892,6 +1428,42 @@
 Add a return statement that makes the return value explicit, even if `null`
 is the appropriate value.
 
+### non_constant_case_expression
+
+_Case expressions must be constant._
+
+#### Description
+
+The analyzer produces this diagnostic when the expression in a case clause
+isn't a constant expression.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f(int i, int j) {
+  switch (i) {
+    case [!j!]:
+      // ...
+      break;
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Either make the expression a constant expression, or rewrite the switch
+statement as a sequence of if statements:
+
+{% prettify dart %}
+void f(int i, int j) {
+  if (i == j) {
+    // ...
+  }
+}
+{% endprettify %}
+
 ### non_constant_list_element
 
 _The values in a const list literal must be constants._
@@ -934,6 +1506,122 @@
 var y = <int>[0, 1, x];
 {% endprettify %}
 
+### non_constant_map_element
+
+_The elements in a const map literal must be constant._
+
+#### Description
+
+The analyzer produces this diagnostic when an if element or a spread
+element in a constant map isn't a constant element.
+
+#### Example
+
+The following code produces this diagnostic because it is attempting to
+spread a non-constant map:
+
+{% prettify dart %}
+var notConst = <int, int>{};
+var map = const <int, int>{...[!notConst!]};
+{% endprettify %}
+
+Similarly, the following code produces this diagnostic because the
+condition in the if element isn't a constant expression:
+
+{% prettify dart %}
+bool notConst = true;
+var map = const <int, int>{if ([!notConst!]) 1 : 2};
+{% endprettify %}
+
+#### Common fixes
+
+If the map needs to be a constant map, then make the elements  constants.
+In the spread example, you might do that by making the collection being
+spread a constant:
+
+{% prettify dart %}
+const notConst = <int, int>{};
+var map = const <int, int>{...notConst};
+{% endprettify %}
+
+If the map doesn't need to be a constant map, then remove the `const`
+keyword:
+
+{% prettify dart %}
+bool notConst = true;
+var map = <int, int>{if (notConst) 1 : 2};
+{% endprettify %}
+
+### non_constant_map_key
+
+_The keys in a const map literal must be constant._
+
+#### Description
+
+The analyzer produces this diagnostic when a key in a constant map literal
+isn't a constant value.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+var a = 'a';
+var m = const {[!a!]: 0};
+{% endprettify %}
+
+#### Common fixes
+
+If the map needs to be a constant map, then make the key a constant:
+
+{% prettify dart %}
+const a = 'a';
+var m = const {a: 0};
+{% endprettify %}
+
+If the map doesn't need to be a constant map, then remove the `const`
+keyword:
+
+{% prettify dart %}
+var a = 'a';
+var m = {a: 0};
+{% endprettify %}
+
+### non_constant_map_value
+
+_The values in a const map literal must be constant._
+
+#### Description
+
+The analyzer produces this diagnostic when a value in a constant map
+literal isn't a constant value.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+var a = 'a';
+var m = const {0: [!a!]};
+{% endprettify %}
+
+#### Common fixes
+
+If the map needs to be a constant map, then make the key a constant:
+
+{% prettify dart %}
+const a = 'a';
+var m = const {0: a};
+{% endprettify %}
+
+If the map doesn't need to be a constant map, then remove the `const`
+keyword:
+
+{% prettify dart %}
+var a = 'a';
+var m = {0: a};
+{% endprettify %}
+
 ### non_type_as_type_argument
 
 _The name '{0}' isn't a type so it can't be used as a type argument._
@@ -984,6 +1672,38 @@
 
 Replace the name with the name of a type.
 
+### not_enough_positional_arguments
+
+_{0} positional argument(s) expected, but {1} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function invocation
+has fewer positional arguments than the number of required positional
+parameters.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f(int a, int b) {}
+void g() {
+  f[!(0)!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add arguments corresponding to the remaining parameters:
+
+{% prettify dart %}
+void f(int a, int b) {}
+void g() {
+  f(0, 1);
+}
+{% endprettify %}
+
 ### not_iterable_spread
 
 _Spread elements in list or set literals must implement 'Iterable'._
@@ -1013,6 +1733,35 @@
 var s = <String>{...m.keys};
 {% endprettify %}
 
+### not_map_spread
+
+_Spread elements in map literals must implement 'Map'._
+
+#### Description
+
+The analyzer produces this diagnostic when the static type of the
+expression of a spread element that appears in a map literal doesn't
+implement the type `Map`.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+var l =  <String>['a', 'b'];
+var m = <int, String>{...[!l!]};
+{% endprettify %}
+
+#### Common fixes
+
+The most common fix is to replace the expression with one that produces a
+map:
+
+{% prettify dart %}
+var l =  <String>['a', 'b'];
+var m = <int, String>{...l.asMap()};
+{% endprettify %}
+
 ### redirect_to_non_class
 
 _The name '{0}' isn't a type and can't be used in a redirected constructor._
@@ -1055,6 +1804,55 @@
 }
 {% endprettify %}
 
+### referenced_before_declaration
+
+_Local variable '{0}' can't be referenced before it is declared._
+
+#### Description
+
+The analyzer produces this diagnostic when a variable is referenced before
+it’s declared. In Dart, variables are visible everywhere in the block in
+which they are declared, but can only be referenced after they are
+declared.
+
+The analyzer also produces a context message that indicates where the
+declaration is located.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f() {
+  print([!i!]);
+  int i = 5;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you intended to reference the local variable, move the declaration
+before the first reference:
+
+{% prettify dart %}
+void f() {
+  int i = 5;
+  print(i);
+}
+{% endprettify %}
+
+If you intended to reference a name from an outer scope, such as a
+parameter, instance field or top-level variable, then rename the local
+declaration so that it doesn't hide the outer variable.
+
+{% prettify dart %}
+void f(int i) {
+  print(i);
+  int x = 5;
+  print(x);
+}
+{% endprettify %}
+
 ### sdk_version_async_exported_from_core
 
 _The class '{0}' wasn't exported from 'dart:core' until version 2.1, but this
@@ -1589,6 +2387,78 @@
 var a = A<int>();
 {% endprettify %}
 
+### type_test_with_undefined_name
+
+_The name '{0}' isn't defined, so it can't be used in an 'is' expression._
+
+#### Description
+
+The analyzer produces this diagnostic when the name following the `is` in a
+type test expression isn't defined.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f(Object o) {
+  if (o is [!Srting!]) {
+    // ...
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Replace the name with the name of a type:
+
+{% prettify dart %}
+void f(Object o) {
+  if (o is String) {
+    // ...
+  }
+}
+{% endprettify %}
+
+### undefined_annotation
+
+_Undefined name '{0}' used as an annotation._
+
+#### Description
+
+The analyzer produces this diagnostic when a name that isn't defined is
+used as an annotation.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+[!@undefined!]
+void f() {}
+{% endprettify %}
+
+#### Common fixes
+
+If the name is correct, but it isn’t declared yet, then declare the name as
+a constant value:
+
+{% prettify dart %}
+const undefined = 'undefined';
+
+@undefined
+void f() {}
+{% endprettify %}
+
+If the name is wrong, replace the name with the name of a valid constant:
+
+{% prettify dart %}
+@deprecated
+void f() {}
+{% endprettify %}
+
+Otherwise, remove the annotation.
+
 ### undefined_class
 
 _Undefined class '{0}'._
@@ -2099,6 +2969,37 @@
 }
 {% endprettify %}
 
+### undefined_prefixed_name
+
+_The name '{0}' is being referenced through the prefix '{1}', but it isn't
+defined in any of the libraries imported using that prefix._
+
+#### Description
+
+The analyzer produces this diagnostic when a prefixed identifier is found
+where the prefix is valid, but the identifier isn't declared in any of the
+libraries imported using that prefix.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+import 'dart:core' as p;
+
+void f() {
+  p.[!a!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the library in which the name is declared isn't imported yet, add an
+import for the library.
+
+If the name is wrong, then change it to one of the names that's declared in
+the imported libraries.
+
 ### undefined_setter
 
 _The setter '{0}' isn't defined for the class '{1}'._
@@ -2137,6 +3038,100 @@
 }
 {% endprettify %}
 
+### undefined_super_method
+
+_The method '{0}' isn't defined in a superclass of '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when an inherited method is
+referenced using `super`, but there’s no method with that name in the
+superclass chain.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+class C {
+  void m() {
+    super.[!n!]();
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the inherited method you intend to invoke has a different name, then
+make the name of the invoked method  match the inherited method.
+
+If the method you intend to invoke is defined in the same class, then
+remove the `super.`.
+
+If not, then either add the method to one of the superclasses or remove the
+invocation.
+
+### 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._
+
+#### Description
+
+The analyzer produces this diagnostic when an undefined name is found, and
+the name is the same as a static member of the extended type or one of its
+superclasses.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+class C {
+  static void m() {}
+}
+
+extension E on C {
+  void f() {
+    [!m!]();
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you're trying to reference a static member that's declared outside the
+extension, then add the name of the class or extension before the reference
+to the member:
+
+{% prettify dart %}
+class C {
+  static void m() {}
+}
+
+extension E on C {
+  void f() {
+    C.m();
+  }
+}
+{% endprettify %}
+
+If you're referencing a member that isn't declared yet, add a declaration:
+
+{% prettify dart %}
+class C {
+  static void m() {}
+}
+
+extension E on C {
+  void f() {
+    m();
+  }
+
+  void m() {}
+}
+{% endprettify %}
+
 ### unused_element
 
 _The declaration '{0}' isn't referenced._
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
index 41d5c6a..9e16b8f 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -130,7 +130,7 @@
         : CompletionSuggestionKind.INVOCATION;
 
     if (!skipChildClass) {
-      _addSuggestionsForType(classElement.type, optype,
+      _addSuggestionsForType(classElement.thisType, optype,
           isFunctionalArgument: isFunctionalArgument);
     }
 
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index e118229..8e9c085 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -2253,6 +2253,10 @@
   /// where all types arguments are `dynamic`.
   InterfaceType getRawType(ClassEntity cls);
 
+  /// Returns the 'JS-interop type' of [cls]; that is, the instantiation of
+  /// [cls] where all type arguments are 'any'.
+  InterfaceType getJsInteropType(ClassEntity cls);
+
   /// Returns the 'this type' of [cls]. That is, the instantiation of [cls]
   /// where the type arguments are the type variables of [cls].
   InterfaceType getThisType(ClassEntity cls);
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 69425c5..df92e42 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -174,7 +174,8 @@
   final ClassEntity element;
   final List<DartType> typeArguments;
 
-  InterfaceType(this.element, this.typeArguments);
+  InterfaceType(this.element, this.typeArguments)
+      : assert(typeArguments.every((e) => e != null));
 
   @override
   bool get isInterfaceType => true;
@@ -942,7 +943,7 @@
 }
 
 /// A visitor that by default visits the substructure of the type until some
-/// visit returns`true`.  The default handers return `false` which will search
+/// visit returns `true`.  The default handers return `false` which will search
 /// the whole structure unless overridden.
 abstract class DartTypeStructuralPredicateVisitor
     extends DartTypeVisitor<bool, List<FunctionTypeVariable>> {
@@ -1528,11 +1529,12 @@
   }
 }
 
-// TODO(fishythefish): Support 'any'.
 abstract class MoreSpecificVisitor<T extends DartType>
     extends AbstractTypeRelation<T> {
   bool isMoreSpecific(T t, T s) {
     if (identical(t, s) ||
+        t.isAny ||
+        s.isAny ||
         s.treatAsDynamic ||
         s.isVoid ||
         s == commonElements.objectType ||
@@ -1582,10 +1584,10 @@
 }
 
 /// Type visitor that determines the subtype relation two types.
-// TODO(fishythefish): Support 'any'.
 abstract class SubtypeVisitor<T extends DartType>
     extends MoreSpecificVisitor<T> {
   bool isSubtype(DartType t, DartType s) {
+    if (t.isAny || s.isAny) return true;
     if (s.isFutureOr) {
       FutureOrType sFutureOr = s;
       if (isSubtype(t, sFutureOr.typeArgument)) {
@@ -1644,13 +1646,13 @@
 /// Type visitor that determines one type could a subtype of another given the
 /// right type variable substitution. The computation is approximate and returns
 /// `false` only if we are sure no such substitution exists.
-// TODO(fishythefish): Support 'any'.
 abstract class PotentialSubtypeVisitor<T extends DartType>
     extends SubtypeVisitor<T> {
   bool _assumeInstantiations = true;
 
   @override
   bool isSubtype(DartType t, DartType s) {
+    if (t.isAny || s.isAny) return true;
     if (t is TypeVariableType || s is TypeVariableType) {
       return true;
     }
diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart
index 5bc26a3..f8d5341 100644
--- a/pkg/compiler/lib/src/io/kernel_source_information.dart
+++ b/pkg/compiler/lib/src/io/kernel_source_information.dart
@@ -42,6 +42,11 @@
     [CallStructure callStructure]) {
   MemberDefinition definition = elementMap.getMemberDefinition(member);
   switch (definition.kind) {
+    case MemberKind.regular:
+      ir.Member node = definition.node;
+      if (node.isExtensionMember) return _findExtensionMemberName(node);
+      return computeElementNameForSourceMaps(member, callStructure);
+
     case MemberKind.closureCall:
       ir.TreeNode node = definition.node;
       String name;
@@ -70,6 +75,32 @@
   }
 }
 
+/// Extract a simple readable name for an extension member.
+String _findExtensionMemberName(ir.Member member) {
+  assert(member.isExtensionMember);
+  for (ir.Extension extension in member.enclosingLibrary.extensions) {
+    for (ir.ExtensionMemberDescriptor descriptor in extension.members) {
+      if (descriptor.member == member.reference) {
+        String extensionName;
+        // Anonymous extensions contain a # on their synthetic name.
+        if (extension.name.contains('#')) {
+          ir.DartType type = extension.onType;
+          if (type is ir.InterfaceType) {
+            extensionName = "${type.classNode.name}.<anonymous extension>";
+          } else {
+            extensionName = "<anonymous extension>";
+          }
+        } else {
+          extensionName = extension.name;
+        }
+        String memberName = descriptor.name.name;
+        return '$extensionName.$memberName';
+      }
+    }
+  }
+  throw StateError('No original name found for extension member $member.');
+}
+
 /// [SourceInformationBuilder] that generates [PositionSourceInformation] from
 /// Kernel nodes.
 class KernelSourceInformationBuilder implements SourceInformationBuilder {
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 0ec782d..084ffd0 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -220,9 +220,9 @@
     // Treat the properties of Object specially.
     String nameString = node.name.name;
     if (nameString == 'hashCode') {
-      return typeEnvironment.intType;
+      return typeEnvironment.coreTypes.intLegacyRawType;
     } else if (nameString == 'runtimeType') {
-      return typeEnvironment.typeType;
+      return typeEnvironment.coreTypes.typeLegacyRawType;
     }
     return const ir.DynamicType();
   }
@@ -382,7 +382,7 @@
 
   ir.Procedure _objectEquals;
   ir.Procedure get objectEquals =>
-      _objectEquals ??= _getMember(typeEnvironment.objectType.classNode, '==');
+      _objectEquals ??= _getMember(typeEnvironment.coreTypes.objectClass, '==');
 
   /// Returns [receiverType] narrowed to enclosing class of [interfaceTarget].
   ///
@@ -434,7 +434,7 @@
     /// [type].
     bool isTypeApplicable(ir.DartType type) {
       if (type is ir.DynamicType) return true;
-      if (type == typeEnvironment.rawFunctionType) return true;
+      if (type == typeEnvironment.coreTypes.functionLegacyRawType) return true;
       if (type is ir.FunctionType) {
         return isFunctionTypeApplicable(
             type.typeParameters.length,
@@ -636,7 +636,7 @@
     }
     if (node.name.name == '==') {
       // We use this special case to simplify generation of '==' checks.
-      return typeEnvironment.boolType;
+      return typeEnvironment.coreTypes.boolLegacyRawType;
     }
     return const ir.DynamicType();
   }
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 2da7c24..c544cb0 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -98,34 +98,36 @@
   }
 
   @override
-  ir.DartType visitBoolLiteral(ir.BoolLiteral node) => typeEnvironment.boolType;
+  ir.DartType visitBoolLiteral(ir.BoolLiteral node) =>
+      typeEnvironment.coreTypes.boolLegacyRawType;
 
   @override
   ir.DartType visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) =>
-      typeEnvironment.objectType;
+      typeEnvironment.coreTypes.objectLegacyRawType;
 
   @override
   ir.DartType visitStringLiteral(ir.StringLiteral node) =>
-      typeEnvironment.stringType;
+      typeEnvironment.coreTypes.stringLegacyRawType;
 
   @override
   ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
-    return typeEnvironment.stringType;
+    return typeEnvironment.coreTypes.stringLegacyRawType;
   }
 
   @override
   ir.DartType visitNullLiteral(ir.NullLiteral node) => typeEnvironment.nullType;
 
   @override
-  ir.DartType visitIntLiteral(ir.IntLiteral node) => typeEnvironment.intType;
+  ir.DartType visitIntLiteral(ir.IntLiteral node) =>
+      typeEnvironment.coreTypes.intLegacyRawType;
 
   @override
   ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) =>
-      typeEnvironment.doubleType;
+      typeEnvironment.coreTypes.doubleLegacyRawType;
 
   @override
   ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) =>
-      typeEnvironment.symbolType;
+      typeEnvironment.coreTypes.symbolLegacyRawType;
 
   @override
   ir.DartType visitListLiteral(ir.ListLiteral node) {
@@ -181,11 +183,11 @@
 
   @override
   ir.DartType visitLogicalExpression(ir.LogicalExpression node) =>
-      typeEnvironment.boolType;
+      typeEnvironment.coreTypes.boolLegacyRawType;
 
   @override
   ir.DartType visitNot(ir.Not node) {
-    return typeEnvironment.boolType;
+    return typeEnvironment.coreTypes.boolLegacyRawType;
   }
 
   @override
@@ -195,11 +197,12 @@
 
   @override
   ir.DartType visitIsExpression(ir.IsExpression node) {
-    return typeEnvironment.boolType;
+    return typeEnvironment.coreTypes.boolLegacyRawType;
   }
 
   @override
-  ir.DartType visitTypeLiteral(ir.TypeLiteral node) => typeEnvironment.typeType;
+  ir.DartType visitTypeLiteral(ir.TypeLiteral node) =>
+      typeEnvironment.coreTypes.typeLegacyRawType;
 
   @override
   ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
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 0dfdaf9..ecb9b52 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -473,26 +473,29 @@
     world.extractTypeArgumentsInterfacesNewRti.contains(cls);
 
 class _RulesetEntry {
-  final InterfaceType _targetType;
-  List<InterfaceType> _supertypes;
-  Map<TypeVariableType, DartType> _typeVariables;
+  Set<InterfaceType> _supertypes = {};
+  Map<TypeVariableType, DartType> _typeVariables = {};
 
-  _RulesetEntry(
-      this._targetType, Iterable<InterfaceType> supertypes, this._typeVariables)
-      : _supertypes = supertypes.toList();
+  void addAll(Iterable<InterfaceType> supertypes,
+      Map<TypeVariableType, DartType> typeVariables) {
+    _supertypes.addAll(supertypes);
+    _typeVariables.addAll(typeVariables);
+  }
 
   bool get isEmpty => _supertypes.isEmpty && _typeVariables.isEmpty;
 }
 
 class Ruleset {
-  List<_RulesetEntry> _entries;
+  Map<InterfaceType, _RulesetEntry> _entries;
 
   Ruleset(this._entries);
-  Ruleset.empty() : this([]);
+  Ruleset.empty() : this({});
 
   void add(InterfaceType targetType, Iterable<InterfaceType> supertypes,
-          Map<TypeVariableType, DartType> typeVariables) =>
-      _entries.add(_RulesetEntry(targetType, supertypes, typeVariables));
+      Map<TypeVariableType, DartType> typeVariables) {
+    _RulesetEntry entry = _entries[targetType] ??= _RulesetEntry();
+    entry.addAll(supertypes, typeVariables);
+  }
 }
 
 class RulesetEncoder {
@@ -515,16 +518,17 @@
 
   bool _isObject(InterfaceType type) => identical(type.element, _objectClass);
 
-  void _preprocessEntry(_RulesetEntry entry) {
+  void _preprocessEntry(InterfaceType targetType, _RulesetEntry entry) {
     entry._supertypes.removeWhere((InterfaceType supertype) =>
-        _isObject(supertype) || identical(entry._targetType, supertype));
+        _isObject(supertype) ||
+        identical(targetType.element, supertype.element));
   }
 
   void _preprocessRuleset(Ruleset ruleset) {
     ruleset._entries
-        .removeWhere((_RulesetEntry entry) => _isObject(entry._targetType));
+        .removeWhere((InterfaceType targetType, _) => _isObject(targetType));
     ruleset._entries.forEach(_preprocessEntry);
-    ruleset._entries.removeWhere((_RulesetEntry entry) => entry.isEmpty);
+    ruleset._entries.removeWhere((_, _RulesetEntry entry) => entry.isEmpty);
   }
 
   // TODO(fishythefish): Common substring elimination.
@@ -539,21 +543,22 @@
       js.concatenateStrings([
         _quote,
         _leftBrace,
-        ...js.joinLiterals(ruleset._entries.map(_encodeEntry), _comma),
+        ...js.joinLiterals(ruleset._entries.entries.map(_encodeEntry), _comma),
         _rightBrace,
         _quote,
       ]);
 
-  jsAst.StringConcatenation _encodeEntry(_RulesetEntry entry) =>
+  jsAst.StringConcatenation _encodeEntry(
+          MapEntry<InterfaceType, _RulesetEntry> entry) =>
       js.concatenateStrings([
-        js.quoteName(_emitter.typeAccessNewRti(entry._targetType.element)),
+        js.quoteName(_emitter.typeAccessNewRti(entry.key.element)),
         _colon,
         _leftBrace,
         ...js.joinLiterals([
-          ...entry._supertypes.map((InterfaceType supertype) =>
-              _encodeSupertype(entry._targetType, supertype)),
-          ...entry._typeVariables.entries.map((mapEntry) => _encodeTypeVariable(
-              entry._targetType, mapEntry.key, mapEntry.value))
+          ...entry.value._supertypes.map((InterfaceType supertype) =>
+              _encodeSupertype(entry.key, supertype)),
+          ...entry.value._typeVariables.entries.map((mapEntry) =>
+              _encodeTypeVariable(entry.key, mapEntry.key, mapEntry.value))
         ], _comma),
         _rightBrace,
       ]);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index adf8d1c..17d454c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -589,9 +589,12 @@
   RecipeEncoder _recipeEncoder;
   RulesetEncoder _rulesetEncoder;
 
+  ClassHierarchy get _classHierarchy => _closedWorld.classHierarchy;
+  CommonElements get _commonElements => _closedWorld.commonElements;
   DartTypes get _dartTypes => _closedWorld.dartTypes;
   JElementEnvironment get _elementEnvironment =>
       _closedWorld.elementEnvironment;
+  NativeData get _nativeData => _closedWorld.nativeData;
 
   js.Name _call0Name, _call1Name, _call2Name;
   js.Name get call0Name =>
@@ -1948,17 +1951,35 @@
     classes.forEach((Class cls) {
       if (cls.classChecksNewRti == null) return;
       InterfaceType targetType = _elementEnvironment.getThisType(cls.element);
-      Iterable<InterfaceType> supertypes = cls.classChecksNewRti.checks.map(
-          (TypeCheck check) => _dartTypes.asInstanceOf(targetType, check.cls));
+      bool isInterop = _nativeData.isJsInteropClass(cls.element);
+
+      Iterable<TypeCheck> checks = cls.classChecksNewRti.checks;
+      Iterable<InterfaceType> supertypes = isInterop
+          ? checks
+              .map((check) => _elementEnvironment.getJsInteropType(check.cls))
+          : checks
+              .map((check) => _dartTypes.asInstanceOf(targetType, check.cls));
+
       Map<TypeVariableType, DartType> typeVariables = {};
       for (TypeVariableType typeVariable in cls.namedTypeVariablesNewRti) {
         TypeVariableEntity element = typeVariable.element;
-        InterfaceType supertype =
-            _dartTypes.asInstanceOf(targetType, element.typeDeclaration);
+        InterfaceType supertype = isInterop
+            ? _elementEnvironment.getJsInteropType(element.typeDeclaration)
+            : _dartTypes.asInstanceOf(targetType, element.typeDeclaration);
         List<DartType> supertypeArguments = supertype.typeArguments;
         typeVariables[typeVariable] = supertypeArguments[element.index];
       }
-      ruleset.add(targetType, supertypes, typeVariables);
+
+      if (isInterop) {
+        _classHierarchy
+            .subtypesOf(_commonElements.jsJavaScriptObjectClass)
+            .forEach((ClassEntity interceptor) {
+          ruleset.add(_elementEnvironment.getThisType(interceptor), supertypes,
+              typeVariables);
+        });
+      } else {
+        ruleset.add(targetType, supertypes, typeVariables);
+      }
     });
 
     FunctionEntity method = _closedWorld.commonElements.rtiAddRulesMethod;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index ef075cd..0a78680 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -49,11 +49,13 @@
 import '../../js_backend/js_backend.dart'
     show Namer, ConstantEmitter, StringBackedName;
 import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
+import '../../js_backend/native_data.dart' show NativeData;
 import '../../js_backend/runtime_types.dart';
 import '../../js_backend/runtime_types_codegen.dart';
 import '../../js_backend/runtime_types_new.dart'
     show RecipeEncoder, RecipeEncoderImpl, Ruleset, RulesetEncoder;
 import '../../options.dart';
+import '../../universe/class_hierarchy.dart' show ClassHierarchy;
 import '../../universe/codegen_world_builder.dart' show CodegenWorld;
 import '../../world.dart';
 import '../code_emitter_task.dart';
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index e0ebc2f..4c87632 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -888,6 +888,9 @@
   InterfaceType get mixedInType => null;
 
   @override
+  InterfaceType get jsInteropType => thisType;
+
+  @override
   InterfaceType get rawType => thisType;
 }
 
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 43985c5..6b99f16 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -714,6 +714,20 @@
     }
   }
 
+  void _ensureJsInteropType(ClassEntity cls, JClassData data) {
+    assert(checkFamily(cls));
+    if (data is JClassDataImpl && data.jsInteropType == null) {
+      ir.Class node = data.cls;
+      if (node.typeParameters.isEmpty) {
+        _ensureThisAndRawType(cls, data);
+        data.jsInteropType = data.thisType;
+      } else {
+        data.jsInteropType = InterfaceType(cls,
+            List<DartType>.filled(node.typeParameters.length, const AnyType()));
+      }
+    }
+  }
+
   @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
@@ -993,6 +1007,13 @@
     return data.thisType;
   }
 
+  InterfaceType _getJsInteropType(IndexedClass cls) {
+    assert(checkFamily(cls));
+    JClassData data = classes.getData(cls);
+    _ensureJsInteropType(cls, data);
+    return data.jsInteropType;
+  }
+
   InterfaceType _getRawType(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -2181,6 +2202,11 @@
   }
 
   @override
+  InterfaceType getJsInteropType(ClassEntity cls) {
+    return elementMap._getJsInteropType(cls);
+  }
+
+  @override
   InterfaceType getRawType(ClassEntity cls) {
     return elementMap._getRawType(cls);
   }
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index ac096b1..527a27b 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -440,6 +440,7 @@
   ClassDefinition get definition;
 
   InterfaceType get thisType;
+  InterfaceType get jsInteropType;
   InterfaceType get rawType;
   InterfaceType get supertype;
   InterfaceType get mixedInType;
@@ -466,6 +467,8 @@
   @override
   InterfaceType thisType;
   @override
+  InterfaceType jsInteropType;
+  @override
   InterfaceType rawType;
   @override
   InterfaceType supertype;
diff --git a/pkg/compiler/lib/src/js_model/type_recipe.dart b/pkg/compiler/lib/src/js_model/type_recipe.dart
index ed1543c..9e17421 100644
--- a/pkg/compiler/lib/src/js_model/type_recipe.dart
+++ b/pkg/compiler/lib/src/js_model/type_recipe.dart
@@ -4,7 +4,77 @@
 
 library dart2js.js_model.type_recipe;
 
+import '../elements/entities.dart' show ClassEntity;
 import '../elements/types.dart';
+import '../diagnostics/invariant.dart';
+import '../diagnostics/spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
+
+abstract class TypeRecipeDomain {
+  /// Detect if a recipe evaluates to its input environment.
+  ///
+  /// Returns `true` if [recipe] evaluates in an environment with [structure] to
+  /// the environment. This is typically a recipe that selects the entire input.
+  bool isIdentity(TypeRecipe recipe, TypeEnvironmentStructure structure);
+
+  /// Detect if a recipe evaluates to its input environment.
+  ///
+  /// Returns `true` if [recipe] evaluates in an environment with
+  /// [environmentStructure] to the environment, where the environment is known
+  /// to be an instance type of exactly the class [classEntity].
+  ///
+  /// This is a special case of [isIdentity] where we have additional
+  /// information about the input environment that is not encoded in the
+  /// environment structure.
+  // TODO(sra): Consider extending TypeEnvironmentStructure to encode when the
+  // classType is an exact type. Then the [classEntity] parameter would not be
+  // needed.
+  bool isReconstruction(ClassEntity classEntity,
+      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);
+
+  /// Tries to evaluate [recipe] against a fixed environment [environmentRecipe]
+  /// having structure [environmentStructure].
+  ///
+  /// May return `null` if the evaluation is too complex.
+  TypeRecipe foldLoadEval(TypeRecipe environmentRecipe,
+      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);
+
+  /// Partial constant folding of a type expression when the environment is
+  /// created by binding a ground term.
+  ///
+  /// An 'original' environment is extended with [bindArgument] to produce an
+  /// intermediate environment with structure [environmentStructure]. [recipe]
+  /// is evaluated against this intermediate environment to produce a result.
+  ///
+  /// Returns the structure of the 'original' environment and a recipe that
+  /// evaluates against that structure to produce the same result.
+  ///
+  /// [bindArgument] must be a ground term, i.e. have no type variables.
+  TypeRecipeAndEnvironmentStructure foldBindLoadEval(
+    TypeRecipe bindArgument,
+    TypeEnvironmentStructure environmentStructure,
+    TypeRecipe recipe,
+  );
+
+  /// Combines [recipe1] and [recipe2] into a single recipe that can be
+  /// evaluated against [environmentStructure1]. ([recipe1] produces an
+  /// intermediate type or environment value that conforms to the layout
+  /// described by [environmentStructure2].)
+  TypeRecipeAndEnvironmentStructure foldEvalEval(
+    TypeEnvironmentStructure environmentStructure1,
+    TypeRecipe recipe1,
+    TypeEnvironmentStructure environmentStructure2,
+    TypeRecipe recipe2,
+  );
+}
+
+/// A type recipe and the structure of the type environment against which it is
+/// evaluated.
+class TypeRecipeAndEnvironmentStructure {
+  final TypeRecipe recipe;
+  final TypeEnvironmentStructure environmentStructure;
+
+  TypeRecipeAndEnvironmentStructure(this.recipe, this.environmentStructure);
+}
 
 /// A TypeEnvironmentStructure describes the shape or layout of a reified type
 /// environment.
@@ -79,17 +149,6 @@
     // yield the same type, e.g. `List<X> @X` and `List<Y> @Y`.
     return false;
   }
-
-  /// Returns `true` if [recipe] evaluates in an environment with [structure] to
-  /// the environment.
-  static bool isIdentity(
-      TypeRecipe recipe, TypeEnvironmentStructure structure) {
-    if (structure is SingletonTypeEnvironmentStructure &&
-        recipe is TypeExpressionRecipe) {
-      if (structure.variable == recipe.type) return true;
-    }
-    return false;
-  }
 }
 
 /// A recipe that yields a reified type.
@@ -161,3 +220,243 @@
   @override
   String toString() => 'FullTypeEnvironmentRecipe($classType, $types)';
 }
+
+class TypeRecipeDomainImpl implements TypeRecipeDomain {
+  @override
+  bool isIdentity(TypeRecipe recipe, TypeEnvironmentStructure structure) {
+    if (structure is SingletonTypeEnvironmentStructure &&
+        recipe is TypeExpressionRecipe) {
+      if (structure.variable == recipe.type) return true;
+    }
+    return false;
+  }
+
+  @override
+  bool isReconstruction(ClassEntity classEntity,
+      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
+    if (environmentStructure is FullTypeEnvironmentStructure &&
+        environmentStructure.bindings.isEmpty) {
+      InterfaceType classType = environmentStructure.classType;
+      if (classType.element == classEntity) {
+        if (recipe is TypeExpressionRecipe && recipe.type == classType) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  @override
+  TypeRecipe foldLoadEval(TypeRecipe environmentRecipe,
+      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
+    if (environmentStructure is SingletonTypeEnvironmentStructure) {
+      if (environmentRecipe is TypeExpressionRecipe) {
+        List<TypeVariableType> variables = [environmentStructure.variable];
+        List<DartType> replacements = [environmentRecipe.type];
+        return _Substitution(null, null, variables, replacements)
+            .substituteRecipe(recipe);
+      }
+      failedAt(CURRENT_ELEMENT_SPANNABLE,
+          'Expected a TypeExpressionRecipe: $environmentRecipe');
+      return null;
+    }
+
+    if (environmentStructure is FullTypeEnvironmentStructure) {
+      if (environmentStructure.classType != null) {
+        if (environmentRecipe is TypeExpressionRecipe) {
+          assert(environmentStructure.bindings.isEmpty);
+          return _Substitution(environmentStructure.classType,
+                  environmentRecipe.type, null, null)
+              .substituteRecipe(recipe);
+        }
+        return null;
+      }
+      if (environmentRecipe is TypeExpressionRecipe) {
+        // Is this possible?
+        return null;
+      }
+      if (environmentRecipe is FullTypeEnvironmentRecipe) {
+        return _Substitution(
+                environmentStructure.classType,
+                environmentRecipe.classType,
+                environmentStructure.bindings,
+                environmentRecipe.types)
+            .substituteRecipe(recipe);
+      }
+      return null;
+    }
+
+    failedAt(CURRENT_ELEMENT_SPANNABLE,
+        'Unknown environmentStructure: $environmentStructure');
+    return null;
+  }
+
+  @override
+  TypeRecipeAndEnvironmentStructure foldBindLoadEval(TypeRecipe bindArgument,
+      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
+    // 'Bind' adds variables to the environment. We fold 'bind' of a ground type
+    // by removing the added variables and replacing them in the recipe with the
+    // constant type values.
+
+    if (environmentStructure is FullTypeEnvironmentStructure) {
+      List<DartType> replacements;
+      if (bindArgument is TypeExpressionRecipe) {
+        // Bind call adds a single binding.
+        replacements = [bindArgument.type];
+      } else if (bindArgument is FullTypeEnvironmentRecipe) {
+        replacements = bindArgument.types;
+      } else {
+        failedAt(CURRENT_ELEMENT_SPANNABLE,
+            'Unexpected bindArgument: $bindArgument');
+      }
+      List<TypeVariableType> bindings = environmentStructure.bindings;
+      int index = bindings.length - replacements.length;
+      List<TypeVariableType> replacedVariables = bindings.sublist(index);
+      List<TypeVariableType> remainingVariables = bindings.sublist(0, index);
+      TypeRecipe newRecipe =
+          _Substitution(null, null, replacedVariables, replacements)
+              .substituteRecipe(recipe);
+      if (newRecipe == null) return null;
+      TypeEnvironmentStructure newEnvironmentStructure =
+          FullTypeEnvironmentStructure(
+              classType: environmentStructure.classType,
+              bindings: remainingVariables);
+      return TypeRecipeAndEnvironmentStructure(
+          newRecipe, newEnvironmentStructure);
+    }
+
+    failedAt(CURRENT_ELEMENT_SPANNABLE,
+        'unexpected bind on environment with structure $environmentStructure');
+    return null;
+  }
+
+  @override
+  TypeRecipeAndEnvironmentStructure foldEvalEval(
+      TypeEnvironmentStructure environmentStructure1,
+      TypeRecipe recipe1,
+      TypeEnvironmentStructure environmentStructure2,
+      TypeRecipe recipe2) {
+    if (environmentStructure2 is SingletonTypeEnvironmentStructure &&
+        recipe1 is TypeExpressionRecipe) {
+      TypeRecipe newRecipe = _Substitution(
+              null, null, [environmentStructure2.variable], [recipe1.type])
+          .substituteRecipe(recipe2);
+      if (newRecipe == null) return null;
+      return TypeRecipeAndEnvironmentStructure(
+          newRecipe, environmentStructure1);
+    }
+
+    if (environmentStructure2 is FullTypeEnvironmentStructure &&
+        recipe1 is TypeExpressionRecipe) {
+      assert(environmentStructure2.bindings.isEmpty);
+      TypeRecipe newRecipe = _Substitution(
+              environmentStructure2.classType, recipe1.type, null, null)
+          .substituteRecipe(recipe2);
+      if (newRecipe == null) return null;
+      return TypeRecipeAndEnvironmentStructure(
+          newRecipe, environmentStructure1);
+    }
+
+    if (environmentStructure2 is FullTypeEnvironmentStructure &&
+        recipe1 is FullTypeEnvironmentRecipe) {
+      TypeRecipe newRecipe = _Substitution(environmentStructure2.classType,
+              recipe1.classType, environmentStructure2.bindings, recipe1.types)
+          .substituteRecipe(recipe2);
+      if (newRecipe == null) return null;
+      return TypeRecipeAndEnvironmentStructure(
+          newRecipe, environmentStructure1);
+    }
+
+    return null;
+  }
+}
+
+/// Substitution algorithm for transforming a TypeRecipe by substitution of
+/// bindings of a type environment.
+///
+/// Since the general case of a type environment has class type variables (bound
+/// by a class instance type) and method type variable bindings, both are
+/// provided. The class type variables can be implicit (e.g. CodeUnits defines
+/// ListMixin.E), whereas the method type variables are always bound explicitly.
+///
+/// A [_Substitution] contains the bindings and the state required to perform
+/// a single substitution.
+class _Substitution extends DartTypeSubstitutionVisitor<Null> {
+  final Map<DartType, DartType> _lookupCache = {};
+  final Map<DartType, int> _counts = {};
+  bool _failed = false;
+
+  final InterfaceType _classEnvironment;
+  final InterfaceType _classValue;
+  final List<TypeVariableType> _variables;
+  final List<DartType> _replacements;
+
+  _Substitution(this._classEnvironment, this._classValue, this._variables,
+      this._replacements)
+      : assert(_variables?.length == _replacements?.length);
+
+  // Returns `null` if declined.
+  TypeRecipe substituteRecipe(TypeRecipe recipe) {
+    if (recipe is TypeExpressionRecipe) {
+      DartType result = _substituteType(recipe.type);
+      if (_failed) return null;
+      return TypeExpressionRecipe(result);
+    }
+    if (recipe is FullTypeEnvironmentRecipe) {
+      DartType newClass = _substitutePossiblyNullType(recipe.classType);
+      List<DartType> newTypes = recipe.types.map(_substituteType).toList();
+      if (_failed) return null;
+      return FullTypeEnvironmentRecipe(classType: newClass, types: newTypes);
+    }
+
+    failedAt(CURRENT_ELEMENT_SPANNABLE, 'Unexpected recipe: $recipe');
+    return null;
+  }
+
+  DartType _substituteType(DartType type) => visit(type, null);
+
+  DartType _substitutePossiblyNullType(DartType type) =>
+      type == null ? null : visit(type, null);
+
+  // Returns `null` if not bound.
+  DartType _lookupTypeVariableType(TypeVariableType type) {
+    if (_variables != null) {
+      int index = _variables.indexOf(type);
+      if (index >= 0) return _replacements[index];
+    }
+    if (_classEnvironment == null) return null;
+
+    if (_classEnvironment.element == _classValue.element) {
+      int index = _classEnvironment.typeArguments.indexOf(type);
+      if (index >= 0) return _classValue.typeArguments[index];
+      return null;
+    }
+    // TODO(sra): Lookup type variable of supertype (e.g. ListMixin.E of
+    // CodeUnits).
+    _failed = true;
+    return null;
+  }
+
+  @override
+  DartType substituteTypeVariableType(
+      TypeVariableType variable, Null argument, bool freshReference) {
+    DartType replacement =
+        _lookupCache[variable] ??= _lookupTypeVariableType(variable);
+    if (replacement == null) return variable; // not substituted.
+    if (!freshReference) return replacement;
+    int count = _counts[variable] = (_counts[variable] ?? 0) + 1;
+    if (count > 1) {
+      // If the replacement is 'big', duplicating it can grow the term, perhaps
+      // exponentially given a sufficently pathological input.
+      // TODO(sra): Fix exponential terms by encoding a DAG in recipes to avoid
+      // linearization.
+      if (replacement is FunctionType ||
+          replacement is InterfaceType &&
+              replacement.typeArguments.isNotEmpty ||
+          replacement is FutureOrType) {
+        _failed = true;
+      }
+    }
+    return replacement;
+  }
+}
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 5818ce3..1c3701c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -285,6 +285,20 @@
     }
   }
 
+  void _ensureJsInteropType(ClassEntity cls, KClassData data) {
+    assert(checkFamily(cls));
+    if (data is KClassDataImpl && data.jsInteropType == null) {
+      ir.Class node = data.node;
+      if (node.typeParameters.isEmpty) {
+        _ensureThisAndRawType(cls, data);
+        data.jsInteropType = data.thisType;
+      } else {
+        data.jsInteropType = InterfaceType(cls,
+            List<DartType>.filled(node.typeParameters.length, const AnyType()));
+      }
+    }
+  }
+
   @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
@@ -567,6 +581,13 @@
     return data.thisType;
   }
 
+  InterfaceType _getJsInteropType(IndexedClass cls) {
+    assert(checkFamily(cls));
+    KClassData data = classes.getData(cls);
+    _ensureJsInteropType(cls, data);
+    return data.jsInteropType;
+  }
+
   InterfaceType _getRawType(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -1645,6 +1666,11 @@
   }
 
   @override
+  InterfaceType getJsInteropType(ClassEntity cls) {
+    return elementMap._getJsInteropType(cls);
+  }
+
+  @override
   InterfaceType getRawType(ClassEntity cls) {
     return elementMap._getRawType(cls);
   }
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 1b22344..8dd1973 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -612,6 +612,7 @@
   ir.Class get node;
 
   InterfaceType get thisType;
+  InterfaceType get jsInteropType;
   InterfaceType get rawType;
   InterfaceType get supertype;
   InterfaceType get mixedInType;
@@ -638,6 +639,8 @@
   @override
   InterfaceType thisType;
   @override
+  InterfaceType jsInteropType;
+  @override
   InterfaceType rawType;
   @override
   InterfaceType supertype;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 2e65567..b23b29c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4698,8 +4698,9 @@
         InterfaceType(_commonElements.jsArrayClass, [DynamicType()]);
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCall(invocation, invocation);
-    HInstruction rti = HLoadType(interopType, _abstractValueDomain.dynamicType)
-      ..sourceInformation = sourceInformation;
+    HInstruction rti =
+        HLoadType.type(interopType, _abstractValueDomain.dynamicType)
+          ..sourceInformation = sourceInformation;
     push(rti);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 1197751..158413d 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -31,7 +31,6 @@
     show RecipeEncoder, RecipeEncoding;
 import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
 import '../js_model/elements.dart' show JGeneratorBody;
-import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 import '../native/behavior.dart';
 import '../options.dart';
 import '../tracer.dart';
@@ -3400,8 +3399,8 @@
     FunctionEntity helperElement = _commonElements.findType;
     _registry.registerStaticUse(
         new StaticUse.staticInvoke(helperElement, CallStructure.ONE_ARG));
-    js.Expression recipe = _rtiRecipeEncoder.encodeGroundRecipe(
-        _emitter, TypeExpressionRecipe(node.typeExpression));
+    js.Expression recipe =
+        _rtiRecipeEncoder.encodeGroundRecipe(_emitter, node.typeExpression);
     js.Expression helper = _emitter.staticFunctionAccess(helperElement);
     push(js.js(r'#(#)', [helper, recipe]).withSourceInformation(
         node.sourceInformation));
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 495f629..068ae28 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -14,7 +14,8 @@
 import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
-import '../js_model/type_recipe.dart' show TypeEnvironmentStructure, TypeRecipe;
+import '../js_model/type_recipe.dart'
+    show TypeEnvironmentStructure, TypeRecipe, TypeExpressionRecipe;
 import '../native/behavior.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
@@ -4518,12 +4519,16 @@
 
 /// Evaluates an Rti type recipe in the global environment.
 class HLoadType extends HRtiInstruction {
-  DartType typeExpression; // TODO(sra): Allow a type environment expression.
+  TypeRecipe typeExpression;
 
-  HLoadType(this.typeExpression, AbstractValue type) : super([], type) {
+  HLoadType(this.typeExpression, AbstractValue instructionType)
+      : super([], instructionType) {
     setUseGvn();
   }
 
+  HLoadType.type(DartType dartType, AbstractValue instructionType)
+      : this(TypeExpressionRecipe(dartType), instructionType);
+
   @override
   accept(HVisitor visitor) => visitor.visitLoadType(this);
 
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 8eb2043..d7d7140 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -18,7 +18,13 @@
 import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/native_data.dart' show NativeData;
 import '../js_backend/runtime_types_codegen.dart';
-import '../js_model/type_recipe.dart' show TypeRecipe;
+import '../js_model/type_recipe.dart'
+    show
+        TypeRecipe,
+        TypeExpressionRecipe,
+        TypeRecipeAndEnvironmentStructure,
+        TypeRecipeDomain,
+        TypeRecipeDomainImpl;
 import '../js_backend/specialized_checks.dart';
 import '../native/behavior.dart';
 import '../options.dart';
@@ -70,6 +76,8 @@
     SsaCodeMotion codeMotion;
     SsaLoadElimination loadElimination;
 
+    TypeRecipeDomain typeRecipeDomain = TypeRecipeDomainImpl();
+
     OptimizationTestLog log;
     if (retainDataForTesting) {
       loggersForTesting ??= {};
@@ -80,8 +88,14 @@
       List<OptimizationPhase> phases = <OptimizationPhase>[
         // Run trivial instruction simplification first to optimize
         // some patterns useful for type conversion.
-        new SsaInstructionSimplifier(globalInferenceResults, _options,
-            codegen.rtiSubstitutions, closedWorld, registry, log),
+        new SsaInstructionSimplifier(
+            globalInferenceResults,
+            _options,
+            codegen.rtiSubstitutions,
+            closedWorld,
+            typeRecipeDomain,
+            registry,
+            log),
         new SsaTypeConversionInserter(closedWorld),
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
@@ -89,11 +103,23 @@
             closedWorld.commonElements, closedWorld, log),
         // After type propagation, more instructions can be
         // simplified.
-        new SsaInstructionSimplifier(globalInferenceResults, _options,
-            codegen.rtiSubstitutions, closedWorld, registry, log),
+        new SsaInstructionSimplifier(
+            globalInferenceResults,
+            _options,
+            codegen.rtiSubstitutions,
+            closedWorld,
+            typeRecipeDomain,
+            registry,
+            log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
-        new SsaInstructionSimplifier(globalInferenceResults, _options,
-            codegen.rtiSubstitutions, closedWorld, registry, log),
+        new SsaInstructionSimplifier(
+            globalInferenceResults,
+            _options,
+            codegen.rtiSubstitutions,
+            closedWorld,
+            typeRecipeDomain,
+            registry,
+            log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
         new SsaTypePropagator(globalInferenceResults,
             closedWorld.commonElements, closedWorld, log),
@@ -118,8 +144,14 @@
         new SsaValueRangeAnalyzer(closedWorld, this),
         // Previous optimizations may have generated new
         // opportunities for instruction simplification.
-        new SsaInstructionSimplifier(globalInferenceResults, _options,
-            codegen.rtiSubstitutions, closedWorld, registry, log),
+        new SsaInstructionSimplifier(
+            globalInferenceResults,
+            _options,
+            codegen.rtiSubstitutions,
+            closedWorld,
+            typeRecipeDomain,
+            registry,
+            log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
       ];
       phases.forEach(runPhase);
@@ -133,6 +165,7 @@
       runPhase(dce);
       if (codeMotion.movedCode ||
           dce.eliminatedSideEffects ||
+          dce.newGvnCandidates ||
           loadElimination.newGvnCandidates) {
         phases = <OptimizationPhase>[
           new SsaTypePropagator(globalInferenceResults,
@@ -140,8 +173,14 @@
           new SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
           new SsaCodeMotion(closedWorld.abstractValueDomain),
           new SsaValueRangeAnalyzer(closedWorld, this),
-          new SsaInstructionSimplifier(globalInferenceResults, _options,
-              codegen.rtiSubstitutions, closedWorld, registry, log),
+          new SsaInstructionSimplifier(
+              globalInferenceResults,
+              _options,
+              codegen.rtiSubstitutions,
+              closedWorld,
+              typeRecipeDomain,
+              registry,
+              log),
           new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
           new SsaSimplifyInterceptors(closedWorld, member.enclosingClass),
           new SsaDeadCodeEliminator(closedWorld, this),
@@ -152,8 +191,14 @@
               closedWorld.commonElements, closedWorld, log),
           // Run the simplifier to remove unneeded type checks inserted by
           // type propagation.
-          new SsaInstructionSimplifier(globalInferenceResults, _options,
-              codegen.rtiSubstitutions, closedWorld, registry, log),
+          new SsaInstructionSimplifier(
+              globalInferenceResults,
+              _options,
+              codegen.rtiSubstitutions,
+              closedWorld,
+              typeRecipeDomain,
+              registry,
+              log),
         ];
       }
       phases.forEach(runPhase);
@@ -196,12 +241,19 @@
   final CompilerOptions _options;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
   final JClosedWorld _closedWorld;
+  final TypeRecipeDomain _typeRecipeDomain;
   final CodegenRegistry _registry;
   final OptimizationTestLog _log;
   HGraph _graph;
 
-  SsaInstructionSimplifier(this._globalInferenceResults, this._options,
-      this._rtiSubstitutions, this._closedWorld, this._registry, this._log);
+  SsaInstructionSimplifier(
+      this._globalInferenceResults,
+      this._options,
+      this._rtiSubstitutions,
+      this._closedWorld,
+      this._typeRecipeDomain,
+      this._registry,
+      this._log);
 
   JCommonElements get commonElements => _closedWorld.commonElements;
 
@@ -638,7 +690,7 @@
 
     HInstruction typeInfo;
     if (_options.experimentNewRti) {
-      typeInfo = HLoadType(
+      typeInfo = HLoadType.type(
           _closedWorld.elementEnvironment.createInterfaceType(
               commonElements.jsArrayClass, [commonElements.stringType]),
           _abstractValueDomain.dynamicType);
@@ -1884,9 +1936,77 @@
 
   @override
   HInstruction visitTypeEval(HTypeEval node) {
-    if (TypeRecipe.isIdentity(node.typeExpression, node.envStructure)) {
-      return node.inputs.single;
+    HInstruction environment = node.inputs.single;
+    if (_typeRecipeDomain.isIdentity(node.typeExpression, node.envStructure)) {
+      return environment;
     }
+
+    if (environment is HLoadType) {
+      TypeRecipe result = _typeRecipeDomain.foldLoadEval(
+          environment.typeExpression, node.envStructure, node.typeExpression);
+      if (result != null) return HLoadType(result, node.instructionType);
+      return node;
+    }
+
+    if (environment is HTypeBind) {
+      HInstruction bindings = environment.inputs.last;
+      if (bindings is HLoadType) {
+        //  env.bind(LoadType(T)).eval(...1...)  -->  env.eval(...T...)
+        TypeRecipeAndEnvironmentStructure result =
+            _typeRecipeDomain.foldBindLoadEval(bindings.typeExpression,
+                node.envStructure, node.typeExpression);
+        if (result != null) {
+          HInstruction previousEnvironment = environment.inputs.first;
+          return HTypeEval(previousEnvironment, result.environmentStructure,
+              result.recipe, node.instructionType);
+        }
+      }
+      // TODO(sra):  LoadType(T).bind(E).eval(...1...) --> E.eval(...0...)
+      return node;
+    }
+
+    if (environment is HTypeEval) {
+      TypeRecipeAndEnvironmentStructure result = _typeRecipeDomain.foldEvalEval(
+          environment.envStructure,
+          environment.typeExpression,
+          node.envStructure,
+          node.typeExpression);
+      if (result != null) {
+        HInstruction previousEnvironment = environment.inputs.first;
+        return HTypeEval(previousEnvironment, result.environmentStructure,
+            result.recipe, node.instructionType);
+      }
+      return node;
+    }
+
+    if (environment is HInstanceEnvironment) {
+      HInstruction instance = environment.inputs.single;
+      AbstractValue instanceAbstractValue = instance.instructionType;
+      ClassEntity instanceClass =
+          _abstractValueDomain.getExactClass(instanceAbstractValue);
+      if (instanceClass == null) {
+        // All the subclasses of JSArray are JSArray at runtime.
+        ClassEntity jsArrayClass = _closedWorld.commonElements.jsArrayClass;
+        if (_abstractValueDomain
+            .isInstanceOf(instanceAbstractValue, jsArrayClass)
+            .isDefinitelyTrue) {
+          instanceClass = jsArrayClass;
+        }
+      }
+      if (instanceClass != null) {
+        if (_typeRecipeDomain.isReconstruction(
+            instanceClass, node.envStructure, node.typeExpression)) {
+          return environment;
+        }
+      }
+    }
+
+    return node;
+  }
+
+  @override
+  HInstruction visitTypeBind(HTypeBind node) {
+    // TODO(sra):  env1.eval(X).bind(env1.eval(Y)) --> env1.eval(...X...Y...)
     return node;
   }
 
@@ -1897,7 +2017,8 @@
     // See if this check can be lowered to a simple one.
     HInstruction typeInput = node.typeInput;
     if (typeInput is HLoadType) {
-      DartType dartType = typeInput.typeExpression;
+      TypeExpressionRecipe recipe = typeInput.typeExpression;
+      DartType dartType = recipe.type;
       MemberEntity specializedCheck = SpecializedChecks.findAsCheck(
           dartType, node.isTypeError, _closedWorld.commonElements);
       if (specializedCheck != null) {
@@ -1906,6 +2027,9 @@
         return HAsCheckSimple(node.checkedInput, dartType, checkedType,
             node.isTypeError, specializedCheck, node.instructionType);
       }
+      if (dartType is DynamicType) {
+        return node.checkedInput;
+      }
     }
     return node;
   }
@@ -1957,7 +2081,13 @@
     if (instance is HCreate) {
       if (instance.hasRtiInput) {
         instance.instantiatedTypes?.forEach(_registry.registerInstantiation);
-        return instance.inputs.last;
+        return instance.rtiInput;
+      }
+      InterfaceType instanceType =
+          _closedWorld.elementEnvironment.getThisType(instance.element);
+      if (instanceType.typeArguments.length == 0) {
+        instance.instantiatedTypes?.forEach(_registry.registerInstantiation);
+        return HLoadType.type(instanceType, instance.instructionType);
       }
       return node;
     }
@@ -1966,7 +2096,7 @@
       ConstantValue constantValue = instance.constant;
       if (constantValue is ConstructedConstantValue) {
         _registry.registerInstantiation(constantValue.type);
-        return HLoadType(constantValue.type, instance.instructionType);
+        return HLoadType.type(constantValue.type, instance.instructionType);
       }
       return node;
     }
@@ -2081,6 +2211,7 @@
   Map<HInstruction, bool> trivialDeadStoreReceivers =
       new Maplet<HInstruction, bool>();
   bool eliminatedSideEffects = false;
+  bool newGvnCandidates = false;
 
   SsaDeadCodeEliminator(this.closedWorld, this.optimizer);
 
@@ -2321,6 +2452,9 @@
       while (!instruction.isControlFlow()) {
         HInstruction next = instruction.next;
         if (instruction is HTypeKnown && instruction.isPinned) break;
+        // It might be worth re-running GVN optimizations if we hoisted a
+        // GVN-able instructions from [target] into [block].
+        newGvnCandidates = newGvnCandidates || instruction.useGvn();
         instruction.block.detach(instruction);
         block.moveAtExit(instruction);
         instruction = next;
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index aac509a..0b77dbd 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -288,8 +288,9 @@
     argument = argument.unaliased;
 
     if (!argument.containsTypeVariables) {
-      HInstruction rti = HLoadType(argument, _abstractValueDomain.dynamicType)
-        ..sourceInformation = sourceInformation;
+      HInstruction rti =
+          HLoadType.type(argument, _abstractValueDomain.dynamicType)
+            ..sourceInformation = sourceInformation;
       builder.add(rti);
       return rti;
     }
diff --git a/pkg/compiler/testing.json b/pkg/compiler/testing.json
index 498a45c..dcac855 100644
--- a/pkg/compiler/testing.json
+++ b/pkg/compiler/testing.json
@@ -16,7 +16,8 @@
     "exclude": [
       "^tests/compiler/dart2js/.*/data/.*",
       "^tests/compiler/dart2js/.*/model_data/.*",
-      "^tests/compiler/dart2js/deferred_loading/libs/.*"
+      "^tests/compiler/dart2js/deferred_loading/libs/.*",
+      "^tests/compiler/dart2js/sourcemaps/stacktrace/extension_method.dart"
     ]
   }
 }
diff --git a/pkg/dart2native/bin/dart2aot.dart b/pkg/dart2native/bin/dart2aot.dart
deleted file mode 100644
index b406184..0000000
--- a/pkg/dart2native/bin/dart2aot.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env dart
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-import 'package:args/args.dart';
-import 'package:path/path.dart';
-
-const clearLine = '\r\x1b[2K';
-
-void aot(String sourceFile, String snapshotFile, bool enableAsserts,
-    bool buildElf, bool tfa, bool noTfa, String packages, List<String> ds) {
-  if (!FileSystemEntity.isFileSync(sourceFile)) {
-    print('Error: $sourceFile is not a file');
-    return;
-  }
-
-  String genSnapshotOption = buildElf
-      ? '--snapshot-kind=app-aot-assembly'
-      : '--snapshot-kind=app-aot-blobs';
-  String genSnapshotFilename = buildElf
-      ? '--assembly=$snapshotFile.S'
-      : '--blobs_container_filename=$snapshotFile';
-
-  String snapDir = dirname(Platform.script.path);
-  String binDir = canonicalize(join(snapDir, '..'));
-  String sdkDir = canonicalize(join(binDir, '..'));
-  String dartCommand = join(binDir, 'dart');
-  String snapshot = join(snapDir, 'gen_kernel.dart.snapshot');
-
-  stdout.write('${clearLine}Generating AOT snapshot');
-  List<String> dartArgs = <String>[
-    snapshot,
-    '--platform',
-    '${sdkDir}//lib/_internal/vm_platform_strong.dill',
-    '--aot',
-    '-Ddart.vm.product=true',
-    if (tfa) '--tfa',
-    if (noTfa) '--no-tfa',
-    ...ds,
-    if (packages != null) ...['--packages', packages],
-    '-o',
-    '$snapshotFile.dill',
-    sourceFile
-  ];
-
-  var cmdResult = Process.runSync(dartCommand, dartArgs);
-  if (cmdResult.exitCode != 0) {
-    print('\nGenerating AOT snapshot failed\n');
-    print(cmdResult.stdout);
-    print(cmdResult.stderr);
-    return;
-  }
-
-  stdout.write("${clearLine}Generating AOT .dill");
-  String genSnapshotCommand = join(binDir, 'utils', 'gen_snapshot');
-  List<String> genSnapshotArgs = [
-    genSnapshotOption,
-    genSnapshotFilename,
-    if (enableAsserts) '--enable-asserts',
-    '$snapshotFile.dill'
-  ];
-  cmdResult = Process.runSync(genSnapshotCommand, genSnapshotArgs);
-  if (cmdResult.exitCode != 0) {
-    print('\nGenerating AOT .dill failed\n');
-    print(cmdResult.stdout);
-    print(cmdResult.stderr);
-    return;
-  }
-  stdout.write("${clearLine}Done.\n");
-  stdout.flush();
-}
-
-void setupAOTArgs(ArgParser parser) {
-  parser.addFlag('build-elf');
-  parser.addFlag('enable-asserts');
-  parser.addFlag('tfa');
-  parser.addFlag('no-tfa');
-  parser.addOption('packages');
-}
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index ac9cf35..f15d5d2 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -3,68 +3,171 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
 import 'package:args/args.dart';
-import 'dart2aot.dart';
+import 'package:dart2native/dart2native.dart';
+import 'package:path/path.dart' as path;
 
-typedef void Command(ArgResults args, List<String> ds);
+final String executableSuffix = Platform.isWindows ? '.exe' : '';
+final String snapshotDir = path.dirname(Platform.script.toFilePath());
+final String binDir = path.canonicalize(path.join(snapshotDir, '..'));
+final String sdkDir = path.canonicalize(path.join(binDir, '..'));
+final String dart = path.join(binDir, 'dart${executableSuffix}');
+final String genKernel = path.join(snapshotDir, 'gen_kernel.dart.snapshot');
+final String dartaotruntime =
+    path.join(binDir, 'dartaotruntime${executableSuffix}');
+final String genSnapshot =
+    path.join(binDir, 'utils', 'gen_snapshot${executableSuffix}');
+final String platformDill =
+    path.join(sdkDir, 'lib', '_internal', 'vm_platform_strong.dill');
 
-void main(List<String> args) {
-  Map<String, Command> commands = <String, Command>{};
-  commands['aot'] = callAOT;
-
-  // Read -D args that the ArgParser can't handle.
-  List<String> ds = [];
-  args = filterDArgs(args, ds);
-
-  ArgParser parser = ArgParser();
-  parser.addFlag('help');
-  ArgParser aotParser = parser.addCommand('aot');
-  setupAOTArgs(aotParser);
-
-  ArgResults result = null;
+Future<void> generateNative(
+    Kind kind,
+    String sourceFile,
+    String outputFile,
+    String packages,
+    List<String> defines,
+    bool enableAsserts,
+    bool verbose) async {
+  final Directory tempDir = Directory.systemTemp.createTempSync();
   try {
-    result = parser.parse(args);
-  } catch (ArgParserException) {
-    // We handle this case as result == null below.
-  }
+    final String kernelFile = path.join(tempDir.path, 'kernel.dill');
+    final String snapshotFile = (kind == Kind.aot
+        ? outputFile
+        : path.join(tempDir.path, 'snapshot.aot'));
 
-  if (result == null || result.command == null || result['help']) {
-    print('dart2native <command> <args>\n');
-    print(' command: ');
-    print('   aot  - Compile script into one ahead of time dart snapshot');
-    return;
-  }
-
-  if (commands.containsKey(result.command.name)) {
-    commands[result.command.name](result.command, ds);
-    return;
-  }
-}
-
-void callAOT(ArgResults args, List<String> ds) {
-  List<String> rest = args.rest;
-  if (rest.length != 2) {
-    print(
-        'Usage: dart2native aot [options] <dart-source-file> <dart-aot-file>\n');
-    print(
-        'Dart AOT (ahead-of-time) compile Dart source code into native machine code.');
-    return;
-  }
-
-  aot(rest[0], rest[1], args['build-elf'], args['enable-asserts'], args['tfa'],
-      args['no-tfa'], args['packages'], ds);
-}
-
-List<String> filterDArgs(List<String> args, List<String> ds) {
-  List<String> result = <String>[];
-
-  args.forEach((String arg) {
-    if (!arg.startsWith('-D')) {
-      result.add(arg);
-    } else {
-      ds.add(arg);
+    if (verbose) {
+      print('Generating AOT kernel dill.');
     }
-  });
+    final kernelResult = await generateAotKernel(dart, genKernel, platformDill,
+        sourceFile, kernelFile, packages, defines);
+    if (kernelResult.exitCode != 0) {
+      stderr.writeln(kernelResult.stdout);
+      stderr.writeln(kernelResult.stderr);
+      await stderr.flush();
+      throw 'Generating AOT kernel dill failed!';
+    }
 
-  return result;
+    if (verbose) {
+      print('Generating AOT snapshot.');
+    }
+    final snapshotResult = await generateAotSnapshot(
+        genSnapshot, kernelFile, snapshotFile, enableAsserts);
+    if (snapshotResult.exitCode != 0) {
+      stderr.writeln(snapshotResult.stdout);
+      stderr.writeln(snapshotResult.stderr);
+      await stderr.flush();
+      throw 'Generating AOT snapshot failed!';
+    }
+
+    if (kind == Kind.exe) {
+      if (verbose) {
+        print('Generating executable.');
+      }
+      await writeAppendedExecutable(dartaotruntime, snapshotFile, outputFile);
+
+      if (Platform.isLinux || Platform.isMacOS) {
+        if (verbose) {
+          print('Marking binary executable.');
+        }
+        await markExecutable(outputFile);
+      }
+    }
+
+    print('Generated: ${outputFile}');
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+void printUsage(final ArgParser parser) {
+  print('''
+Usage: dart2native <main-dart-file> [<options>]
+
+Generates an executable or an AOT snapshot from <main-dart-file>.
+''');
+  print(parser.usage);
+}
+
+Future<void> main(List<String> args) async {
+  final ArgParser parser = ArgParser()
+    ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
+Set values of environment variables.
+To specify multiple variables, use multiple flags or use commas to separate pairs.
+Example:
+dart2native -Da=1,b=2 -Dc=3 --define=d=4 main.dart''')
+    ..addFlag('enable-asserts',
+        negatable: false, help: 'Enable assert statements.')
+    ..addFlag('help',
+        abbr: 'h', negatable: false, help: 'Displays this help message.')
+    ..addOption('output',
+        abbr: 'o', valueHelp: 'path', help: 'Put the output in file <path>.')
+    ..addOption('output-kind',
+        abbr: 'k',
+        allowed: ['exe', 'aot'],
+        defaultsTo: 'exe',
+        valueHelp: 'exe|aot',
+        help: 'Generate a standalone executable or an AOT snapshot.')
+    ..addOption('packages',
+        abbr: 'p', valueHelp: 'path', help: 'Use the .packages file at <path>.')
+    ..addFlag('verbose',
+        abbr: 'v', negatable: false, help: 'Show verbose output.');
+
+  ArgResults parsedArgs;
+  try {
+    parsedArgs = parser.parse(args);
+  } on FormatException catch (e) {
+    stderr.writeln('Error: ${e.message}');
+    await stderr.flush();
+    printUsage(parser);
+    exit(1);
+  }
+
+  if (parsedArgs['help']) {
+    printUsage(parser);
+    exit(0);
+  }
+
+  if (parsedArgs.rest.length != 1) {
+    printUsage(parser);
+    exit(1);
+  }
+
+  final Kind kind = {
+    'aot': Kind.aot,
+    'exe': Kind.exe,
+  }[parsedArgs['output-kind']];
+
+  final sourcePath = path.canonicalize(path.normalize(parsedArgs.rest[0]));
+  final outputPath =
+      path.canonicalize(path.normalize(parsedArgs['output'] != null
+          ? parsedArgs['output']
+          : {
+              Kind.aot: '${sourcePath}.aot',
+              Kind.exe: '${sourcePath}.exe',
+            }[kind]));
+
+  if (!FileSystemEntity.isFileSync(sourcePath)) {
+    stderr.writeln(
+        '"${sourcePath}" is not a file. See \'--help\' for more information.');
+    await stderr.flush();
+    exit(1);
+  }
+
+  try {
+    await generateNative(
+        kind,
+        sourcePath,
+        outputPath,
+        parsedArgs['packages'],
+        parsedArgs['define'],
+        parsedArgs['enable-asserts'],
+        parsedArgs['verbose']);
+  } catch (e) {
+    stderr.writeln('Failed to generate native files:');
+    stderr.writeln(e);
+    await stderr.flush();
+    exit(1);
+  }
 }
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
new file mode 100644
index 0000000..754fec9
--- /dev/null
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:path/path.dart' as path;
+
+const appSnapshotPageSize = 4096;
+const appjitMagicNumber = <int>[0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0];
+
+enum Kind { aot, exe }
+
+Future writeAppendedExecutable(
+    String dartaotruntimePath, String payloadPath, String outputPath) async {
+  final dartaotruntime = File(dartaotruntimePath);
+  final int dartaotruntimeLength = dartaotruntime.lengthSync();
+
+  final padding =
+      ((appSnapshotPageSize - dartaotruntimeLength) % appSnapshotPageSize);
+  final padBytes = Uint8List(padding);
+  final offset = dartaotruntimeLength + padding;
+
+  // Note: The offset is always Little Endian regardless of host.
+  final offsetBytes = new ByteData(8) // 64 bit in bytes.
+    ..setUint64(0, offset, Endian.little);
+
+  final outputFile = File(outputPath).openWrite();
+  outputFile.add(dartaotruntime.readAsBytesSync());
+  outputFile.add(padBytes);
+  outputFile.add(File(payloadPath).readAsBytesSync());
+  outputFile.add(offsetBytes.buffer.asUint8List());
+  outputFile.add(appjitMagicNumber);
+  await outputFile.close();
+}
+
+Future markExecutable(String outputFile) {
+  return Process.run('chmod', ['+x', outputFile]);
+}
+
+Future generateAotKernel(
+    String dart,
+    String genKernel,
+    String platformDill,
+    String sourceFile,
+    String kernelFile,
+    String packages,
+    List<String> defines) {
+  return Process.run(dart, [
+    genKernel,
+    '--platform',
+    platformDill,
+    '--aot',
+    '-Ddart.vm.product=true',
+    ...(defines.map((d) => '-D${d}')),
+    if (packages != null) ...['--packages', packages],
+    '-o',
+    kernelFile,
+    sourceFile
+  ]);
+}
+
+Future generateAotSnapshot(String genSnapshot, String kernelFile,
+    String snapshotFile, bool enableAsserts) {
+  return Process.run(genSnapshot, [
+    '--snapshot-kind=app-aot-blobs',
+    '--blobs_container_filename=${snapshotFile}',
+    if (enableAsserts) '--enable-asserts',
+    kernelFile
+  ]);
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index e521784..4fe742b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart' show Token, 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/error/error.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -198,8 +199,8 @@
       this.options, this._extensionTypes, this.errors)
       : rules = Dart2TypeSystem(types),
         declaredVariables = driver.declaredVariables,
-        _asyncStreamIterator =
-            driver.getClass('dart:async', 'StreamIterator').type,
+        _asyncStreamIterator = getLegacyRawClassType(
+            driver.getClass('dart:async', 'StreamIterator')),
         _coreIdentical = driver
             .getLibrary('dart:core')
             .publicNamespace
@@ -218,18 +219,18 @@
         internalSymbolClass = driver.getClass('dart:_internal', 'Symbol'),
         privateSymbolClass =
             driver.getClass('dart:_js_helper', 'PrivateSymbol'),
-        linkedHashMapImplType =
-            driver.getClass('dart:_js_helper', 'LinkedMap').type,
-        identityHashMapImplType =
-            driver.getClass('dart:_js_helper', 'IdentityMap').type,
-        linkedHashSetImplType =
-            driver.getClass('dart:collection', '_HashSet').type,
-        identityHashSetImplType =
-            driver.getClass('dart:collection', '_IdentityHashSet').type,
-        syncIterableType =
-            driver.getClass('dart:_js_helper', 'SyncIterable').type,
-        asyncStarImplType =
-            driver.getClass('dart:async', '_AsyncStarImpl').type,
+        linkedHashMapImplType = getLegacyRawClassType(
+            driver.getClass('dart:_js_helper', 'LinkedMap')),
+        identityHashMapImplType = getLegacyRawClassType(
+            driver.getClass('dart:_js_helper', 'IdentityMap')),
+        linkedHashSetImplType = getLegacyRawClassType(
+            driver.getClass('dart:collection', '_HashSet')),
+        identityHashSetImplType = getLegacyRawClassType(
+            driver.getClass('dart:collection', '_IdentityHashSet')),
+        syncIterableType = getLegacyRawClassType(
+            driver.getClass('dart:_js_helper', 'SyncIterable')),
+        asyncStarImplType = getLegacyRawClassType(
+            driver.getClass('dart:async', '_AsyncStarImpl')),
         dartJSLibrary = driver.getLibrary('dart:js') {
     jsTypeRep = JSTypeRep(rules, driver);
   }
@@ -244,10 +245,12 @@
   FunctionBody get currentFunction => _currentFunction;
 
   @override
-  InterfaceType get privateSymbolType => privateSymbolClass.type;
+  InterfaceType get privateSymbolType =>
+      getLegacyRawClassType(privateSymbolClass);
 
   @override
-  InterfaceType get internalSymbolType => internalSymbolClass.type;
+  InterfaceType get internalSymbolType =>
+      getLegacyRawClassType(internalSymbolClass);
 
   CompilationUnitElement get _currentCompilationUnit {
     for (var e = _currentElement;; e = e.enclosingElement) {
@@ -1004,7 +1007,8 @@
     }
     if (classElem.library.isDartAsync) {
       if (classElem == types.futureOrElement) {
-        var typeParamT = classElem.typeParameters[0].type;
+        var typeParamT =
+            getLegacyTypeParameterType(classElem.typeParameters[0]);
         var typeT = _emitType(typeParamT);
         var futureOfT = _emitType(types.futureType2(typeParamT));
         body.add(js.statement('''
@@ -1249,7 +1253,7 @@
     }
 
     getBaseClass(int count) {
-      var base = emitDeferredType(classElem.type);
+      var base = emitDeferredType(getLegacyRawClassType(classElem));
       while (--count >= 0) {
         base = js.call('#.__proto__', [base]);
       }
@@ -1416,7 +1420,7 @@
 
   List<js_ast.Method> _emitClassMethods(
       ClassElement classElem, List<ClassMember> memberNodes) {
-    var type = classElem.type;
+    var type = getLegacyRawClassType(classElem);
     var virtualFields = _classProperties.virtualFields;
 
     var jsMethods = <js_ast.Method>[];
@@ -1838,7 +1842,7 @@
   void _registerExtensionType(
       ClassElement classElem, String jsPeerName, List<js_ast.Statement> body) {
     var className = _emitTopLevelName(classElem);
-    if (jsTypeRep.isPrimitive(classElem.type)) {
+    if (jsTypeRep.isPrimitive(getLegacyRawClassType(classElem))) {
       body.add(runtimeStatement(
           'definePrimitiveHashCode(#.prototype)', [className]));
     }
@@ -1954,7 +1958,7 @@
       Map<Element, Declaration> members, List<js_ast.Statement> body) {
     if (classElem.isEnum) {
       // Emit enum static fields
-      var type = classElem.type;
+      var type = getLegacyRawClassType(classElem);
       void addField(FieldElement e, js_ast.Expression value) {
         body.add(defineValueOnClass(classElem, _emitStaticClassName(e),
                 _declareMemberName(e.getter), value)
@@ -2004,7 +2008,7 @@
 
   /// Ensure `dartx.` symbols we will use are present.
   void _initExtensionSymbols(ClassElement classElem) {
-    if (_extensionTypes.hasNativeSubtype(classElem.type) ||
+    if (_extensionTypes.hasNativeSubtype(getLegacyRawClassType(classElem)) ||
         classElem.isDartCoreObject) {
       for (var members in [classElem.methods, classElem.accessors]) {
         for (var m in members) {
@@ -2083,8 +2087,8 @@
 
         var name = method.name;
         var reifiedType = _getMemberRuntimeType(method);
-        var memberOverride =
-            classElem.type.lookUpMethodInSuperclass(name, currentLibrary);
+        var memberOverride = getLegacyRawClassType(classElem)
+            .lookUpMethodInSuperclass(name, currentLibrary);
         // Don't add redundant signatures for inherited methods whose signature
         // did not change.  If we are not overriding, or if the thing we are
         // overriding has a different reified type from ourselves, we must
@@ -2140,8 +2144,10 @@
         var name = accessor.name;
         var isGetter = accessor.isGetter;
         var memberOverride = isGetter
-            ? classElem.type.lookUpGetterInSuperclass(name, currentLibrary)
-            : classElem.type.lookUpSetterInSuperclass(name, currentLibrary);
+            ? getLegacyRawClassType(classElem)
+                .lookUpGetterInSuperclass(name, currentLibrary)
+            : getLegacyRawClassType(classElem)
+                .lookUpSetterInSuperclass(name, currentLibrary);
 
         var reifiedType = accessor.type;
         // Don't add redundant signatures for inherited methods whose signature
@@ -2258,7 +2264,7 @@
     var parameters = element.parameters
         .map((p) => ParameterElementImpl.synthetic(
             p.name,
-            _isCovariant(p) ? objectClass.type : p.type,
+            _isCovariant(p) ? getLegacyRawClassType(objectClass) : p.type,
             // ignore: deprecated_member_use
             p.parameterKind))
         .toList();
@@ -2861,8 +2867,11 @@
     for (var t in typeFormals) {
       t = covariantParams.lookup(t) as TypeParameterElement;
       if (t != null) {
-        body.add(runtimeStatement('checkTypeBound(#, #, #)',
-            [_emitType(t.type), _emitType(t.bound), propertyName(t.name)]));
+        body.add(runtimeStatement('checkTypeBound(#, #, #)', [
+          _emitType(getLegacyTypeParameterType(t)),
+          _emitType(t.bound),
+          propertyName(t.name)
+        ]));
       }
     }
   }
@@ -3096,7 +3105,7 @@
       ClassMemberElement element, Element accessor, Expression node) {
     bool isStatic = element.isStatic;
     var classElem = element.enclosingElement as ClassElement;
-    var type = classElem.type;
+    var type = getLegacyRawClassType(classElem);
     var member = _emitMemberName(element.name,
         isStatic: isStatic, type: type, element: accessor);
 
@@ -3259,7 +3268,8 @@
       // If any explicit bounds were passed, emit them.
       if (typeFormals.any((t) => t.bound != null)) {
         var bounds = typeFormals
-            .map((t) => _emitType(t.type.bound, cacheType: cacheType))
+            .map((t) => _emitType(getLegacyTypeParameterType(t).bound,
+                cacheType: cacheType))
             .toList();
         typeParts.add(addTypeFormalsAsParameters(bounds));
       }
@@ -3586,7 +3596,9 @@
     var classElem = field.enclosingElement as ClassElement;
     var isStatic = field.isStatic;
     var member = _emitMemberName(field.name,
-        isStatic: isStatic, type: classElem.type, element: field.setter);
+        isStatic: isStatic,
+        type: getLegacyRawClassType(classElem),
+        element: field.setter);
     jsTarget = isStatic
         ? (js_ast.PropertyAccess(_emitStaticClassName(field), member)
           ..sourceInformation = _nodeSpan(id))
@@ -3653,7 +3665,7 @@
       if (e.name == 'getGenericClass' && firstArg is SimpleIdentifier) {
         var typeElem = firstArg.staticElement;
         if (typeElem is TypeDefiningElement &&
-            typeElem.type is ParameterizedType) {
+            getLegacyElementType(typeElem) is ParameterizedType) {
           return _emitTopLevelNameNoInterop(typeElem, suffix: '\$');
         }
       }
@@ -3686,7 +3698,8 @@
       Expression target, Element member, bool isStatic) {
     if (isStatic) {
       if (member is ConstructorElement) {
-        return emitConstructorAccess(member.enclosingElement.type)
+        return emitConstructorAccess(
+            getLegacyRawClassType(member.enclosingElement))
           ..sourceInformation = _nodeSpan(target);
       }
       if (member is PropertyAccessorElement) {
@@ -4533,8 +4546,11 @@
       if (typeNode is NamedType && typeNode.typeArguments != null) {
         var e = typeNode.name.staticElement;
         if (e is ClassElement) {
-          return e.type.instantiate(
-              typeNode.typeArguments.arguments.map(getType).toList());
+          return e.instantiate(
+            typeArguments:
+                typeNode.typeArguments.arguments.map(getType).toList(),
+            nullabilitySuffix: NullabilitySuffix.star,
+          );
         } else if (e is FunctionTypedElement) {
           return e.type.instantiate(
               typeNode.typeArguments.arguments.map(getType).toList());
@@ -5652,7 +5668,9 @@
     // This applies regardless in an int or double context.
     var valueInJS = BigInt.from(value.toDouble());
     if (value != valueInJS) {
-      assert(node.staticType == intClass.type || options.unsafeForceCompile,
+      assert(
+          node.staticType == getLegacyRawClassType(intClass) ||
+              options.unsafeForceCompile,
           'int literals in double contexts should be checked by Analyzer.');
 
       var lexeme = node.literal.lexeme;
@@ -5721,7 +5739,7 @@
     if (itemType.isDynamic) return list;
 
     // Call `new JSArray<E>.of(list)`
-    var arrayType = _jsArray.type.instantiate([itemType]);
+    var arrayType = getLegacyRawClassType(_jsArray).instantiate([itemType]);
     return js.call('#.of(#)', [_emitType(arrayType), list]);
   }
 
@@ -5878,7 +5896,8 @@
       if (_isUiAsCodeElement(node)) {
         // Create a temporary variable to build a new collection from.
         var previousCollectionVariable = _currentCollectionVariable;
-        var arrayType = _jsArray.type.instantiate([elementType]);
+        var arrayType =
+            getLegacyRawClassType(_jsArray).instantiate([elementType]);
         var temporaryIdentifier = _createTemporary('items', arrayType);
         _currentCollectionVariable = _emitSimpleIdentifier(temporaryIdentifier);
         var items = js.statement('let # = #',
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index a306bfb..5723e17 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -6,6 +6,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'
     show DartType, InterfaceType, FunctionType;
 import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,8 @@
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
 
+import 'type_utilities.dart';
+
 class Tuple2<T0, T1> {
   final T0 e0;
   final T1 e1;
@@ -29,9 +32,12 @@
 /// [instantiateElementTypeToBounds] should be used instead.
 InterfaceType fillDynamicTypeArgsForClass(InterfaceType t) {
   if (t.typeArguments.isNotEmpty) {
-    var rawT = t.element.type;
-    var dyn = List.filled(rawT.typeArguments.length, DynamicTypeImpl.instance);
-    return rawT.substitute2(dyn, rawT.typeArguments);
+    var dyn =
+        List.filled(t.element.typeParameters.length, DynamicTypeImpl.instance);
+    return t.element.instantiate(
+      typeArguments: dyn,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
   }
   return t;
 }
@@ -63,14 +69,14 @@
     } else if (e is FunctionTypedElement) {
       type = e.type;
     } else if (e is ClassElement) {
-      type = e.type;
+      type = getLegacyRawClassType(e);
     }
     var bounds = rules.instantiateTypeFormalsToBounds(e.typeParameters);
     if (bounds == null) return type;
     return type.substitute2(
         bounds, TypeParameterTypeImpl.getTypes(e.typeParameters));
   }
-  return element.type;
+  return getLegacyElementType(element);
 }
 
 /// Given an [element] and a [test] function, returns the first matching
@@ -253,7 +259,8 @@
   // * `dynamic d; d();` without a declared `call` method is handled by dcall.
   // * for `class C implements Callable { noSuchMethod(i) { ... } }` we find
   //   the `call` method on the `Callable` interface.
-  var callMethod = c.type.lookUpInheritedGetterOrMethod('call');
+  var callMethod =
+      getLegacyRawClassType(c).lookUpInheritedGetterOrMethod('call');
   return callMethod is PropertyAccessorElement
       ? callMethod.returnType is FunctionType
       : callMethod != null;
diff --git a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
index 833a968..0175913 100644
--- a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
@@ -10,7 +10,9 @@
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
+
 import 'element_helpers.dart' show getAnnotationName, isBuiltinAnnotation;
+import 'type_utilities.dart';
 
 /// Contains information about native JS types (those types provided by the
 /// implementation) that are also provided by the Dart SDK.
@@ -79,7 +81,7 @@
 
   void _visitClass(ClassElement element) {
     if (_isNative(element)) {
-      _addExtensionType(element.type, true);
+      _addExtensionType(getLegacyRawClassType(element), true);
     }
   }
 
@@ -114,7 +116,7 @@
   void _addExtensionTypesForLibrary(String libraryUri, List<String> typeNames) {
     var library = _getLibraryByUri(libraryUri);
     for (var typeName in typeNames) {
-      _addExtensionType(library.getType(typeName).type);
+      _addExtensionType(getLegacyRawClassType(library.getType(typeName)));
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index 851d47b..c24e5f5 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -2,12 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/element.dart' show ClassElement;
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
+
 import '../compiler/js_typerep.dart';
 import 'driver.dart';
+import 'type_utilities.dart';
 
 class JSTypeRep extends SharedJSTypeRep<DartType> {
   final Dart2TypeSystem rules;
@@ -54,9 +56,9 @@
   InterfaceType getImplementationType(DartType t) {
     var rep = typeFor(t);
     // Number, String, and Bool are final
-    if (rep == JSType.jsNumber) return _jsNumber.type;
-    if (rep == JSType.jsBoolean) return _jsBool.type;
-    if (rep == JSType.jsString) return _jsString.type;
+    if (rep == JSType.jsNumber) return getLegacyRawClassType(_jsNumber);
+    if (rep == JSType.jsBoolean) return getLegacyRawClassType(_jsBool);
+    if (rep == JSType.jsString) return getLegacyRawClassType(_jsString);
     return null;
   }
 }
diff --git a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
index 4aa976d..40f5f7c 100644
--- a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
@@ -14,6 +14,7 @@
 import 'js_interop.dart' show isNotNullAnnotation, isNullCheckAnnotation;
 import 'js_typerep.dart';
 import 'property_model.dart';
+import 'type_utilities.dart';
 
 /// An inference engine for nullable types.
 ///
@@ -86,7 +87,7 @@
     if (e is MethodElement) {
       Element container = e.enclosingElement;
       if (container is ClassElement) {
-        DartType targetType = container.type;
+        DartType targetType = getLegacyRawClassType(container);
         InterfaceType implType = jsTypeRep.getImplementationType(targetType);
         if (implType != null) {
           MethodElement method = implType.lookUpMethod(e.name, coreLibrary);
@@ -110,7 +111,7 @@
     // type.
     Element container = element.enclosingElement;
     if (container is ClassElement) {
-      var targetType = container.type;
+      var targetType = getLegacyRawClassType(container);
       var implType = jsTypeRep.getImplementationType(targetType);
       if (implType != null) {
         var getter = implType.lookUpGetter(name, coreLibrary);
diff --git a/pkg/dev_compiler/lib/src/analyzer/property_model.dart b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
index 227afa7..74d3484 100644
--- a/pkg/dev_compiler/lib/src/analyzer/property_model.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
@@ -11,6 +11,7 @@
 import '../compiler/js_names.dart' as js_ast;
 import 'element_helpers.dart';
 import 'extension_types.dart';
+import 'type_utilities.dart';
 
 /// Dart allows all fields to be overridden.
 ///
@@ -220,7 +221,7 @@
       }
     }
 
-    _collectMockMembers(classElem.type);
+    _collectMockMembers(getLegacyRawClassType(classElem));
     _collectExtensionMembers(classElem);
 
     var virtualAccessorNames = HashSet<String>()
@@ -311,12 +312,13 @@
     // this class. This will help us identify which parameters need checks
     // for soundness.
     var allNatives = HashSet<String>();
-    _collectNativeMembers(element.type, allNatives);
+    _collectNativeMembers(getLegacyRawClassType(element), allNatives);
     if (allNatives.isEmpty) return;
 
     // For members on this class, check them against all generic interfaces.
     var seenConcreteMembers = HashSet<String>();
-    _findExtensionMembers(element.type, seenConcreteMembers, allNatives);
+    _findExtensionMembers(
+        getLegacyRawClassType(element), seenConcreteMembers, allNatives);
     // Add mock members. These are compiler-generated concrete members that
     // forward to `noSuchMethod`.
     for (var m in mockMembers.values) {
diff --git a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
index 789197d..3b24cf0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
@@ -5,14 +5,50 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
+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' show TypeParameterMember;
 
 import '../analyzer/element_helpers.dart';
 import '../compiler/js_names.dart' as js_ast;
 import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 
+/// Return the [InterfaceType] that itself has the legacy nullability, and for
+/// every type parameter a [TypeParameterType] instance with the legacy
+/// nullability is used as the corresponding type argument.
+InterfaceType getLegacyRawClassType(ClassElement element) {
+  var typeParameters = element.typeParameters;
+  var typeArguments = typeParameters.map(getLegacyTypeParameterType).toList();
+  return element.instantiate(
+    typeArguments: typeArguments,
+    nullabilitySuffix: NullabilitySuffix.star,
+  );
+}
+
+/// Return the [TypeParameterType] with the legacy nullability for the given
+/// type parameter [element].
+TypeParameterType getLegacyTypeParameterType(TypeParameterElement element) {
+  return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
+}
+
+/// Return the raw type (i.e. the type where type parameters are replaced with
+/// the corresponding [TypeParameterType]) for the given [element]. The type
+/// returned, and every [TypeParameterType] instance will have the legacy
+/// nullability suffix.
+DartType getLegacyElementType(TypeDefiningElement element) {
+  if (element is ClassElement) {
+    return getLegacyRawClassType(element);
+  } else if (element is DynamicElementImpl) {
+    return element.type;
+  } else if (element is TypeParameterElement) {
+    return getLegacyTypeParameterType(element);
+  } else {
+    throw StateError('Unsupported element: (${element.runtimeType}) $element');
+  }
+}
+
 Set<TypeParameterElement> freeTypeParameters(DartType t) {
   var result = Set<TypeParameterElement>();
   void find(DartType t) {
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 01d77e4..645dd90 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -263,7 +263,8 @@
     return privateNames.putIfAbsent(name, initPrivateNameSymbol);
   }
 
-  /// Emits a private name JS Symbol for [name] unique to a Dart class [cls].
+  /// Emits a private name JS Symbol for [memberName] unique to a Dart
+  /// class [className].
   ///
   /// This is now required for fields of constant objects that may be
   /// overridden within the same library.
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 4f1d80b..7b9408a 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -2,8 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:core' hide MapEntry;
 import 'dart:collection';
+import 'dart:core' hide MapEntry;
+
 import 'package:analyzer/dart/element/element.dart' as a;
 import 'package:analyzer/dart/element/type.dart' as a;
 import 'package:analyzer/file_system/physical_file_system.dart' as a;
@@ -13,18 +14,19 @@
 import 'package:analyzer/src/dart/element/type.dart' as a;
 import 'package:analyzer/src/generated/constant.dart' as a;
 import 'package:analyzer/src/generated/engine.dart' as a;
+import 'package:analyzer/src/generated/resolver.dart' as a
+    show NamespaceBuilder, TypeProvider;
 import 'package:analyzer/src/generated/source.dart' as a;
 import 'package:analyzer/src/generated/type_system.dart' as a;
 import 'package:analyzer/src/summary/idl.dart' as a;
 import 'package:analyzer/src/summary/package_bundle_reader.dart' as a;
 import 'package:analyzer/src/summary/summary_sdk.dart' as a;
-import 'package:analyzer/src/generated/resolver.dart' as a
-    show NamespaceBuilder, TypeProvider;
 import 'package:front_end/src/api_unstable/ddc.dart'
     show RedirectingFactoryBody;
 import 'package:kernel/kernel.dart';
 import 'package:kernel/type_algebra.dart';
 
+import '../analyzer/type_utilities.dart' hide freeTypeParameters;
 import 'type_table.dart';
 
 /// Converts an Analyzer summary file to a Kernel [Component].
@@ -471,7 +473,8 @@
       if (typeParams.isNotEmpty) {
         // Skip past the type formals, we'll add them back below, so these
         // type parameter names will end up in scope in the generated JS.
-        type = type.instantiate(typeParams.map((f) => f.type).toList());
+        type = type.instantiate(
+            typeParams.map((f) => getLegacyTypeParameterType(f)).toList());
       }
     }
     t.typeParameters.addAll(typeParams.map(visitTypeParameterElement));
@@ -732,7 +735,8 @@
   }
 
   bool _isGenericCovariant(a.ClassElement c, a.DartType type) {
-    var classUpperBound = rules.instantiateToBounds(c.type) as a.InterfaceType;
+    var classUpperBound =
+        rules.instantiateToBounds(getLegacyRawClassType(c)) as a.InterfaceType;
     var typeUpperBound = type.substitute2(classUpperBound.typeArguments,
         a.TypeParameterTypeImpl.getTypes(classUpperBound.typeParameters));
     // Is it safe to assign the upper bound of the field/parameter to it?
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 396b0ae..2539d4a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1194,7 +1194,6 @@
       js_ast.Expression className, List<js_ast.Statement> body) {
     void emitExtensions(String helperName, Iterable<String> extensions) {
       if (extensions.isEmpty) return;
-
       var names = extensions
           .map((e) => propertyName(js_ast.memberNameForDartMember(e)))
           .toList();
@@ -2267,8 +2266,7 @@
     }
 
     useExtension ??= _isSymbolizedMember(memberClass, name);
-    name = js_ast.memberNameForDartMember(
-        name, member is Procedure && member.isExternal);
+    name = js_ast.memberNameForDartMember(name, _isExternal(member));
     if (useExtension) {
       return getExtensionSymbolInternal(name);
     }
@@ -2292,7 +2290,7 @@
 
       // Fields on a native class are implicitly native.
       // Methods/getters/setters are marked external/native.
-      if (member is Field || member is Procedure && member.isExternal) {
+      if (member is Field || _isExternal(member)) {
         var jsName = _annotationName(member, isJSName);
         return jsName != null && jsName != name;
       } else {
@@ -2384,6 +2382,46 @@
     return propertyName(name + suffix);
   }
 
+  bool _isExternal(Member m) {
+    // Corresponds to the names in memberNameForDartMember in
+    // compiler/js_names.dart.
+    const renamedJsMembers = ["prototype", "constructor"];
+    if (m is Procedure) {
+      if (m.isExternal) return true;
+      if (m.isNoSuchMethodForwarder) {
+        if (renamedJsMembers.contains(m.name.name)) {
+          return _hasExternalProcedure(m.enclosingClass, m.name.name);
+        }
+      }
+    }
+    return false;
+  }
+
+  /// Returns true if anything up the class hierarchy externally defines a
+  /// procedure with name = [name].
+  ///
+  /// Used to determine when we should alias Dart-JS reserved members
+  /// (e.g., 'prototype' and 'constructor').
+  bool _hasExternalProcedure(Class c, String name) {
+    var classes = Queue<Class>()..add(c);
+
+    while (classes.isNotEmpty) {
+      var c = classes.removeFirst();
+      var classesToCheck = [
+        if (c.supertype != null) c.supertype.classNode,
+        for (var t in c.implementedTypes) if (t.classNode != null) t.classNode,
+      ];
+      classes.addAll(classesToCheck);
+      for (var procedure in c.procedures) {
+        if (procedure.name.name == name && !procedure.isNoSuchMethodForwarder) {
+          return procedure.isExternal;
+        }
+      }
+    }
+
+    return false;
+  }
+
   String _getJSNameWithoutGlobal(NamedNode n) {
     if (!usesJSInterop(n)) return null;
     var libraryJSName = _annotationName(getLibrary(n), isPublicJSAnnotation);
@@ -2651,7 +2689,8 @@
       /// Kernel represents `<T>` as `<T extends Object = dynamic>`. We can find
       /// explicit bounds by looking for anything *except* that.
       typeParameterHasExplicitBound(TypeParameter t) =>
-          t.bound != _types.objectType || t.defaultType != const DynamicType();
+          t.bound != _types.coreTypes.objectLegacyRawType ||
+          t.defaultType != const DynamicType();
 
       // If any explicit bounds were passed, emit them.
       if (typeFormals.any(typeParameterHasExplicitBound)) {
@@ -3147,7 +3186,7 @@
     }
 
     if (node is AsExpression && node.isTypeError) {
-      assert(node.getStaticType(_types) == _types.boolType);
+      assert(node.getStaticType(_types) == _types.coreTypes.boolLegacyRawType);
       return runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
     }
 
@@ -4317,7 +4356,7 @@
       var rightType = right.getStaticType(_types);
 
       if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
-          leftType == _types.stringType && op == '+') {
+          leftType == _types.coreTypes.stringLegacyRawType && op == '+') {
         // Inline operations on primitive types where possible.
         // TODO(jmesserly): inline these from dart:core instead of hardcoding
         // the implementation details here.
@@ -4629,7 +4668,7 @@
       // A static native element should just forward directly to the JS type's
       // member, for example `Css.supports(...)` in dart:html should be replaced
       // by a direct call to the DOM API: `global.CSS.supports`.
-      if (target is Procedure && target.isStatic && target.isExternal) {
+      if (_isExternal(target) && (target as Procedure).isStatic) {
         var nativeName = _extensionTypes.getNativePeers(c);
         if (nativeName.isNotEmpty) {
           var memberName = _annotationName(target, isJSName) ??
@@ -4894,6 +4933,11 @@
   }
 
   @override
+  js_ast.Expression visitNullCheck(NullCheck node) {
+    throw UnimplementedError('Unimplemented null check expression: $node');
+  }
+
+  @override
   js_ast.Expression visitLogicalExpression(LogicalExpression node) {
     // The operands of logical boolean operators are subject to boolean
     // conversion.
@@ -4918,9 +4962,11 @@
       if (jsExpr is js_ast.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
         continue;
       }
-      parts.add(e.getStaticType(_types) == _types.stringType && !isNullable(e)
-          ? jsExpr
-          : runtimeCall('str(#)', [jsExpr]));
+      parts.add(
+          e.getStaticType(_types) == _types.coreTypes.stringLegacyRawType &&
+                  !isNullable(e)
+              ? jsExpr
+              : runtimeCall('str(#)', [jsExpr]));
     }
     if (parts.isEmpty) return js.string('');
     return js_ast.Expression.binary(parts, '+');
@@ -4966,7 +5012,7 @@
     var lhs = _visitExpression(operand);
     var typeofName = _typeRep.typeFor(type).primitiveTypeOf;
     // Inline primitives other than int (which requires a Math.floor check).
-    if (typeofName != null && type != _types.intType) {
+    if (typeofName != null && type != _types.coreTypes.intLegacyRawType) {
       return js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
     } else {
       return js.call('#.is(#)', [_emitType(type), lhs]);
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index f1ced92..fe3e379 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -147,11 +147,6 @@
       // Enums are not extensible.
       return false;
     }
-    var libraryUri = class_.enclosingLibrary.importUri;
-    if (libraryUri.scheme == 'dart' && libraryUri.path.startsWith('_')) {
-      // There should be no extensible fields in private SDK libraries.
-      return false;
-    }
 
     if (!field.name.isPrivate) {
       // Public fields in public classes (or extensible private classes)
diff --git a/pkg/dev_compiler/test/modular_ddc_suite.dart b/pkg/dev_compiler/test/modular_ddc_suite.dart
index 3d75a07..f537492 100644
--- a/pkg/dev_compiler/test/modular_ddc_suite.dart
+++ b/pkg/dev_compiler/test/modular_ddc_suite.dart
@@ -19,6 +19,7 @@
 String _test_package = 'ddc_modular_test';
 
 Uri sdkRoot = Platform.script.resolve("../../../");
+bool _nnbd = false;
 Options _options;
 String _dartdevcScript;
 String _buildSdkScript;
@@ -68,8 +69,8 @@
 
     ProcessResult result;
 
-    bool nnbd = flags.contains('non-nullable');
-    bool allowErrors = nnbd && _nnbdOptOut.contains(module.name);
+    _nnbd = flags.contains('non-nullable');
+    bool allowErrors = _nnbd && _nnbdOptOut.contains(module.name);
 
     if (module.isSdk) {
       assert(transitiveDependencies.isEmpty);
@@ -82,7 +83,7 @@
             sdkRoot.toFilePath(),
             _sdkDevRuntime,
             'patched_sdk',
-            if (nnbd) 'sdk_nnbd'
+            if (_nnbd) 'sdk_nnbd'
           ],
           root.toFilePath());
       _checkExitCode(result, this, module);
@@ -309,5 +310,8 @@
       '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');
+  _sdkDevRuntime = await resolve(_nnbd
+      ? 'sdk_nnbd'
+      : 'sdk'
+          '/lib/_internal/js_dev_runtime');
 }
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 2a73fd9..9b07711 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -62,7 +62,13 @@
     ..addOption('mode',
         help: 'Option to (compile|run|all).  Default is all (compile and run).',
         allowed: ['compile', 'run', 'all'],
-        defaultsTo: 'all');
+        defaultsTo: 'all')
+    ..addOption('compile-vm-options',
+        help: 'DART_VM_OPTIONS for the compilation VM.')
+    ..addOption('packages',
+        help: 'Where to find a package spec file.')
+    ..addOption('out',
+        help: 'Output file.');
 
   var options = parser.parse(args);
   if (options['help'] as bool) {
@@ -90,6 +96,7 @@
   var run = mode == 'run' || mode == 'all';
 
   var entry = p.canonicalize(options.rest.first);
+  var out = (options['out'] as String) ?? p.setExtension(entry, '.js');
   var libRoot = p.dirname(entry);
   var basename = p.basenameWithoutExtension(entry);
   var libname = kernel
@@ -135,8 +142,12 @@
       // Use built snapshot.
       command = p.join(dartSdk, 'bin', command);
     }
-    var process =
-        await Process.start(command, args, mode: ProcessStartMode.inheritStdio);
+    var process = await Process.start(command, args,
+        mode: ProcessStartMode.inheritStdio,
+        environment: <String, String>{
+          if (options['compile-vm-options'] != null)
+            'DART_VM_OPTIONS': options['compile-vm-options']
+        });
     if (await process.exitCode != 0) exit(await process.exitCode);
   }
 
@@ -185,8 +196,9 @@
         '--library-root=$libRoot',
       for (var summary in summaries) '--summary=$summary',
       for (var experiment in experiments) '--enable-experiment=$experiment',
+      if (options['packages'] != null) '--packages=${options['packages']}',
       '-o',
-      p.setExtension(entry, '.js'),
+      out,
       entry
     ];
 
@@ -226,7 +238,7 @@
   });
 </script>
 ''';
-      var htmlFile = p.setExtension(entry, '.html');
+      var htmlFile = p.setExtension(out, '.html');
       File(htmlFile).writeAsStringSync(html);
       var tmp = p.join(Directory.systemTemp.path, 'ddc');
 
@@ -262,7 +274,7 @@
   process.exit(1);
 }
 ''';
-      var nodeFile = p.setExtension(entry, '.run.js');
+      var nodeFile = p.setExtension(out, '.run.js');
       File(nodeFile).writeAsStringSync(runjs);
       var nodeBinary = binary ?? 'node';
       var process = await Process.start(
@@ -274,7 +286,7 @@
       // Fix SDK import.  `d8` doesn't let us set paths, so we need a full path
       // to the SDK.
 
-      var jsFile = File(p.setExtension(entry, '.js'));
+      var jsFile = File(out);
       var jsContents = jsFile.readAsStringSync();
       jsContents = jsContents.replaceFirst(
           "from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
@@ -291,7 +303,7 @@
   console.error(e);
 }
 ''';
-      var d8File = p.setExtension(entry, '.d8.js');
+      var d8File = p.setExtension(out, '.d8.js');
       File(d8File).writeAsStringSync(runjs);
       var d8Binary = binary ?? p.join(dartCheckoutPath, _d8executable);
       var process = await Process.start(d8Binary, ['--module', d8File],
diff --git a/pkg/dev_compiler/web/source_map_stack_trace.dart b/pkg/dev_compiler/web/source_map_stack_trace.dart
index 9dce84a..57a4016 100644
--- a/pkg/dev_compiler/web/source_map_stack_trace.dart
+++ b/pkg/dev_compiler/web/source_map_stack_trace.dart
@@ -58,7 +58,7 @@
 
     if (!sourceUrl.startsWith('dart:') &&
         !sourceUrl.startsWith('package:') &&
-        sourceUrl.contains('dart_sdk.js')) {
+        sourceUrl.contains('dart_sdk')) {
       // This compresses the long dart_sdk URLs if SDK source maps are missing.
       // It's no longer linkable, but neither are the properly mapped ones
       // above.
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 68939cd..6c6b5a4 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -77,6 +77,9 @@
   WorkerInputComponent cachedSdkInput;
   Map<Uri, WorkerInputComponent> workerInputCache =
       oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
+  Map<Uri, Uri> workerInputCacheLibs =
+      oldState?.workerInputCacheLibs ?? new Map<Uri, Uri>();
+
   bool startOver = false;
   Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
       parseExperimentalArguments(experiments),
@@ -92,6 +95,7 @@
 
     // We'll load a new sdk, anything loaded already will have a wrong root.
     workerInputCache.clear();
+    workerInputCacheLibs.clear();
   } else {
     // We do have a previous state.
     cachedSdkInput = workerInputCache[sdkSummary];
@@ -101,6 +105,7 @@
       startOver = true;
       // We'll load a new sdk, anything loaded already will have a wrong root.
       workerInputCache.clear();
+      workerInputCacheLibs.clear();
     }
   }
 
@@ -120,6 +125,12 @@
     cachedSdkInput = new WorkerInputComponent(
         sdkDigest, await processedOpts.loadSdkSummary(null));
     workerInputCache[sdkSummary] = cachedSdkInput;
+    for (Library lib in cachedSdkInput.component.libraries) {
+      if (workerInputCacheLibs.containsKey(lib.importUri)) {
+        throw new StateError("Duplicate sources in sdk.");
+      }
+      workerInputCacheLibs[lib.importUri] = sdkSummary;
+    }
 
     incrementalCompiler = new IncrementalCompiler.fromComponent(
         new CompilerContext(processedOpts),
@@ -166,7 +177,9 @@
     libraryToInputDill = new Map<Uri, Uri>();
   }
   List<Uri> loadFromDill = new List<Uri>();
+  Set<Uri> inputSummariesSet = new Set<Uri>();
   for (Uri summary in summaryInputs) {
+    inputSummariesSet.add(summary);
     WorkerInputComponent cachedInput = workerInputCache[summary];
     List<int> summaryDigest = workerInputDigests[summary];
     if (summaryDigest == null) {
@@ -175,6 +188,14 @@
     if (cachedInput == null ||
         cachedInput.component.root != nameRoot ||
         !digestsEqual(cachedInput.digest, summaryDigest)) {
+      // Remove any old libraries from workerInputCacheLibs.
+      Component component = cachedInput?.component;
+      if (component != null) {
+        for (Library lib in component.libraries) {
+          workerInputCacheLibs.remove(lib.importUri);
+        }
+      }
+
       loadFromDill.add(summary);
     } else {
       // Need to reset cached components so they are usable again.
@@ -202,8 +223,24 @@
             alwaysCreateNewNamedNodes: true));
     workerInputCache[summary] = cachedInput;
     inputSummaries.add(cachedInput.component);
-    if (trackNeededDillLibraries) {
-      for (Library lib in cachedInput.component.libraries) {
+    for (Library lib in cachedInput.component.libraries) {
+      if (workerInputCacheLibs.containsKey(lib.importUri)) {
+        Uri fromSummary = workerInputCacheLibs[lib.importUri];
+        if (inputSummariesSet.contains(fromSummary)) {
+          throw new StateError(
+              "Asked to load several summaries that contain the same library.");
+        } else {
+          // Library contained in old cached component. Flush that cache.
+          Component component = workerInputCache.remove(fromSummary).component;
+          for (Library lib in component.libraries) {
+            workerInputCacheLibs.remove(lib.importUri);
+          }
+        }
+      } else {
+        workerInputCacheLibs[lib.importUri] = summary;
+      }
+
+      if (trackNeededDillLibraries) {
         libraryToInputDill[lib.importUri] = summary;
       }
     }
@@ -213,6 +250,7 @@
 
   return new InitializedCompilerState(options, processedOpts,
       workerInputCache: workerInputCache,
+      workerInputCacheLibs: workerInputCacheLibs,
       incrementalCompiler: incrementalCompiler,
       tags: tags,
       libraryToInputDill: libraryToInputDill);
diff --git a/pkg/front_end/lib/src/api_unstable/compiler_state.dart b/pkg/front_end/lib/src/api_unstable/compiler_state.dart
index 0852c60..06998b7 100644
--- a/pkg/front_end/lib/src/api_unstable/compiler_state.dart
+++ b/pkg/front_end/lib/src/api_unstable/compiler_state.dart
@@ -15,12 +15,17 @@
   final CompilerOptions options;
   final ProcessedOptions processedOpts;
   final Map<Uri, WorkerInputComponent> workerInputCache;
+
+  /// A map from library import uri to dill uri, i.e. where a library came from,
+  /// for all cached libraries.
+  final Map<Uri, Uri> workerInputCacheLibs;
   final IncrementalCompiler incrementalCompiler;
   final Set<String> tags;
   final Map<Uri, Uri> libraryToInputDill;
 
   InitializedCompilerState(this.options, this.processedOpts,
       {this.workerInputCache,
+      this.workerInputCacheLibs,
       this.incrementalCompiler,
       this.tags,
       this.libraryToInputDill});
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 585c738..8885e67 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -157,6 +157,9 @@
 
   Map<Uri, WorkerInputComponent> workerInputCache =
       oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
+  Map<Uri, Uri> workerInputCacheLibs =
+      oldState?.workerInputCacheLibs ?? new Map<Uri, Uri>();
+
   final List<int> sdkDigest = workerInputDigests[sdkSummary];
   if (sdkDigest == null) {
     throw new StateError("Expected to get sdk digest at $sdkSummary");
@@ -187,12 +190,20 @@
 
     // We'll load a new sdk, anything loaded already will have a wrong root.
     workerInputCache.clear();
+    workerInputCacheLibs.clear();
 
     processedOpts = new ProcessedOptions(options: options);
 
     cachedSdkInput = new WorkerInputComponent(
         sdkDigest, await processedOpts.loadSdkSummary(null));
     workerInputCache[sdkSummary] = cachedSdkInput;
+    for (Library lib in cachedSdkInput.component.libraries) {
+      if (workerInputCacheLibs.containsKey(lib.importUri)) {
+        throw new StateError("Duplicate sources in sdk.");
+      }
+      workerInputCacheLibs[lib.importUri] = sdkSummary;
+    }
+
     incrementalCompiler = new IncrementalCompiler.fromComponent(
         new CompilerContext(processedOpts), cachedSdkInput.component);
     incrementalCompiler.trackNeededDillLibraries = trackNeededDillLibraries;
@@ -234,8 +245,10 @@
   if (doneInputSummaries.length != inputSummaries.length) {
     throw new ArgumentError("Invalid length.");
   }
+  Set<Uri> inputSummariesSet = new Set<Uri>();
   for (int i = 0; i < inputSummaries.length; i++) {
     Uri inputSummary = inputSummaries[i];
+    inputSummariesSet.add(inputSummary);
     WorkerInputComponent cachedInput = workerInputCache[inputSummary];
     List<int> digest = workerInputDigests[inputSummary];
     if (digest == null) {
@@ -244,6 +257,14 @@
     if (cachedInput == null ||
         cachedInput.component.root != nameRoot ||
         !digestsEqual(digest, cachedInput.digest)) {
+      // Remove any old libraries from workerInputCacheLibs.
+      Component component = cachedInput?.component;
+      if (component != null) {
+        for (Library lib in component.libraries) {
+          workerInputCacheLibs.remove(lib.importUri);
+        }
+      }
+
       loadFromDillIndexes.add(i);
     } else {
       // Need to reset cached components so they are usable again.
@@ -273,8 +294,24 @@
             .loadComponent(bytes, nameRoot, alwaysCreateNewNamedNodes: true));
     workerInputCache[summary] = cachedInput;
     doneInputSummaries[index] = cachedInput.component;
-    if (trackNeededDillLibraries) {
-      for (Library lib in cachedInput.component.libraries) {
+    for (Library lib in cachedInput.component.libraries) {
+      if (workerInputCacheLibs.containsKey(lib.importUri)) {
+        Uri fromSummary = workerInputCacheLibs[lib.importUri];
+        if (inputSummariesSet.contains(fromSummary)) {
+          throw new StateError(
+              "Asked to load several summaries that contain the same library.");
+        } else {
+          // Library contained in old cached component. Flush that cache.
+          Component component = workerInputCache.remove(fromSummary).component;
+          for (Library lib in component.libraries) {
+            workerInputCacheLibs.remove(lib.importUri);
+          }
+        }
+      } else {
+        workerInputCacheLibs[lib.importUri] = summary;
+      }
+
+      if (trackNeededDillLibraries) {
         libraryToInputDill[lib.importUri] = summary;
       }
     }
@@ -284,6 +321,7 @@
 
   return new InitializedCompilerState(options, processedOpts,
       workerInputCache: workerInputCache,
+      workerInputCacheLibs: workerInputCacheLibs,
       incrementalCompiler: incrementalCompiler,
       tags: tags,
       libraryToInputDill: libraryToInputDill);
diff --git a/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
index a673664..b3ff558 100644
--- a/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
@@ -6,7 +6,12 @@
 
 import 'package:kernel/ast.dart' show DartType, Nullability;
 
-import 'builder.dart' show LibraryBuilder, TypeBuilder, TypeDeclarationBuilder;
+import 'builder.dart'
+    show
+        LibraryBuilder,
+        NullabilityBuilder,
+        TypeBuilder,
+        TypeDeclarationBuilder;
 
 abstract class BuiltinTypeBuilder extends TypeDeclarationBuilder {
   final DartType type;
@@ -15,9 +20,9 @@
       String name, this.type, LibraryBuilder compilationUnit, int charOffset)
       : super(null, 0, name, compilationUnit, charOffset);
 
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
-    // TODO(dmitryas): Use [nullability].
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+    // TODO(dmitryas): Use [nullabilityBuilder].
     return type;
   }
 
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 1687f79..c4a1632 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -62,6 +62,7 @@
         LibraryBuilder,
         MemberBuilder,
         MetadataBuilder,
+        NullabilityBuilder,
         Scope,
         ScopeBuilder,
         TypeBuilder,
@@ -86,15 +87,15 @@
         templateGenericFunctionTypeInferredAsActualTypeArgument,
         templateImplementsRepeated,
         templateImplementsSuperClass,
-        templateImplicitMixinOverrideContext,
+        templateImplicitMixinOverride,
         templateIncompatibleRedirecteeFunctionType,
         templateIncorrectTypeArgument,
         templateIncorrectTypeArgumentInSupertype,
         templateIncorrectTypeArgumentInSupertypeInferred,
-        templateInterfaceCheckContext,
+        templateInterfaceCheck,
         templateInternalProblemNotFoundIn,
         templateMixinApplicationIncompatibleSupertype,
-        templateNamedMixinOverrideContext,
+        templateNamedMixinOverride,
         templateOverriddenMethodCause,
         templateOverrideFewerNamedArguments,
         templateOverrideFewerPositionalArguments,
@@ -500,10 +501,12 @@
   }
 
   /// If [arguments] are null, the default types for the variables are used.
-  InterfaceType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
+  InterfaceType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
     return buildTypesWithBuiltArguments(
-        library, nullability, buildTypeArguments(library, arguments));
+        library,
+        nullabilityBuilder.build(library),
+        buildTypeArguments(library, arguments));
   }
 
   Supertype buildSupertype(
@@ -1067,7 +1070,9 @@
     }
     if (declaredFunction?.typeParameters?.length !=
         interfaceFunction?.typeParameters?.length) {
-      library.addProblem(
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
           templateOverrideTypeVariablesMismatch.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.name}",
@@ -1075,14 +1080,12 @@
                   "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
-          declaredMember.fileUri,
           context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(_getMemberUri(interfaceMember),
-                        interfaceMember.fileOffset, noLength)
-              ] +
-              inheritedContext(isInterfaceCheck, declaredMember));
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.name)
+                .withLocation(_getMemberUri(interfaceMember),
+                    interfaceMember.fileOffset, noLength)
+          ]);
     } else if (declaredFunction?.typeParameters != null) {
       Map<TypeParameter, DartType> substitutionMap =
           <TypeParameter, DartType>{};
@@ -1103,7 +1106,9 @@
                 interfaceSubstitution.substituteType(interfaceBound);
           }
           if (declaredBound != substitution.substituteType(interfaceBound)) {
-            library.addProblem(
+            reportInvalidOverride(
+                isInterfaceCheck,
+                declaredMember,
                 templateOverrideTypeVariablesMismatch.withArguments(
                     "${declaredMember.enclosingClass.name}."
                         "${declaredMember.name.name}",
@@ -1111,14 +1116,12 @@
                         "${interfaceMember.name.name}"),
                 declaredMember.fileOffset,
                 noLength,
-                declaredMember.fileUri,
                 context: [
-                      templateOverriddenMethodCause
-                          .withArguments(interfaceMember.name.name)
-                          .withLocation(_getMemberUri(interfaceMember),
-                              interfaceMember.fileOffset, noLength)
-                    ] +
-                    inheritedContext(isInterfaceCheck, declaredMember));
+                  templateOverriddenMethodCause
+                      .withArguments(interfaceMember.name.name)
+                      .withLocation(_getMemberUri(interfaceMember),
+                          interfaceMember.fileOffset, noLength)
+                ]);
           }
         }
       }
@@ -1203,14 +1206,14 @@
             interfaceMemberName);
         fileOffset = declaredParameter.fileOffset;
       }
-      library.addProblem(message, fileOffset, noLength, declaredMember.fileUri,
+      reportInvalidOverride(
+          isInterfaceCheck, declaredMember, message, fileOffset, noLength,
           context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(_getMemberUri(interfaceMember),
-                        interfaceMember.fileOffset, noLength)
-              ] +
-              inheritedContext(isInterfaceCheck, declaredMember));
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.name)
+                .withLocation(_getMemberUri(interfaceMember),
+                    interfaceMember.fileOffset, noLength)
+          ]);
     }
   }
 
@@ -1248,7 +1251,9 @@
         isInterfaceCheck);
     if (declaredFunction.positionalParameters.length <
         interfaceFunction.positionalParameters.length) {
-      library.addProblem(
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
           templateOverrideFewerPositionalArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.name}",
@@ -1256,18 +1261,18 @@
                   "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
-          declaredMember.fileUri,
           context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(interfaceMember.fileUri,
-                        interfaceMember.fileOffset, noLength)
-              ] +
-              inheritedContext(isInterfaceCheck, declaredMember));
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.name)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, noLength)
+          ]);
     }
     if (interfaceFunction.requiredParameterCount <
         declaredFunction.requiredParameterCount) {
-      library.addProblem(
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
           templateOverrideMoreRequiredArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.name}",
@@ -1275,14 +1280,12 @@
                   "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
-          declaredMember.fileUri,
           context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(interfaceMember.fileUri,
-                        interfaceMember.fileOffset, noLength)
-              ] +
-              inheritedContext(isInterfaceCheck, declaredMember));
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.name)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, noLength)
+          ]);
     }
     for (int i = 0;
         i < declaredFunction.positionalParameters.length &&
@@ -1311,7 +1314,9 @@
     }
     if (declaredFunction.namedParameters.length <
         interfaceFunction.namedParameters.length) {
-      library.addProblem(
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
           templateOverrideFewerNamedArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.name}",
@@ -1319,14 +1324,12 @@
                   "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
-          declaredMember.fileUri,
           context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(interfaceMember.fileUri,
-                        interfaceMember.fileOffset, noLength)
-              ] +
-              inheritedContext(isInterfaceCheck, declaredMember));
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.name)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, noLength)
+          ]);
     }
     int compareNamedParameters(VariableDeclaration p0, VariableDeclaration p1) {
       return p0.name.compareTo(p1.name);
@@ -1348,7 +1351,9 @@
       while (declaredNamedParameters.current.name !=
           interfaceNamedParameters.current.name) {
         if (!declaredNamedParameters.moveNext()) {
-          library.addProblem(
+          reportInvalidOverride(
+              isInterfaceCheck,
+              declaredMember,
               templateOverrideMismatchNamedParameter.withArguments(
                   "${declaredMember.enclosingClass.name}."
                       "${declaredMember.name.name}",
@@ -1357,14 +1362,12 @@
                       "${interfaceMember.name.name}"),
               declaredMember.fileOffset,
               noLength,
-              declaredMember.fileUri,
               context: [
-                    templateOverriddenMethodCause
-                        .withArguments(interfaceMember.name.name)
-                        .withLocation(interfaceMember.fileUri,
-                            interfaceMember.fileOffset, noLength)
-                  ] +
-                  inheritedContext(isInterfaceCheck, declaredMember));
+                templateOverriddenMethodCause
+                    .withArguments(interfaceMember.name.name)
+                    .withLocation(interfaceMember.fileUri,
+                        interfaceMember.fileOffset, noLength)
+              ]);
           break outer;
         }
       }
@@ -1440,38 +1443,52 @@
     return isCovariant;
   }
 
-  // Extra context on override messages when the overriding member is inherited
-  List<LocatedMessage> inheritedContext(
-      bool isInterfaceCheck, Member declaredMember) {
+  // When the overriding member is inherited, report the class containing
+  // the conflict as the main error.
+  void reportInvalidOverride(bool isInterfaceCheck, Member declaredMember,
+      Message message, int fileOffset, int length,
+      {List<LocatedMessage> context}) {
     if (declaredMember.enclosingClass == cls) {
       // Ordinary override
-      return const [];
-    }
-    if (isInterfaceCheck) {
-      // Interface check
-      return [
-        templateInterfaceCheckContext
-            .withArguments(cls.name)
-            .withLocation(cls.fileUri, cls.fileOffset, cls.name.length)
-      ];
+      library.addProblem(message, fileOffset, length, declaredMember.fileUri,
+          context: context);
     } else {
-      if (cls.isAnonymousMixin) {
-        // Implicit mixin application class
-        String baseName = cls.superclass.demangledName;
-        String mixinName = cls.mixedInClass.name;
-        int classNameLength = cls.nameAsMixinApplicationSubclass.length;
-        return [
-          templateImplicitMixinOverrideContext
-              .withArguments(mixinName, baseName)
-              .withLocation(cls.fileUri, cls.fileOffset, classNameLength)
-        ];
+      context = [
+        message.withLocation(declaredMember.fileUri, fileOffset, length),
+        ...?context
+      ];
+      if (isInterfaceCheck) {
+        // Interface check
+        library.addProblem(
+            templateInterfaceCheck.withArguments(
+                declaredMember.name.name, cls.name),
+            cls.fileOffset,
+            cls.name.length,
+            cls.fileUri,
+            context: context);
       } else {
-        // Named mixin application class
-        return [
-          templateNamedMixinOverrideContext
-              .withArguments(cls.name)
-              .withLocation(cls.fileUri, cls.fileOffset, cls.name.length)
-        ];
+        if (cls.isAnonymousMixin) {
+          // Implicit mixin application class
+          String baseName = cls.superclass.demangledName;
+          String mixinName = cls.mixedInClass.name;
+          int classNameLength = cls.nameAsMixinApplicationSubclass.length;
+          library.addProblem(
+              templateImplicitMixinOverride.withArguments(
+                  mixinName, baseName, declaredMember.name.name),
+              cls.fileOffset,
+              classNameLength,
+              cls.fileUri,
+              context: context);
+        } else {
+          // Named mixin application class
+          library.addProblem(
+              templateNamedMixinOverride.withArguments(
+                  cls.name, declaredMember.name.name),
+              cls.fileOffset,
+              cls.name.length,
+              cls.fileUri,
+              context: context);
+        }
       }
     }
   }
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 df6cd20..ef242db 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -19,7 +19,6 @@
         IntLiteral,
         InterfaceType,
         ListLiteral,
-        Nullability,
         ProcedureKind,
         ReturnStatement,
         StaticGet,
@@ -263,9 +262,9 @@
 
   TypeBuilder get mixedInType => null;
 
-  InterfaceType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
-    return rawType(nullability);
+  InterfaceType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+    return rawType(nullabilityBuilder.build(library));
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 8984604..dc2007f 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -58,8 +58,8 @@
       fileUri);
 
   @override
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
     throw new UnsupportedError("ExtensionBuilder.buildType is not supported.");
   }
 
@@ -93,4 +93,17 @@
 
   @override
   String get debugName => "ExtensionBuilder";
+
+  void buildOutlineExpressions(LibraryBuilder library) {
+    void build(String ignore, Builder declaration) {
+      MemberBuilder member = declaration;
+      member.buildOutlineExpressions(library);
+    }
+
+    // TODO(johnniwinther): Handle annotations on the extension declaration.
+    //MetadataBuilder.buildAnnotations(
+    //    isPatch ? origin.extension : extension,
+    //    metadata, library, this, null);
+    scope.forEach(build);
+  }
 }
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 3083665..44e5a9a 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
@@ -69,8 +69,9 @@
   Token initializerToken;
 
   FormalParameterBuilder(this.metadata, this.modifiers, this.type, this.name,
-      LibraryBuilder compilationUnit, int charOffset)
-      : super(compilationUnit, charOffset);
+      LibraryBuilder compilationUnit, int charOffset,
+      [Uri fileUri])
+      : super(compilationUnit, charOffset, fileUri);
 
   String get debugName => "FormalParameterBuilder";
 
@@ -114,8 +115,8 @@
   FormalParameterBuilder clone(List<TypeBuilder> newTypes) {
     // TODO(dmitryas):  It's not clear how [metadata] is used currently, and
     // how it should be cloned.  Consider cloning it instead of reusing it.
-    return new FormalParameterBuilder(
-        metadata, modifiers, type?.clone(newTypes), name, parent, charOffset)
+    return new FormalParameterBuilder(metadata, modifiers,
+        type?.clone(newTypes), name, parent, charOffset, fileUri)
       ..kind = kind;
   }
 
@@ -129,7 +130,8 @@
             type,
             name,
             null,
-            charOffset)
+            charOffset,
+            fileUri)
           ..parent = parent
           ..variable = variable);
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/invalid_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/invalid_type_builder.dart
index 4e71b742..c03cc7d 100644
--- a/pkg/front_end/lib/src/fasta/builder/invalid_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/invalid_type_builder.dart
@@ -8,7 +8,7 @@
 
 import '../fasta_codes.dart' show LocatedMessage;
 
-import 'builder.dart' show TypeDeclarationBuilder;
+import 'builder.dart' show NullabilityBuilder, TypeDeclarationBuilder;
 
 import '../kernel/kernel_builder.dart' show TypeBuilder, LibraryBuilder;
 
@@ -28,8 +28,8 @@
   @override
   InvalidType get target => const InvalidType();
 
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
     return buildTypesWithBuiltArguments(library, null, null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 27f7bbf..71093d5 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -103,6 +103,9 @@
   /// Returns the [Library] built by this builder.
   Library get library;
 
+  /// Returns the import uri for the library.
+  ///
+  /// This is the canonical uri for the library, for instance 'dart:core'.
   Uri get uri;
 
   Iterator<Builder> get iterator {
@@ -292,15 +295,21 @@
     return Nullability.legacy;
   }
 
-  NullabilityBuilder computeNullabilityFromToken(bool markedAsNullable) {
-    if (!isNonNullableByDefault) {
-      return const NullabilityBuilder.legacy();
-    }
-    if (markedAsNullable) {
-      return const NullabilityBuilder.nullable();
-    }
+  NullabilityBuilder get nullableBuilder {
+    return isNonNullableByDefault
+        ? const NullabilityBuilder.nullable()
+        : const NullabilityBuilder.omitted();
+  }
+
+  NullabilityBuilder get nonNullableBuilder {
     return const NullabilityBuilder.omitted();
   }
+
+  NullabilityBuilder nullableBuilderIfTrue(bool isNullable) {
+    return isNullable
+        ? const NullabilityBuilder.nullable()
+        : const NullabilityBuilder.omitted();
+  }
 }
 
 class LibraryLocalDeclarationIterator implements Iterator<Builder> {
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 458013a..38a57ae 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -214,8 +214,7 @@
 
   DartType build(LibraryBuilder library) {
     assert(declaration != null, "Declaration has not been resolved on $this.");
-    return declaration.buildType(
-        library, nullabilityBuilder.build(library), arguments);
+    return declaration.buildType(library, nullabilityBuilder, arguments);
   }
 
   Supertype buildSupertype(
@@ -254,8 +253,7 @@
     }
   }
 
-  TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution,
-      [List<NamedTypeBuilder> unboundTypes]) {
+  TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution) {
     TypeBuilder result = substitution[declaration];
     if (result != null) {
       assert(declaration is TypeVariableBuilder);
@@ -264,7 +262,7 @@
       List<TypeBuilder> arguments;
       int i = 0;
       for (TypeBuilder argument in this.arguments) {
-        TypeBuilder type = argument.subst(substitution, unboundTypes);
+        TypeBuilder type = argument.subst(substitution);
         if (type != argument) {
           arguments ??= this.arguments.toList();
           arguments[i] = type;
@@ -276,8 +274,6 @@
             new NamedTypeBuilder(name, nullabilityBuilder, arguments);
         if (declaration != null) {
           result.bind(declaration);
-        } else if (unboundTypes != null) {
-          unboundTypes.add(result);
         } else {
           throw new UnsupportedError("Unbound type in substitution: $result.");
         }
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 4f67b7c..b723bdf 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
@@ -29,9 +29,6 @@
   const NullabilityBuilder.nullable()
       : _syntacticNullability = SyntacticNullability.nullable;
 
-  const NullabilityBuilder.legacy()
-      : _syntacticNullability = SyntacticNullability.legacy;
-
   const NullabilityBuilder.omitted()
       : _syntacticNullability = SyntacticNullability.omitted;
 
@@ -40,7 +37,6 @@
       case Nullability.nullable:
         return const NullabilityBuilder.nullable();
       case Nullability.legacy:
-        return const NullabilityBuilder.legacy();
       case Nullability.nonNullable:
       case Nullability.neither:
       default:
@@ -48,16 +44,6 @@
     }
   }
 
-  /// Used temporarily in the places that need proper handling of NNBD features.
-  ///
-  /// Over time the uses of [NullabilityBuilder.pendingImplementation] should be
-  /// eliminated, and the constructor should be eventually removed.  Currently,
-  /// 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(38286): Remove this constructor.
-  const NullabilityBuilder.pendingImplementation() : this.legacy();
-
   Nullability build(LibraryBuilder libraryBuilder, {Nullability ifOmitted}) {
     // TODO(dmitryas): Ensure that either ifOmitted is set or libraryBuilder is
     // provided;
@@ -94,4 +80,10 @@
     unhandled("$_syntacticNullability", "writeNullabilityOn", TreeNode.noOffset,
         noLocation);
   }
+
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    writeNullabilityOn(buffer);
+    return "$buffer";
+  }
 }
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 bf45b08..d818e4d 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -6,7 +6,8 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart';
+import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:kernel/ast.dart' hide Variance;
 
 import 'package:kernel/type_algebra.dart';
 
@@ -361,6 +362,27 @@
     return function = result;
   }
 
+  /// Returns the [index]th parameter of this function.
+  ///
+  /// The index is the syntactical index, including both positional and named
+  /// parameter in the order they are declared, and excluding the synthesized
+  /// this parameter on extension instance members.
+  VariableDeclaration getFormalParameter(int index) {
+    if (isExtensionInstanceMember) {
+      return formals[index + 1].variable;
+    } else {
+      return formals[index].variable;
+    }
+  }
+
+  /// If this is an extension instance method, the tear off closure parameter
+  /// corresponding to the [index]th parameter on the instance method is
+  /// returned.
+  ///
+  /// This is used to update the default value for the closure parameter when
+  /// it has been computed for the original parameter.
+  VariableDeclaration getExtensionTearOffParameter(int index) => null;
+
   /// Returns the parameter for 'this' synthetically added to extension
   /// instance members.
   VariableDeclaration get extensionThis {
@@ -451,6 +473,14 @@
   /// the synthetically created tear off function.
   Procedure _extensionTearOff;
 
+  /// If this is an extension instance method then
+  /// [_extensionTearOffParameterMap] holds a map from the parameters of
+  /// the methods to the parameter of the closure returned in the tear-off.
+  ///
+  /// This map is used to set the default values on the closure parameters when
+  /// these have been built.
+  Map<VariableDeclaration, VariableDeclaration> _extensionTearOffParameterMap;
+
   ProcedureBuilder(
       List<MetadataBuilder> metadata,
       int modifiers,
@@ -485,60 +515,6 @@
     return _body;
   }
 
-  /// If this is an extension instance setter, wrap the setter body to return
-  /// the rhs value from the method.
-  ///
-  /// That is, this setter
-  ///
-  ///     extension E on A {
-  ///       void set property(B value) {
-  ///         value++;
-  ///       }
-  ///     }
-  ///
-  /// is converted into this top level method
-  ///
-  ///    B E|property(A #this, B value) {
-  ///      final #t1 = value;
-  ///      value++;
-  ///      return #t1;
-  ///    }
-  ///
-  void _updateExtensionSetterBody() {
-    if (isExtensionInstanceMember && isSetter) {
-      // TODO(johnniwinther): Avoid the synthetic variable if the parameter is
-      // never modified.
-      // TODO(johnniwinther): Handle setter bodies with return statements.
-      VariableDeclaration value = procedure.function.positionalParameters[1];
-      procedure.function.returnType = value.type;
-      Statement body = procedure.function.body;
-      List<Statement> statements = [];
-      Block block = new Block(statements);
-      VariableDeclaration variableDeclaration =
-          new VariableDeclarationImpl.forValue(
-              new VariableGet(value)..fileOffset = procedure.fileOffset)
-            ..type = value.type;
-      statements.add(variableDeclaration);
-      if (body is Block) {
-        statements.addAll(body.statements);
-      } else {
-        statements.add(body);
-      }
-      ReturnStatement returnStatement = new ReturnStatement(
-          new VariableGet(variableDeclaration)
-            ..fileOffset = procedure.fileEndOffset);
-      statements.add(returnStatement);
-      setParents(block.statements, block);
-      procedure.function.body = block;
-      block.parent = procedure.function;
-    }
-  }
-
-  void set body(Statement newBody) {
-    super.body = newBody;
-    _updateExtensionSetterBody();
-  }
-
   void set asyncModifier(AsyncMarker newModifier) {
     actualAsyncModifier = newModifier;
     if (function != null) {
@@ -639,6 +615,8 @@
         _extensionTearOff != null, "No extension tear off created for $this.");
     if (_extensionTearOff.name != null) return;
 
+    _extensionTearOffParameterMap = {};
+
     int fileOffset = _procedure.fileOffset;
 
     int extensionTypeParameterCount =
@@ -646,17 +624,18 @@
 
     List<TypeParameter> typeParameters = <TypeParameter>[];
 
+    Map<TypeParameter, DartType> substitutionMap = {};
     List<DartType> typeArguments = <DartType>[];
     for (TypeParameter typeParameter in function.typeParameters) {
       TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
       typeParameters.add(newTypeParameter);
-      typeArguments.add(new TypeParameterType(newTypeParameter));
+      typeArguments.add(substitutionMap[typeParameter] =
+          new TypeParameterType(newTypeParameter));
     }
 
     List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
     List<TypeParameter> closureTypeParameters = <TypeParameter>[];
-    Substitution substitution =
-        Substitution.fromPairs(function.typeParameters, typeArguments);
+    Substitution substitution = Substitution.fromMap(substitutionMap);
     for (int index = 0; index < typeParameters.length; index++) {
       TypeParameter newTypeParameter = typeParameters[index];
       newTypeParameter.bound =
@@ -672,12 +651,11 @@
     VariableDeclaration copyParameter(
         VariableDeclaration parameter, DartType type,
         {bool isOptional}) {
-      // TODO(johnniwinther): Handle default values.
-      return new VariableDeclaration(parameter.name,
-          type: type,
-          initializer: isOptional ? new NullLiteral() : null,
-          isFinal: parameter.isFinal)
+      VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
+          type: type, isFinal: parameter.isFinal)
         ..fileOffset = parameter.fileOffset;
+      _extensionTearOffParameterMap[parameter] = newParameter;
+      return newParameter;
     }
 
     VariableDeclaration extensionThis = copyParameter(
@@ -751,6 +729,14 @@
     _extensionTearOff.function.parent = _extensionTearOff;
   }
 
+  @override
+  VariableDeclaration getExtensionTearOffParameter(int index) {
+    if (_extensionTearOffParameterMap != null) {
+      return _extensionTearOffParameterMap[getFormalParameter(index)];
+    }
+    return null;
+  }
+
   /// The [Procedure] built by this builder.
   Procedure get procedure => isPatch ? origin.procedure : _procedure;
 
@@ -940,9 +926,7 @@
     assert(lastInitializer == superInitializer ||
         lastInitializer == redirectingInitializer);
     Initializer error = helper.buildInvalidInitializer(
-        helper.desugarSyntheticExpression(
-            helper.buildProblem(message, charOffset, noLength)),
-        charOffset);
+        helper.buildProblem(message, charOffset, noLength));
     initializers.add(error..parent = _constructor);
     initializers.add(lastInitializer);
   }
@@ -964,10 +948,8 @@
             initializer.fileOffset, helper);
       } else if (_constructor.initializers.isNotEmpty) {
         Initializer first = _constructor.initializers.first;
-        Initializer error = helper.buildInvalidInitializer(
-            helper.desugarSyntheticExpression(helper.buildProblem(
-                messageThisInitializerNotAlone, first.fileOffset, noLength)),
-            first.fileOffset);
+        Initializer error = helper.buildInvalidInitializer(helper.buildProblem(
+            messageThisInitializerNotAlone, first.fileOffset, noLength));
         initializers.add(error..parent = _constructor);
       } else {
         initializers.add(initializer..parent = _constructor);
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index 35afd4b..f07de9d 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -38,6 +38,7 @@
     show
         LibraryBuilder,
         MetadataBuilder,
+        NullabilityBuilder,
         TypeBuilder,
         TypeDeclarationBuilder,
         TypeVariableBuilder;
@@ -204,15 +205,17 @@
   int get typeVariablesCount => typeVariables?.length ?? 0;
 
   @override
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
     DartType thisType = buildThisType(library);
     if (thisType is InvalidType) return thisType;
     FunctionType result = thisType;
     if (typedef.typeParameters.isEmpty && arguments == null) return result;
     // Otherwise, substitute.
     return buildTypesWithBuiltArguments(
-        library, nullability, buildTypeArguments(library, arguments));
+        library,
+        nullabilityBuilder.build(library),
+        buildTypeArguments(library, arguments));
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index d3bf14f..93b1ade 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -10,7 +10,6 @@
 
 import '../scope.dart';
 import 'library_builder.dart';
-import 'named_type_builder.dart';
 import 'type_declaration_builder.dart';
 import 'type_variable_builder.dart';
 
@@ -48,9 +47,7 @@
   // TODO(johnniwinther): Change [NamedTypeBuilder] to hold the
   // [TypeParameterScopeBuilder] should resolve it, so that we cannot create
   // [NamedTypeBuilder]s that are orphaned.
-  TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution,
-          [List<NamedTypeBuilder> unboundTypes]) =>
-      this;
+  TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution) => this;
 
   /// Clones the type builder recursively without binding the subterms to
   /// existing declaration or type variable builders.  All newly built types
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index e25faa6..8d4400c 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -7,7 +7,13 @@
 import 'package:kernel/ast.dart' show DartType, Nullability;
 
 import 'builder.dart'
-    show Builder, LibraryBuilder, MetadataBuilder, ModifierBuilder, TypeBuilder;
+    show
+        Builder,
+        LibraryBuilder,
+        MetadataBuilder,
+        ModifierBuilder,
+        NullabilityBuilder,
+        TypeBuilder;
 
 abstract class TypeDeclarationBuilder extends ModifierBuilder {
   final List<MetadataBuilder> metadata;
@@ -31,8 +37,8 @@
 
   int get typeVariablesCount => 0;
 
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments);
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments);
 
   /// [arguments] have already been built.
   DartType buildTypesWithBuiltArguments(LibraryBuilder library,
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index bea9904..87baf5b 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -14,7 +14,11 @@
 import 'package:kernel/ast.dart'
     show DartType, Nullability, TypeParameter, TypeParameterType;
 
-import '../fasta_codes.dart' show templateTypeArgumentsOnTypeVariable;
+import '../fasta_codes.dart'
+    show
+        templateCycleInTypeVariables,
+        templateInternalProblemUnfinishedTypeVariable,
+        templateTypeArgumentsOnTypeVariable;
 
 import '../kernel/kernel_builder.dart'
     show ClassBuilder, NamedTypeBuilder, LibraryBuilder, TypeBuilder;
@@ -79,8 +83,51 @@
       charOffset,
       fileUri);
 
-  DartType buildType(LibraryBuilder library, Nullability nullability,
-      List<TypeBuilder> arguments) {
+  int get variance => parameter.variance;
+
+  void set variance(int value) {
+    parameter.variance = value;
+  }
+
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+    if (arguments != null) {
+      int charOffset = -1; // TODO(ahe): Provide these.
+      Uri fileUri = null; // TODO(ahe): Provide these.
+      library.addProblem(
+          templateTypeArgumentsOnTypeVariable.withArguments(name),
+          charOffset,
+          name.length,
+          fileUri);
+    }
+    // If the bound is not set yet, the actual value is not important yet as it
+    // will be set later.
+    Nullability nullabilityIfOmitted = parameter.bound != null &&
+            library != null &&
+            library.isNonNullableByDefault
+        ? TypeParameterType.computeNullabilityFromBound(parameter)
+        : Nullability.legacy;
+    DartType type = buildTypesWithBuiltArguments(
+        library,
+        nullabilityBuilder.build(library, ifOmitted: nullabilityIfOmitted),
+        null);
+    if (parameter.bound == null) {
+      if (library is SourceLibraryBuilder) {
+        library.pendingNullabilities.add(type);
+      } else {
+        library.addProblem(
+            templateInternalProblemUnfinishedTypeVariable.withArguments(
+                name, library?.uri),
+            parameter.fileOffset,
+            name.length,
+            fileUri);
+      }
+    }
+    return type;
+  }
+
+  DartType buildTypesWithBuiltArguments(LibraryBuilder library,
+      Nullability nullability, List<DartType> arguments) {
     // TODO(dmitryas): Use [nullability].
     if (arguments != null) {
       int charOffset = -1; // TODO(ahe): Provide these.
@@ -91,34 +138,19 @@
           name.length,
           fileUri);
     }
-    return new TypeParameterType(parameter);
-  }
-
-  DartType buildTypesWithBuiltArguments(LibraryBuilder library,
-      Nullability nullability, List<DartType> arguments) {
-    if (arguments != null) {
-      int charOffset = -1; // TODO(ahe): Provide these.
-      Uri fileUri = null; // TODO(ahe): Provide these.
-      library.addProblem(
-          templateTypeArgumentsOnTypeVariable.withArguments(name),
-          charOffset,
-          name.length,
-          fileUri);
-    }
-    return buildType(library, nullability, null);
+    return new TypeParameterType(parameter, null, nullability);
   }
 
   TypeBuilder asTypeBuilder() {
-    return new NamedTypeBuilder(
-        name, const NullabilityBuilder.pendingImplementation(), null)
+    return new NamedTypeBuilder(name, const NullabilityBuilder.omitted(), null)
       ..bind(this);
   }
 
   void finish(
       LibraryBuilder library, ClassBuilder object, TypeBuilder dynamicType) {
     if (isPatch) return;
-    // TODO(dmitryas): Set the nullability of objectType correctly.
-    DartType objectType = object.buildType(library, Nullability.legacy, null);
+    DartType objectType =
+        object.buildType(library, library.nullableBuilder, null);
     parameter.bound ??= bound?.build(library) ?? objectType;
     // If defaultType is not set, initialize it to dynamic, unless the bound is
     // explicitly specified as Object, in which case defaultType should also be
@@ -130,6 +162,74 @@
             : dynamicType.build(library));
   }
 
+  /// Assigns nullabilities to types in [pendingNullabilities].
+  ///
+  /// It's a helper function to assign the nullabilities to type-parameter types
+  /// after the corresponding type parameters have their bounds set or changed.
+  /// The function takes into account that some of the types in the input list
+  /// may be bounds to some of the type parameters of other types from the input
+  /// list.
+  static void finishNullabilities(LibraryBuilder libraryBuilder,
+      List<TypeParameterType> pendingNullabilities) {
+    // The bounds of type parameters may be type-parameter types of other
+    // parameters from the same declaration.  In this case we need to set the
+    // nullability for them first.  To preserve the ordering, we implement a
+    // depth-first search over the types.  We use the fact that a nullability
+    // of a type parameter type can't ever be 'nullable' if computed from the
+    // bound. It allows us to use 'nullable' nullability as the marker in the
+    // DFS implementation.
+    Nullability marker = Nullability.nullable;
+    List<TypeParameterType> stack =
+        new List<TypeParameterType>.filled(pendingNullabilities.length, null);
+    int stackTop = 0;
+    for (TypeParameterType type in pendingNullabilities) {
+      type.typeParameterTypeNullability = null;
+    }
+    for (TypeParameterType type in pendingNullabilities) {
+      if (type.typeParameterTypeNullability != null) {
+        // Nullability for [type] was already computed on one of the branches
+        // of the depth-first search.  Continue to the next one.
+        continue;
+      }
+      if (type.parameter.bound is TypeParameterType) {
+        TypeParameterType current = type;
+        TypeParameterType next = current.parameter.bound;
+        while (next != null && next.typeParameterTypeNullability == null) {
+          stack[stackTop++] = current;
+          current.typeParameterTypeNullability = marker;
+
+          current = next;
+          if (current.parameter.bound is TypeParameterType) {
+            next = current.parameter.bound;
+            if (next.typeParameterTypeNullability == marker) {
+              next.typeParameterTypeNullability = Nullability.neither;
+              libraryBuilder.addProblem(
+                  templateCycleInTypeVariables.withArguments(
+                      next.parameter.name, current.parameter.name),
+                  next.parameter.fileOffset,
+                  next.parameter.name.length,
+                  next.parameter.location.file);
+              next = null;
+            }
+          } else {
+            next = null;
+          }
+        }
+        current.typeParameterTypeNullability =
+            TypeParameterType.computeNullabilityFromBound(current.parameter);
+        while (stackTop != 0) {
+          --stackTop;
+          current = stack[stackTop];
+          current.typeParameterTypeNullability =
+              TypeParameterType.computeNullabilityFromBound(current.parameter);
+        }
+      } else {
+        type.typeParameterTypeNullability =
+            TypeParameterType.computeNullabilityFromBound(type.parameter);
+      }
+    }
+  }
+
   void applyPatch(covariant TypeVariableBuilder patch) {
     patch.actualOrigin = this;
   }
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 a2a2622..3f1df47 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -3318,6 +3318,26 @@
         r"""Explicit extension application requires exactly 1 positional argument.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExplicitExtensionAsExpression =
+    messageExplicitExtensionAsExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExplicitExtensionAsExpression = const MessageCode(
+    "ExplicitExtensionAsExpression",
+    message:
+        r"""Explicit extension application cannot be used as an expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExplicitExtensionAsLvalue =
+    messageExplicitExtensionAsLvalue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExplicitExtensionAsLvalue = const MessageCode(
+    "ExplicitExtensionAsLvalue",
+    message:
+        r"""Explicit extension application cannot be a target for assignment.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String name,
@@ -4777,30 +4797,35 @@
 const Template<
     Message Function(
         String name,
+        String name2,
         String
-            name2)> templateImplicitMixinOverrideContext = const Template<
-        Message Function(String name, String name2)>(
+            name3)> templateImplicitMixinOverride = const Template<
+        Message Function(String name, String name2, String name3)>(
     messageTemplate:
-        r"""Override was introduced when the mixin '#name' was applied to '#name2'.""",
-    withArguments: _withArgumentsImplicitMixinOverrideContext);
+        r"""Applying the mixin '#name' to '#name2' introduces an erroneous override of '#name3'.""",
+    withArguments: _withArgumentsImplicitMixinOverride);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeImplicitMixinOverrideContext =
-    const Code<Message Function(String name, String name2)>(
-        "ImplicitMixinOverrideContext", templateImplicitMixinOverrideContext,
-        severity: Severity.context);
+const Code<Message Function(String name, String name2, String name3)>
+    codeImplicitMixinOverride =
+    const Code<Message Function(String name, String name2, String name3)>(
+  "ImplicitMixinOverride",
+  templateImplicitMixinOverride,
+);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsImplicitMixinOverrideContext(String name, String name2) {
+Message _withArgumentsImplicitMixinOverride(
+    String name, String name2, String name3) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   if (name2.isEmpty) throw 'No name provided';
   name2 = demangleMixinApplicationName(name2);
-  return new Message(codeImplicitMixinOverrideContext,
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  return new Message(codeImplicitMixinOverride,
       message:
-          """Override was introduced when the mixin '${name}' was applied to '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
+          """Applying the mixin '${name}' to '${name2}' introduces an erroneous override of '${name3}'.""",
+      arguments: {'name': name, 'name2': name2, 'name3': name3});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5656,27 +5681,31 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        String name,
         String
-            name)> templateInterfaceCheckContext = const Template<
-        Message Function(String name)>(
+            name2)> templateInterfaceCheck = const Template<
+        Message Function(String name, String name2)>(
     messageTemplate:
-        r"""Both members are inherited by the non-abstract class '#name'.""",
-    withArguments: _withArgumentsInterfaceCheckContext);
+        r"""The implementation of '#name' in the non-abstract class '#name2' does not conform to its interface.""",
+    withArguments: _withArgumentsInterfaceCheck);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeInterfaceCheckContext =
-    const Code<Message Function(String name)>(
-        "InterfaceCheckContext", templateInterfaceCheckContext,
-        severity: Severity.context);
+const Code<Message Function(String name, String name2)> codeInterfaceCheck =
+    const Code<Message Function(String name, String name2)>(
+  "InterfaceCheck",
+  templateInterfaceCheck,
+);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInterfaceCheckContext(String name) {
+Message _withArgumentsInterfaceCheck(String name, String name2) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  return new Message(codeInterfaceCheckContext,
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeInterfaceCheck,
       message:
-          """Both members are inherited by the non-abstract class '${name}'.""",
-      arguments: {'name': name});
+          """The implementation of '${name}' in the non-abstract class '${name2}' does not conform to its interface.""",
+      arguments: {'name': name, 'name2': name2});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5943,6 +5972,37 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        Uri
+            uri_)> templateInternalProblemUnfinishedTypeVariable = const Template<
+        Message Function(String name, Uri uri_)>(
+    messageTemplate:
+        r"""Unfinished type variable '#name' found in non-source library '#uri'.""",
+    withArguments: _withArgumentsInternalProblemUnfinishedTypeVariable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_)>
+    codeInternalProblemUnfinishedTypeVariable =
+    const Code<Message Function(String name, Uri uri_)>(
+        "InternalProblemUnfinishedTypeVariable",
+        templateInternalProblemUnfinishedTypeVariable,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemUnfinishedTypeVariable(
+    String name, Uri uri_) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  String uri = relativizeUri(uri_);
+  return new Message(codeInternalProblemUnfinishedTypeVariable,
+      message:
+          """Unfinished type variable '${name}' found in non-source library '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String string, String string2)>
     templateInternalProblemUnhandled =
     const Template<Message Function(String string, String string2)>(
@@ -7300,6 +7360,17 @@
     tip: r"""Try combining all of the on clauses into a single clause.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleVarianceModifiers =
+    messageMultipleVarianceModifiers;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleVarianceModifiers = const MessageCode(
+    "MultipleVarianceModifiers",
+    index: 97,
+    message: r"""Each type parameter can have at most one variance modifier.""",
+    tip: r"""Use at most one of the 'in', 'out', or 'inout' modifiers.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeMultipleWith = messageMultipleWith;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7320,27 +7391,31 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        String name,
         String
-            name)> templateNamedMixinOverrideContext = const Template<
-        Message Function(String name)>(
+            name2)> templateNamedMixinOverride = const Template<
+        Message Function(String name, String name2)>(
     messageTemplate:
-        r"""Override was introduced in the mixin application class '#name'.""",
-    withArguments: _withArgumentsNamedMixinOverrideContext);
+        r"""The mixin application class '#name' introduces an erroneous override of '#name2'.""",
+    withArguments: _withArgumentsNamedMixinOverride);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeNamedMixinOverrideContext =
-    const Code<Message Function(String name)>(
-        "NamedMixinOverrideContext", templateNamedMixinOverrideContext,
-        severity: Severity.context);
+const Code<Message Function(String name, String name2)> codeNamedMixinOverride =
+    const Code<Message Function(String name, String name2)>(
+  "NamedMixinOverride",
+  templateNamedMixinOverride,
+);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNamedMixinOverrideContext(String name) {
+Message _withArgumentsNamedMixinOverride(String name, String name2) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  return new Message(codeNamedMixinOverrideContext,
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeNamedMixinOverride,
       message:
-          """Override was introduced in the mixin application class '${name}'.""",
-      arguments: {'name': name});
+          """The mixin application class '${name}' introduces an erroneous override of '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
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 8a82cd2..f1d6340 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -94,9 +94,6 @@
 
 import 'implicit_type_argument.dart' show ImplicitTypeArgument;
 
-import 'kernel_shadow_ast.dart' as shadow
-    show SyntheticExpressionJudgment, SyntheticWrapper;
-
 import 'redirecting_factory_body.dart'
     show
         RedirectingFactoryBody,
@@ -111,6 +108,8 @@
 
 import 'kernel_ast_api.dart';
 
+import 'kernel_shadow_ast.dart';
+
 import 'kernel_builder.dart';
 
 // TODO(ahe): Remove this and ensure all nodes have a location.
@@ -681,10 +680,10 @@
             Initializer initializer;
             if (member.isExternal) {
               initializer = buildInvalidInitializer(
-                  desugarSyntheticExpression(buildProblem(
+                  buildProblem(
                       fasta.messageExternalConstructorWithFieldInitializers,
                       formal.charOffset,
-                      formal.name.length)),
+                      formal.name.length),
                   formal.charOffset);
             } else {
               initializer = buildFieldInitializer(
@@ -790,18 +789,31 @@
         FormalParameterBuilder parameter = formals.parameters[i];
         Expression initializer = parameter.target.initializer;
         if (parameter.isOptional || initializer != null) {
-          VariableDeclaration realParameter = builder.formals[i].target;
           if (parameter.isOptional) {
             initializer ??= forest.createNullLiteral(
-                // TODO(ahe): Should store: realParameter.fileOffset
+                // TODO(ahe): Should store: originParameter.fileOffset
                 // https://github.com/dart-lang/sdk/issues/32289
                 null);
           }
-          realParameter.initializer = initializer..parent = realParameter;
+          VariableDeclaration originParameter = builder.getFormalParameter(i);
+          originParameter.initializer = initializer..parent = originParameter;
           typeInferrer?.inferParameterInitializer(
-              this, initializer, realParameter.type);
+              this, initializer, originParameter.type);
           libraryBuilder.loader.transformPostInference(
-              realParameter, transformSetLiterals, transformCollections);
+              originParameter, transformSetLiterals, transformCollections);
+
+          VariableDeclaration extensionTearOffParameter =
+              builder.getExtensionTearOffParameter(i);
+          if (extensionTearOffParameter != null) {
+            cloner ??= new CloneVisitor();
+            Expression tearOffInitializer = cloner.clone(initializer);
+            extensionTearOffParameter.initializer = tearOffInitializer
+              ..parent = extensionTearOffParameter;
+            libraryBuilder.loader.transformPostInference(
+                extensionTearOffParameter,
+                transformSetLiterals,
+                transformCollections);
+          }
         }
       }
     }
@@ -895,10 +907,8 @@
               forest.createExpressionStatement(
                   // This error is added after type inference is done, so we
                   // don't need to wrap errors in SyntheticExpressionJudgment.
-                  desugarSyntheticExpression(buildProblem(
-                      fasta.messageSetterWithWrongNumberOfFormals,
-                      charOffset,
-                      noLength)),
+                  buildProblem(fasta.messageSetterWithWrongNumberOfFormals,
+                      charOffset, noLength),
                   null),
               body,
             ],
@@ -915,8 +925,8 @@
     } else {
       if (body != null) {
         builder.body = new Block(<Statement>[
-          new ExpressionStatement(desugarSyntheticExpression(buildProblem(
-              fasta.messageExternalMethodWithBody, body.fileOffset, noLength)))
+          new ExpressionStatement(buildProblem(
+              fasta.messageExternalMethodWithBody, body.fileOffset, noLength))
             ..fileOffset = body.fileOffset,
           body,
         ])
@@ -1007,11 +1017,11 @@
         String name = constructorNameForDiagnostics(initialTarget.name.name,
             className: initialTarget.enclosingClass.name);
         // TODO(dmitryas): Report this error earlier.
-        replacementNode = desugarSyntheticExpression(buildProblem(
+        replacementNode = buildProblem(
             fasta.templateCyclicRedirectingFactoryConstructors
                 .withArguments(name),
             initialTarget.fileOffset,
-            name.length));
+            name.length);
       } else if (resolvedTarget is Constructor &&
           resolvedTarget.enclosingClass.isAbstract) {
         replacementNode = evaluateArgumentsBefore(
@@ -1063,12 +1073,6 @@
                   ? Constness.explicitConst
                   : Constness.explicitNew,
               charOffset: invocation.fileOffset);
-          // TODO(dmitryas): Find a better way to unwrap
-          // [SyntheticExpressionJudgment] or not to build it in the first place
-          // when it's not needed.
-          if (replacementNode is shadow.SyntheticExpressionJudgment) {
-            replacementNode = desugarSyntheticExpression(replacementNode);
-          }
         }
       }
 
@@ -1177,7 +1181,7 @@
     for (int i = 0; i < parameters.positionalParameters.length; i++) {
       VariableDeclaration formal = parameters.positionalParameters[i];
       formals[i] = new FormalParameterBuilder(
-          null, 0, null, formal.name, libraryBuilder, formal.fileOffset)
+          null, 0, null, formal.name, libraryBuilder, formal.fileOffset, uri)
         ..variable = formal;
     }
     enterLocalScope(
@@ -1245,9 +1249,7 @@
       // TODO(ahe): Change this to a null check.
       int offset = builder.body?.fileOffset ?? builder.charOffset;
       constructor.initializers.add(buildInvalidInitializer(
-          desugarSyntheticExpression(
-              buildProblem(fasta.messageConstructorNotSync, offset, noLength)),
-          offset));
+          buildProblem(fasta.messageConstructorNotSync, offset, noLength)));
     }
     if (needsImplicitSuperInitializer) {
       /// >If no superinitializer is provided, an implicit superinitializer
@@ -1266,11 +1268,11 @@
           length = (constructor.parent as Class).name.length;
         }
         initializer = buildInvalidInitializer(
-            desugarSyntheticExpression(buildProblem(
+            buildProblem(
                 fasta.templateSuperclassHasNoDefaultConstructor
                     .withArguments(superclass),
                 builder.charOffset,
-                length)),
+                length),
             builder.charOffset);
       } else {
         initializer = buildSuperInitializer(
@@ -1483,7 +1485,7 @@
     if (receiver is ThisAccessGenerator && receiver.isSuper) {
       ThisAccessGenerator thisAccessorReceiver = receiver;
       isSuper = true;
-      receiver = forest.createThisExpression(thisAccessorReceiver.token);
+      receiver = forest.createThisExpression(thisAccessorReceiver.fileOffset);
     }
     push(buildBinaryOperator(toValue(receiver), token, argument, isSuper));
   }
@@ -1530,16 +1532,7 @@
   void doIfNull(Token token) {
     Expression b = popForValue();
     Expression a = popForValue();
-    VariableDeclaration variable = new VariableDeclaration.forValue(a);
-    push(new IfNullJudgment(
-        variable,
-        forest.createConditionalExpression(
-            buildIsNull(new VariableGet(variable), offsetForToken(token), this),
-            token,
-            b,
-            null,
-            new VariableGet(variable)))
-      ..fileOffset = offsetForToken(token));
+    push(new IfNullExpression(a, b)..fileOffset = offsetForToken(token));
   }
 
   /// Handle `a?.b(...)`.
@@ -1619,9 +1612,9 @@
             .withLocation(uri, charOffset, length);
       }
     }
-    return desugarSyntheticExpression(buildProblem(
+    return buildProblem(
         message.messageObject, message.charOffset, message.length,
-        context: context));
+        context: context);
   }
 
   @override
@@ -1879,11 +1872,12 @@
       Builder setter =
           _getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
       // TODO(johnniwinther): Check for constantContext like below?
-      return new ExtensionInstanceAccessGenerator.fromBuilder(this,
+      return new ExtensionInstanceAccessGenerator.fromBuilder(this, name,
           extensionThis, extensionTypeParameters, declaration, token, setter);
     } else if (declaration.isRegularMethod) {
       assert(declaration.isStatic || declaration.isTopLevel);
-      return new StaticAccessGenerator(this, token, declaration.target, null);
+      return new StaticAccessGenerator(
+          this, token, name, declaration.target, null);
     } else if (declaration is PrefixBuilder) {
       assert(prefix == null);
       return new PrefixUseGenerator(this, token, declaration);
@@ -1895,7 +1889,7 @@
       Builder setter =
           _getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
       StaticAccessGenerator generator = new StaticAccessGenerator.fromBuilder(
-          this, declaration, token, setter);
+          this, name, declaration, token, setter);
       if (constantContext != ConstantContext.none) {
         Member readTarget = generator.readTarget;
         if (!(readTarget is Field && readTarget.isConst ||
@@ -2746,9 +2740,21 @@
 
   @override
   void handleNonNullAssertExpression(Token bang) {
+    assert(checkState(bang, [
+      unionOfKinds([ValueKind.Expression, ValueKind.Generator])
+    ]));
     if (!libraryBuilder.loader.target.enableNonNullable) {
       reportNonNullAssertExpressionNotEnabled(bang);
     }
+    Object operand = pop();
+    Expression expression;
+    if (operand is Generator) {
+      expression = operand.buildSimpleRead();
+    } else {
+      assert(operand is Expression);
+      expression = operand;
+    }
+    push(forest.createNullCheck(offsetForToken(bang), expression));
   }
 
   @override
@@ -2775,10 +2781,8 @@
         libraryBuilder.addProblem(
             message, offset, lengthOfSpan(beginToken, suffix), uri);
         push(new UnresolvedType(
-            new NamedTypeBuilder(
-                name,
-                libraryBuilder.computeNullabilityFromToken(isMarkedAsNullable),
-                null)
+            new NamedTypeBuilder(name,
+                libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable), null)
               ..bind(new InvalidTypeBuilder(
                   name,
                   message.withLocation(
@@ -2791,8 +2795,7 @@
     TypeBuilder result;
     if (name is Generator) {
       result = name.buildTypeWithResolvedArguments(
-          libraryBuilder.computeNullabilityFromToken(isMarkedAsNullable),
-          arguments);
+          libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable), arguments);
       if (result == null) {
         unhandled("null", "result", beginToken.charOffset, uri);
       }
@@ -2801,7 +2804,7 @@
       libraryBuilder.addProblem(
           name.message, name.charOffset, name.name.length, name.fileUri);
       result = new NamedTypeBuilder(name.name,
-          libraryBuilder.computeNullabilityFromToken(isMarkedAsNullable), null)
+          libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable), null)
         ..bind(new InvalidTypeBuilder(
             name.name,
             name.message.withLocation(
@@ -2847,7 +2850,7 @@
     List<TypeVariableBuilder> typeVariables = pop();
     UnresolvedType type = formals.toFunctionType(
         returnType,
-        libraryBuilder.computeNullabilityFromToken(questionMark != null),
+        libraryBuilder.nullableBuilderIfTrue(questionMark != null),
         typeVariables);
     exitLocalScope();
     push(type);
@@ -2997,7 +3000,7 @@
       }
     } else {
       parameter = new FormalParameterBuilder(null, modifiers, type?.builder,
-          name?.name, libraryBuilder, offsetForToken(nameToken));
+          name?.name, libraryBuilder, offsetForToken(nameToken), uri);
     }
     VariableDeclaration variable =
         parameter.build(libraryBuilder, functionNestingLevel);
@@ -3069,10 +3072,8 @@
     if (!libraryBuilder.loader.target.enableNonNullable) {
       reportErrorIfNullableType(question);
     }
-    UnresolvedType type = formals.toFunctionType(
-        returnType,
-        libraryBuilder.computeNullabilityFromToken(question != null),
-        typeVariables);
+    UnresolvedType type = formals.toFunctionType(returnType,
+        libraryBuilder.nullableBuilderIfTrue(question != null), typeVariables);
     exitLocalScope();
     push(type);
     functionNestingLevel--;
@@ -3277,7 +3278,7 @@
       bool isSuper = false;
       if (receiver is ThisAccessGenerator && receiver.isSuper) {
         isSuper = true;
-        receiverValue = forest.createThisExpression(receiver.token);
+        receiverValue = forest.createThisExpression(receiver.fileOffset);
       } else {
         receiverValue = toValue(receiver);
       }
@@ -3444,15 +3445,13 @@
     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);
+      return throwNoSuchMethodError(
+          forest.createNullLiteral(null)..fileOffset = charOffset,
+          target.name.name,
+          arguments,
+          charOffset,
+          candidate: target,
+          message: argMessage);
     }
 
     bool isConst = constness == Constness.explicitConst ||
@@ -3463,12 +3462,8 @@
         addProblem(fasta.messageMissingExplicitConst, charOffset, charLength);
       }
       if (isConst && !target.isConst) {
-        return wrapInvalidConstructorInvocation(
-            desugarSyntheticExpression(buildProblem(
-                fasta.messageNonConstConstructor, charOffset, charLength)),
-            target,
-            arguments,
-            charOffset);
+        return buildProblem(
+            fasta.messageNonConstConstructor, charOffset, charLength);
       }
       ConstructorInvocation node =
           new ConstructorInvocation(target, arguments, isConst: isConst)
@@ -3484,12 +3479,8 @@
           addProblem(fasta.messageMissingExplicitConst, charOffset, charLength);
         }
         if (isConst && !procedure.isConst) {
-          return wrapInvalidConstructorInvocation(
-              desugarSyntheticExpression(buildProblem(
-                  fasta.messageNonConstFactory, charOffset, charLength)),
-              target,
-              arguments,
-              charOffset);
+          return buildProblem(
+              fasta.messageNonConstFactory, charOffset, charLength);
         }
         StaticInvocation node = new FactoryConstructorInvocationJudgment(
             target, arguments,
@@ -3517,15 +3508,13 @@
     LocatedMessage argMessage = checkArgumentsForFunction(
         target.function, arguments, fileOffset, typeParameters);
     if (argMessage != null) {
-      return wrapSyntheticExpression(
-          throwNoSuchMethodError(
-              forest.createNullLiteral(null)..fileOffset = fileOffset,
-              target.name.name,
-              arguments,
-              fileOffset,
-              candidate: target,
-              message: argMessage),
-          fileOffset);
+      return throwNoSuchMethodError(
+          forest.createNullLiteral(null)..fileOffset = fileOffset,
+          target.name.name,
+          arguments,
+          fileOffset,
+          candidate: target,
+          message: argMessage);
     }
 
     StaticInvocation node = new StaticInvocation(target, arguments)
@@ -3706,13 +3695,11 @@
       if (type is ProblemBuilder) {
         typeName = type.fullNameForErrors;
       }
-      push(wrapSyntheticExpression(
-          throwNoSuchMethodError(
-              forest.createNullLiteral(null)..fileOffset = offset,
-              debugName(typeName, name),
-              arguments,
-              nameToken.charOffset),
-          offset));
+      push(throwNoSuchMethodError(
+          forest.createNullLiteral(null)..fileOffset = offset,
+          debugName(typeName, name),
+          arguments,
+          nameToken.charOffset));
     }
     constantContext = savedConstantContext;
   }
@@ -3766,17 +3753,13 @@
         message = b.message.withLocation(uri, charOffset, noLength);
       } else if (b.isConstructor) {
         if (type.isAbstract) {
-          return wrapInvalidConstructorInvocation(
-              evaluateArgumentsBefore(
-                  arguments,
-                  buildAbstractClassInstantiationError(
-                      fasta.templateAbstractClassInstantiation
-                          .withArguments(type.name),
-                      type.name,
-                      nameToken.charOffset)),
-              target,
+          return evaluateArgumentsBefore(
               arguments,
-              charOffset);
+              buildAbstractClassInstantiationError(
+                  fasta.templateAbstractClassInstantiation
+                      .withArguments(type.name),
+                  type.name,
+                  nameToken.charOffset));
         }
       }
       if (target is Constructor ||
@@ -3808,15 +3791,12 @@
     }
     errorName ??= name;
 
-    return wrapUnresolvedTargetInvocation(
-        throwNoSuchMethodError(
-            forest.createNullLiteral(null)..fileOffset = charOffset,
-            errorName,
-            arguments,
-            nameLastToken.charOffset,
-            message: message),
+    return throwNoSuchMethodError(
+        forest.createNullLiteral(null)..fileOffset = charOffset,
+        errorName,
         arguments,
-        arguments.fileOffset);
+        nameLastToken.charOffset,
+        message: message);
   }
 
   @override
@@ -3889,10 +3869,8 @@
             ? elseEntry.fileOffset
             : offsetForToken(ifToken);
         push(new MapEntry(
-            desugarSyntheticExpression(buildProblem(
-                fasta.templateExpectedAfterButGot.withArguments(':'),
-                offset,
-                1)),
+            buildProblem(fasta.templateExpectedAfterButGot.withArguments(':'),
+                offset, 1),
             new NullLiteral())
           ..fileOffset = offsetForToken(ifToken));
       }
@@ -3908,10 +3886,8 @@
             ? thenEntry.fileOffset
             : offsetForToken(ifToken);
         push(new MapEntry(
-            desugarSyntheticExpression(buildProblem(
-                fasta.templateExpectedAfterButGot.withArguments(':'),
-                offset,
-                1)),
+            buildProblem(fasta.templateExpectedAfterButGot.withArguments(':'),
+                offset, 1),
             new NullLiteral())
           ..fileOffset = offsetForToken(ifToken));
       }
@@ -4066,14 +4042,8 @@
     if (!isFunctionExpression) {
       annotations = pop(); // Metadata.
     }
-    FunctionNode function = formals.buildFunctionNode(
-        libraryBuilder,
-        returnType,
-        typeParameters,
-        asyncModifier,
-        body,
-        const NullabilityBuilder.pendingImplementation(),
-        token.charOffset);
+    FunctionNode function = formals.buildFunctionNode(libraryBuilder,
+        returnType, typeParameters, asyncModifier, body, token.charOffset);
 
     if (declaration is FunctionDeclaration) {
       VariableDeclaration variable = declaration.variable;
@@ -4095,15 +4065,13 @@
         Expression expression = new NamedFunctionExpressionJudgment(variable);
         if (oldInitializer != null) {
           // This must have been a compile-time error.
-          Expression error = desugarSyntheticExpression(oldInitializer);
+          Expression error = oldInitializer;
           assert(isErroneousNode(error));
           int offset = forest.readOffset(expression);
-          push(wrapSyntheticExpression(
-              new Let(
-                  new VariableDeclaration.forValue(error)..fileOffset = offset,
-                  expression)
-                ..fileOffset = offset,
-              offset));
+          push(new Let(
+              new VariableDeclaration.forValue(error)..fileOffset = offset,
+              expression)
+            ..fileOffset = offset);
         } else {
           push(expression);
         }
@@ -4154,14 +4122,8 @@
     FormalParameters formals = pop();
     exitFunction();
     List<TypeVariableBuilder> typeParameters = pop();
-    FunctionNode function = formals.buildFunctionNode(
-        libraryBuilder,
-        null,
-        typeParameters,
-        asyncModifier,
-        body,
-        const NullabilityBuilder.pendingImplementation(),
-        token.charOffset)
+    FunctionNode function = formals.buildFunctionNode(libraryBuilder, null,
+        typeParameters, asyncModifier, body, token.charOffset)
       ..fileOffset = beginToken.charOffset;
 
     if (constantContext != ConstantContext.none) {
@@ -4295,11 +4257,6 @@
           new VariableGetImpl(variable, fact, scope)
             ..fileOffset = inKeyword.offset,
           voidContext: true);
-      if (syntheticAssignment is shadow.SyntheticExpressionJudgment) {
-        syntheticAssignment = wrapSyntheticExpression(
-            desugarSyntheticExpression(syntheticAssignment),
-            offsetForToken(lvalue.token));
-      }
       return forest.createExpressionStatement(syntheticAssignment, null);
     }
     Message message = forest.isVariablesDeclaration(lvalue)
@@ -4824,6 +4781,16 @@
           libraryBuilder.loader.target.objectClassBuilder,
           libraryBuilder.loader.target.dynamicType);
     }
+    TypeVariableBuilder.finishNullabilities(
+        libraryBuilder, libraryBuilder.pendingNullabilities);
+    libraryBuilder.pendingNullabilities.clear();
+  }
+
+  @override
+  void handleVarianceModifier(Token variance) {
+    if (!libraryBuilder.loader.target.enableVariance) {
+      reportVarianceModifierNotEnabled(variance);
+    }
   }
 
   @override
@@ -4849,15 +4816,13 @@
   @override
   void handleInvalidStatement(Token token, Message message) {
     Statement statement = pop();
-    push(new ExpressionStatement(desugarSyntheticExpression(
-        buildProblem(message, statement.fileOffset, noLength))));
+    push(new ExpressionStatement(
+        buildProblem(message, statement.fileOffset, noLength)));
   }
 
   @override
   Expression buildProblem(Message message, int charOffset, int length,
-      {List<LocatedMessage> context,
-      bool suppressMessage: false,
-      bool wrapInSyntheticExpression: true}) {
+      {List<LocatedMessage> context, bool suppressMessage: false}) {
     if (!suppressMessage) {
       addProblem(message, charOffset, length,
           wasHandled: true, context: context);
@@ -4866,9 +4831,7 @@
         .format(message.withLocation(uri, charOffset, length), Severity.error);
     InvalidExpression expression = new InvalidExpression(text)
       ..fileOffset = charOffset;
-    return wrapInSyntheticExpression
-        ? wrapSyntheticExpression(expression, charOffset)
-        : expression;
+    return expression;
   }
 
   @override
@@ -4897,9 +4860,9 @@
     }
     return new Let(
         new VariableDeclaration.forValue(
-            desugarSyntheticExpression(buildProblem(
+            buildProblem(
                 message.messageObject, message.charOffset, message.length,
-                context: context)),
+                context: context),
             type: const BottomType())
           ..fileOffset = offset,
         expression);
@@ -4944,9 +4907,6 @@
         ]),
         constness: Constness.explicitNew,
         charOffset: charOffset);
-    if (invocation is shadow.SyntheticExpressionJudgment) {
-      invocation = desugarSyntheticExpression(invocation);
-    }
     return forest.createThrow(null, invocation)..fileOffset = charOffset;
   }
 
@@ -4986,12 +4946,11 @@
     return new ShadowInvalidFieldInitializer(
         field,
         value,
-        new VariableDeclaration.forValue(desugarSyntheticExpression(
-            buildProblem(
-                fasta.templateFinalInstanceVariableAlreadyInitialized
-                    .withArguments(name),
-                offset,
-                noLength))))
+        new VariableDeclaration.forValue(buildProblem(
+            fasta.templateFinalInstanceVariableAlreadyInitialized
+                .withArguments(name),
+            offset,
+            noLength)))
       ..fileOffset = offset;
   }
 
@@ -5013,10 +4972,10 @@
       // Duplicated name, already reported.
       return new LocalInitializer(
           new VariableDeclaration.forValue(
-              desugarSyntheticExpression(buildProblem(
+              buildProblem(
                   fasta.templateDuplicatedDeclarationUse.withArguments(name),
                   fieldNameOffset,
-                  name.length))
+                  name.length)
                 ..fileOffset = fieldNameOffset)
             ..fileOffset = fieldNameOffset)
         ..fileOffset = fieldNameOffset;
@@ -5048,9 +5007,6 @@
             ]),
             constness: Constness.explicitNew,
             charOffset: assignmentOffset);
-        if (invocation is shadow.SyntheticExpressionJudgment) {
-          invocation = desugarSyntheticExpression(invocation);
-        }
         return new ShadowInvalidFieldInitializer(
             builder.field,
             expression,
@@ -5078,10 +5034,10 @@
       }
     } else {
       return buildInvalidInitializer(
-          desugarSyntheticExpression(buildProblem(
+          buildProblem(
               fasta.templateInitializerForStaticField.withArguments(name),
               fieldNameOffset,
-              name.length)),
+              name.length),
           fieldNameOffset);
     }
   }
@@ -5094,10 +5050,8 @@
       return buildInvalidSuperInitializer(
           constructor,
           arguments,
-          desugarSyntheticExpression(buildProblem(
-              fasta.messageConstConstructorWithNonConstSuper,
-              charOffset,
-              constructor.name.name.length)),
+          buildProblem(fasta.messageConstConstructorWithNonConstSuper,
+              charOffset, constructor.name.name.length),
           charOffset);
     }
     needsImplicitSuperInitializer = false;
@@ -5289,6 +5243,19 @@
   }
 
   @override
+  Expression buildProblemErrorIfConst(
+      Message message, int charOffset, int length,
+      {bool wasHandled: false, List<LocatedMessage> context}) {
+    addProblemErrorIfConst(message, charOffset, length,
+        wasHandled: wasHandled, context: context);
+    String text = libraryBuilder.loader.target.context
+        .format(message.withLocation(uri, charOffset, length), Severity.error);
+    InvalidExpression expression = new InvalidExpression(text)
+      ..fileOffset = charOffset;
+    return expression;
+  }
+
+  @override
   void reportDuplicatedDeclaration(
       Builder existing, String name, int charOffset) {
     List<LocatedMessage> context = existing.isSynthetic
@@ -5369,49 +5336,6 @@
     }
     return name.isEmpty ? className : "$className.$name";
   }
-
-  @override
-  Expression wrapSyntheticExpression(Expression desugared, int charOffset) {
-    return shadow.SyntheticWrapper.wrapSyntheticExpression(desugared)
-      ..fileOffset = charOffset;
-  }
-
-  @override
-  Expression desugarSyntheticExpression(Expression node) {
-    shadow.SyntheticExpressionJudgment shadowNode = node;
-    return shadowNode.desugared;
-  }
-
-  @override
-  Expression wrapInvalidConstructorInvocation(Expression desugared,
-      Member constructor, Arguments arguments, int charOffset) {
-    return shadow.SyntheticWrapper.wrapInvalidConstructorInvocation(
-        desugared, constructor, arguments)
-      ..fileOffset = charOffset;
-  }
-
-  @override
-  Expression wrapInvalidWrite(
-      Expression desugared, Expression expression, int charOffset) {
-    return shadow.SyntheticWrapper.wrapInvalidWrite(desugared, expression)
-      ..fileOffset = charOffset;
-  }
-
-  @override
-  Expression wrapUnresolvedTargetInvocation(
-      Expression desugared, Arguments arguments, int charOffset) {
-    return shadow.SyntheticWrapper.wrapUnresolvedTargetInvocation(
-        desugared, arguments)
-      ..fileOffset = charOffset;
-  }
-
-  @override
-  Expression wrapUnresolvedVariableAssignment(
-      Expression desugared, bool isCompound, Expression rhs, int charOffset) {
-    return shadow.SyntheticWrapper.wrapUnresolvedVariableAssignment(
-        desugared, isCompound, rhs)
-      ..fileOffset = charOffset;
-  }
 }
 
 abstract class EnsureLoaded {
@@ -5580,12 +5504,11 @@
       List<TypeVariableBuilder> typeParameters,
       AsyncMarker asyncModifier,
       Statement body,
-      NullabilityBuilder nullabilityBuilder,
       int fileEndOffset) {
-    FunctionType type =
-        toFunctionType(returnType, nullabilityBuilder, typeParameters)
-            .builder
-            .build(library);
+    FunctionType type = toFunctionType(
+            returnType, const NullabilityBuilder.omitted(), typeParameters)
+        .builder
+        .build(library);
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
     List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
     if (parameters != null) {
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 39d84cb..991fa4e 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
@@ -247,8 +247,8 @@
   TypeBuilder asSupertypeOf(Class cls, Class supertype) {
     ClassHierarchyNode clsNode = getNodeFromKernelClass(cls);
     if (cls == supertype) {
-      return new NamedTypeBuilder(clsNode.classBuilder.name,
-          const NullabilityBuilder.pendingImplementation(), null)
+      return new NamedTypeBuilder(
+          clsNode.classBuilder.name, const NullabilityBuilder.omitted(), null)
         ..bind(clsNode.classBuilder);
     }
     ClassHierarchyNode supertypeNode = getNodeFromKernelClass(supertype);
@@ -1964,10 +1964,11 @@
   InterfaceType get nullType => hierarchy.coreTypes.nullType;
 
   @override
-  InterfaceType get objectType => hierarchy.coreTypes.objectLegacyRawType;
+  InterfaceType get objectLegacyRawType =>
+      hierarchy.coreTypes.objectLegacyRawType;
 
   @override
-  InterfaceType get rawFunctionType =>
+  InterfaceType get functionLegacyRawType =>
       hierarchy.coreTypes.functionLegacyRawType;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index 21ba143..8803399 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -413,11 +413,11 @@
         isAsync: entry.isAsync)
       ..fileOffset = entry.fileOffset;
   }
-  return helper.desugarSyntheticExpression(helper.buildProblem(
+  return helper.buildProblem(
     templateExpectedButGot.withArguments(','),
     entry.fileOffset,
     1,
-  ));
+  );
 }
 
 bool isConvertibleToMapEntry(Expression element) {
@@ -466,11 +466,11 @@
       ..fileOffset = element.fileOffset;
   }
   return new MapEntry(
-      helper.desugarSyntheticExpression(helper.buildProblem(
+      helper.buildProblem(
         templateExpectedAfterButGot.withArguments(':'),
         element.fileOffset,
         // TODO(danrubel): what is the length of the expression?
         1,
-      )),
+      ),
       new NullLiteral());
 }
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 fa0afb1..539b86f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -1230,15 +1230,17 @@
               statement.message,
               templateConstEvalInvalidType.withArguments(
                   message,
-                  typeEnvironment.stringType,
+                  typeEnvironment.coreTypes.stringLegacyRawType,
                   message.getType(typeEnvironment)));
         }
       }
     } else {
       report(
           statement.condition,
-          templateConstEvalInvalidType.withArguments(condition,
-              typeEnvironment.boolType, condition.getType(typeEnvironment)));
+          templateConstEvalInvalidType.withArguments(
+              condition,
+              typeEnvironment.coreTypes.boolLegacyRawType,
+              condition.getType(typeEnvironment)));
     }
   }
 
@@ -1303,7 +1305,7 @@
                 templateConstEvalInvalidBinaryOperandType.withArguments(
                     '+',
                     receiver,
-                    typeEnvironment.stringType,
+                    typeEnvironment.coreTypes.stringLegacyRawType,
                     other.getType(typeEnvironment)));
         }
       }
@@ -1323,7 +1325,7 @@
                 templateConstEvalInvalidBinaryOperandType.withArguments(
                     op,
                     other,
-                    typeEnvironment.intType,
+                    typeEnvironment.coreTypes.intLegacyRawType,
                     other.getType(typeEnvironment)));
           }
           num receiverValue = (receiver as PrimitiveConstant<num>).value;
@@ -1335,7 +1337,7 @@
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
                 receiver,
-                typeEnvironment.numType,
+                typeEnvironment.coreTypes.numLegacyRawType,
                 other.getType(typeEnvironment)));
       }
     } else if (receiver is DoubleConstant) {
@@ -1346,7 +1348,7 @@
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
                 receiver,
-                typeEnvironment.intType,
+                typeEnvironment.coreTypes.intLegacyRawType,
                 receiver.getType(typeEnvironment)));
       }
       if (arguments.length == 0) {
@@ -1367,7 +1369,7 @@
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
                 receiver,
-                typeEnvironment.numType,
+                typeEnvironment.coreTypes.numLegacyRawType,
                 other.getType(typeEnvironment)));
       }
     } else if (receiver is BoolConstant) {
@@ -1420,7 +1422,7 @@
               templateConstEvalInvalidBinaryOperandType.withArguments(
                   node.operator,
                   left,
-                  typeEnvironment.boolType,
+                  typeEnvironment.coreTypes.boolLegacyRawType,
                   right.getType(typeEnvironment)));
         }
         return report(
@@ -1441,7 +1443,7 @@
               templateConstEvalInvalidBinaryOperandType.withArguments(
                   node.operator,
                   left,
-                  typeEnvironment.boolType,
+                  typeEnvironment.coreTypes.boolLegacyRawType,
                   right.getType(typeEnvironment)));
         }
         return report(
@@ -1479,8 +1481,10 @@
     } else {
       return report(
           node.condition,
-          templateConstEvalInvalidType.withArguments(condition,
-              typeEnvironment.boolType, condition.getType(typeEnvironment)));
+          templateConstEvalInvalidType.withArguments(
+              condition,
+              typeEnvironment.coreTypes.boolLegacyRawType,
+              condition.getType(typeEnvironment)));
     }
   }
 
@@ -1746,7 +1750,7 @@
     }
     if (constant is NullConstant) {
       return makeBoolConstant(node.type == typeEnvironment.nullType ||
-          node.type == typeEnvironment.objectType ||
+          node.type == typeEnvironment.coreTypes.objectLegacyRawType ||
           node.type is DynamicType);
     }
     return makeBoolConstant(
@@ -1764,8 +1768,10 @@
     }
     return report(
         node,
-        templateConstEvalInvalidType.withArguments(constant,
-            typeEnvironment.boolType, constant.getType(typeEnvironment)));
+        templateConstEvalInvalidType.withArguments(
+            constant,
+            typeEnvironment.coreTypes.boolLegacyRawType,
+            constant.getType(typeEnvironment)));
   }
 
   @override
@@ -1850,14 +1856,14 @@
   bool isSubtype(Constant constant, DartType type) {
     DartType constantType = constant.getType(typeEnvironment);
     if (targetingJavaScript) {
-      if (constantType == typeEnvironment.intType &&
-          type == typeEnvironment.doubleType) {
+      if (constantType == typeEnvironment.coreTypes.intLegacyRawType &&
+          type == typeEnvironment.coreTypes.doubleLegacyRawType) {
         // With JS semantics, an integer is also a double.
         return true;
       }
 
-      if (constantType == typeEnvironment.doubleType &&
-          type == typeEnvironment.intType) {
+      if (constantType == typeEnvironment.coreTypes.doubleLegacyRawType &&
+          type == typeEnvironment.coreTypes.intLegacyRawType) {
         double value = (constant as DoubleConstant).value;
         if (value.isFinite && value == value.truncateToDouble()) {
           return true;
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index de53658..89098b2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -47,9 +47,6 @@
 
 import '../scope.dart';
 
-import '../type_inference/type_promotion.dart'
-    show TypePromotionFact, TypePromotionScope;
-
 import 'body_builder.dart' show noLocation;
 
 import 'constness.dart' show Constness;
@@ -85,6 +82,8 @@
 
 import 'kernel_shadow_ast.dart';
 
+import '../type_inference/type_inferrer.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.
 ///
@@ -127,39 +126,14 @@
   ///
   /// The read of this subexpression does _not_ need to support a simultaneous
   /// write of the same subexpression.
-  Expression buildSimpleRead() {
-    return _finish(_makeSimpleRead(), null);
-  }
-
-  /// Internal implementation for [buildSimpleRead].
-  ///
-  /// The read of the this subexpression does _not_ need to support a
-  /// simultaneous write of the same subexpression.
-  ///
-  /// This is in contrast to [_makeRead] which is used for instance in compound
-  /// assignments like `a.b += c` where both a read and a write of the
-  /// subexpression `a.b` occurs.
-  ///
-  /// Subclasses that can benefit from this distinction should override this
-  /// method.
-  Expression _makeSimpleRead() => _makeRead(null);
+  Expression buildSimpleRead();
 
   /// Builds a [Expression] representing an assignment with the generator on
   /// the LHS and [value] on the RHS.
   ///
   /// The returned expression evaluates to the assigned value, unless
   /// [voidContext] is true, in which case it may evaluate to anything.
-  Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    ComplexAssignmentJudgment complexAssignment = startComplexAssignment(value);
-    return _finish(_makeSimpleWrite(value, voidContext, complexAssignment),
-        complexAssignment);
-  }
-
-  /// Internal implementation for [buildAssignment].
-  Expression _makeSimpleWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    return _makeWrite(value, voidContext, complexAssignment);
-  }
+  Expression buildAssignment(Expression value, {bool voidContext: false});
 
   /// Returns a [Expression] representing a null-aware assignment (`??=`) with
   /// the generator on the LHS and [value] on the RHS.
@@ -169,31 +143,7 @@
   ///
   /// [type] is the static type of the RHS.
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
-      {bool voidContext: false}) {
-    ComplexAssignmentJudgment complexAssignment = startComplexAssignment(value);
-    if (voidContext) {
-      Expression nullAwareCombiner = _forest.createConditionalExpression(
-          buildIsNull(_makeRead(complexAssignment), offset, _helper),
-          null,
-          _makeWrite(value, false, complexAssignment),
-          null,
-          _forest.createNullLiteral(null)..fileOffset = offset)
-        ..fileOffset = offset;
-      complexAssignment?.nullAwareCombiner = nullAwareCombiner;
-      return _finish(nullAwareCombiner, complexAssignment);
-    }
-    VariableDeclaration tmp =
-        new VariableDeclaration.forValue(_makeRead(complexAssignment));
-    Expression nullAwareCombiner = _forest.createConditionalExpression(
-        buildIsNull(new VariableGet(tmp), offset, _helper),
-        null,
-        _makeWrite(value, false, complexAssignment),
-        null,
-        new VariableGet(tmp))
-      ..fileOffset = offset;
-    complexAssignment?.nullAwareCombiner = nullAwareCombiner;
-    return _finish(makeLet(tmp, nullAwareCombiner), complexAssignment);
-  }
+      {bool voidContext: false});
 
   /// Returns a [Expression] representing a compound assignment (e.g. `+=`)
   /// with the generator on the LHS and [value] on the RHS.
@@ -202,17 +152,7 @@
       bool voidContext: false,
       Procedure interfaceTarget,
       bool isPreIncDec: false,
-      bool isPostIncDec: false}) {
-    ComplexAssignmentJudgment complexAssignment = startComplexAssignment(value);
-    complexAssignment?.isPreIncDec = isPreIncDec;
-    complexAssignment?.isPostIncDec = isPostIncDec;
-    Expression combiner = makeBinary(_makeRead(complexAssignment),
-        binaryOperator, interfaceTarget, value, _helper,
-        offset: offset);
-    complexAssignment?.combiner = combiner;
-    return _finish(_makeWrite(combiner, voidContext, complexAssignment),
-        complexAssignment);
-  }
+      bool isPostIncDec: false});
 
   /// Returns a [Expression] representing a pre-increment or pre-decrement of
   /// the generator.
@@ -223,6 +163,9 @@
     return buildCompoundAssignment(
         binaryOperator, _forest.createIntLiteral(1, null)..fileOffset = offset,
         offset: offset,
+        // TODO(johnniwinther): We are missing some void contexts here. For
+        // instance `++a?.b;` is not providing a void context making it default
+        // `true`.
         voidContext: voidContext,
         interfaceTarget: interfaceTarget,
         isPreIncDec: true);
@@ -233,43 +176,15 @@
   Expression buildPostfixIncrement(Name binaryOperator,
       {int offset: TreeNode.noOffset,
       bool voidContext: false,
-      Procedure interfaceTarget}) {
-    if (voidContext) {
-      return buildCompoundAssignment(binaryOperator,
-          _forest.createIntLiteral(1, null)..fileOffset = offset,
-          offset: offset,
-          voidContext: voidContext,
-          interfaceTarget: interfaceTarget,
-          isPostIncDec: true);
-    }
-    IntLiteral rhs = _forest.createIntLiteral(1, null)..fileOffset = offset;
-    ComplexAssignmentJudgment complexAssignment = startComplexAssignment(rhs);
-    VariableDeclaration value =
-        new VariableDeclaration.forValue(_makeRead(complexAssignment));
-    valueAccess() => new VariableGet(value);
-    Expression combiner = makeBinary(
-        valueAccess(), binaryOperator, interfaceTarget, rhs, _helper,
-        offset: offset);
-    complexAssignment?.combiner = combiner;
-    complexAssignment?.isPostIncDec = true;
-    VariableDeclarationImpl dummy = new VariableDeclarationImpl.forValue(
-        _makeWrite(combiner, true, complexAssignment));
-    return _finish(
-        makeLet(value, makeLet(dummy, valueAccess())), complexAssignment);
-  }
+      Procedure interfaceTarget});
 
   /// Returns a [Expression] representing a compile-time error.
   ///
   /// At runtime, an exception will be thrown.
   Expression _makeInvalidRead() {
-    return _helper.wrapSyntheticExpression(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(fileOffset),
-            _plainNameForRead,
-            _forest.createArgumentsEmpty(noLocation),
-            fileOffset,
-            isGetter: true),
-        fileOffset);
+    return _helper.throwNoSuchMethodError(_forest.createNullLiteral(fileOffset),
+        _plainNameForRead, _forest.createArgumentsEmpty(noLocation), fileOffset,
+        isGetter: true);
   }
 
   /// Returns a [Expression] representing a compile-time error wrapping
@@ -277,90 +192,20 @@
   ///
   /// At runtime, [value] will be evaluated before throwing an exception.
   Expression _makeInvalidWrite(Expression value) {
-    return _helper.wrapSyntheticExpression(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(fileOffset),
-            _plainNameForRead,
-            _forest.createArguments(noLocation, <Expression>[value]),
-            fileOffset,
-            isSetter: true),
-        fileOffset);
+    return _helper.throwNoSuchMethodError(
+        _forest.createNullLiteral(fileOffset),
+        _plainNameForRead,
+        _forest.createArguments(noLocation, <Expression>[value]),
+        fileOffset,
+        isSetter: true);
   }
 
-  /// Returns an [Expression] the reads this subexpression.
-  ///
-  /// The created read expression must support a simultaneous write of the same
-  /// expression with valid semantics.
-  ///
-  /// For instance in `a.b += c`, both a read and a write of the subexpression
-  /// `a.b` is created, but `a` must _not_ be evaluated twice. For this reason
-  /// [PropertyAccessGenerator] creates a synthetic local variable for `a` and
-  /// uses this for the both the [PropertyGet] and [PropertySet] of property
-  /// `b`.
-  ///
-  /// If [complexAssignment] is provided, the created expression is registered
-  /// as the `read` of the complex assignment.
-  ///
-  /// The default implementation creates the expression through
-  /// [_makeInvalidRead]. Subclasses with valid read operations must override
-  /// this method with a valid implementation.
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    Expression read = _makeInvalidRead();
-    if (complexAssignment != null) {
-      read = _helper.desugarSyntheticExpression(read);
-      complexAssignment.read = read;
-    }
-    return read;
-  }
-
-  /// Returns an [Expression] the write [value] to this subexpression.
-  ///
-  /// The created read expression must support a simultaneous read of the same
-  /// expression with valid semantics.
-  ///
-  /// For instance in `a.b += c`, both a read and a write of the subexpression
-  /// `a.b` is created, but `a` must _not_ be evaluated twice. For this reason
-  /// [PropertyAccessGenerator] creates a synthetic local variable for `a` and
-  /// uses this for the both the [PropertyGet] and [PropertySet] of property
-  /// `b`.
-  ///
-  /// If [complexAssignment] is provided, the created expression is registered
-  /// as the `write` of the complex assignment.
-  ///
-  /// The default implementation creates the expression through
-  /// [_makeInvalidWrite]. Subclasses with valid write operations must override
-  /// this method with a valid implementation.
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    Expression write = _makeInvalidWrite(value);
-    if (complexAssignment != null) {
-      write = _helper.desugarSyntheticExpression(write);
-      complexAssignment.write = write;
-    }
-    return write;
-  }
-
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    if (complexAssignment != null) {
-      complexAssignment.desugared = body;
-      return complexAssignment;
-    } else {
-      return body;
-    }
-  }
-
-  /// Creates a data structure for tracking the desugaring of a complex
-  /// assignment expression whose right hand side is [rhs].
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapIllegalAssignment(rhs);
-
   Expression buildForEffect() => buildSimpleRead();
 
   Initializer buildFieldInitializer(Map<String, int> initializedFields) {
     return _helper.buildInvalidInitializer(
-        _helper.desugarSyntheticExpression(_helper.buildProblem(
-            messageInvalidInitializer, fileOffset, lengthForToken(token))),
+        _helper.buildProblem(
+            messageInvalidInitializer, fileOffset, lengthForToken(token)),
         fileOffset);
   }
 
@@ -430,16 +275,12 @@
       _forest.argumentsSetTypeArguments(
           arguments, _helper.buildDartTypeArguments(typeArguments));
     }
-    return _helper.wrapInvalidConstructorInvocation(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(fileOffset),
-            _helper.constructorNameForDiagnostics(name,
-                className: _plainNameForRead),
-            arguments,
-            nameToken.charOffset),
-        null,
+    return _helper.throwNoSuchMethodError(
+        _forest.createNullLiteral(fileOffset),
+        _helper.constructorNameForDiagnostics(name,
+            className: _plainNameForRead),
         arguments,
-        fileOffset);
+        nameToken.charOffset);
   }
 
   void printOn(StringSink sink);
@@ -496,17 +337,6 @@
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    TypePromotionFact fact = _helper.typePromoter
-        ?.getFactForAccess(variable, _helper.functionNestingLevel);
-    TypePromotionScope scope = _helper.typePromoter?.currentScope;
-    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);
   }
@@ -523,6 +353,16 @@
     return write;
   }
 
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    Expression read = _createRead();
+    Expression write = _createWrite(fileOffset, value);
+    return new IfNullSet(read, write, forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  @override
   Expression buildCompoundAssignment(Name binaryOperator, Expression value,
       {int offset: TreeNode.noOffset,
       bool voidContext: false,
@@ -566,25 +406,6 @@
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    _helper.typePromoter
-        ?.mutateVariable(variable, _helper.functionNestingLevel);
-    Expression write;
-    if (variable.isFinal || variable.isConst) {
-      write = _makeInvalidWrite(value);
-      if (complexAssignment != null) {
-        write = _helper.desugarSyntheticExpression(write);
-        complexAssignment.write = write;
-      }
-    } else {
-      write = new VariableSet(variable, value)..fileOffset = fileOffset;
-      complexAssignment?.write = write;
-    }
-    return write;
-  }
-
-  @override
   Expression doInvocation(int offset, Arguments arguments) {
     return _helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
         adjustForImplicitCall(_plainNameForRead, offset),
@@ -592,12 +413,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) {
-    return SyntheticWrapper.wrapVariableAssignment(rhs)
-      ..fileOffset = fileOffset;
-  }
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", variable: ");
@@ -660,10 +475,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapPropertyAssignment(receiver, rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", _receiverVariable: ");
@@ -679,14 +490,14 @@
   }
 
   @override
-  Expression _makeSimpleRead() {
+  Expression buildSimpleRead() {
     return new PropertyGet(receiver, name, getter)..fileOffset = fileOffset;
   }
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    return new PropertySet(receiver, name, value, setter)
-      ..fileOffset = fileOffset;
+    return _helper.forest.createPropertySet(fileOffset, receiver, name, value,
+        interfaceTarget: setter, forEffect: voidContext);
   }
 
   @override
@@ -697,9 +508,9 @@
     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;
+    PropertySet write = _helper.forest.createPropertySet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name, value,
+        forEffect: voidContext);
     return new IfNullPropertySet(variable, read, write, forEffect: voidContext)
       ..fileOffset = offset;
   }
@@ -721,9 +532,9 @@
         binaryOperator,
         _helper.forest.createArguments(offset, <Expression>[value]),
         interfaceTarget: interfaceTarget);
-    PropertySet write = new PropertySet(
-        _helper.createVariableGet(variable, receiver.fileOffset), name, binary)
-      ..fileOffset = fileOffset;
+    PropertySet write = _helper.forest.createPropertySet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name, binary,
+        forEffect: voidContext);
     return new CompoundPropertySet(variable, write)..fileOffset = offset;
   }
 
@@ -756,46 +567,15 @@
     VariableDeclaration write = _helper.forest
         .createVariableDeclarationForValue(
             offset,
-            new PropertySet(
+            _helper.forest.createPropertySet(
+                fileOffset,
                 _helper.createVariableGet(variable, receiver.fileOffset),
                 name,
-                binary)
-              ..fileOffset = fileOffset);
+                binary,
+                forEffect: true));
     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)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    PropertyGet read = new PropertyGet(receiverAccess(), name, getter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
-  }
-
-  @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    PropertySet write = new PropertySet(receiverAccess(), name, value, setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    return super._finish(makeLet(_receiverVariable, body), complexAssignment);
-  }
-
   /// Creates a [Generator] for the access of property [name] on [receiver].
   static Generator make(
       ExpressionGeneratorHelper helper,
@@ -884,81 +664,91 @@
   }
 
   Expression _createRead() {
-    if (getter == null) {
-      _helper.warnUnresolvedGet(name, fileOffset);
-    }
-    return new PropertyGet(_forest.createThisExpression(token), name, getter)
+    return new PropertyGet(
+        _forest.createThisExpression(fileOffset), name, getter)
       ..fileOffset = fileOffset;
   }
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    return _createWrite(fileOffset, value);
+    return _createWrite(fileOffset, value, forEffect: voidContext);
   }
 
-  Expression _createWrite(int offset, Expression value) {
-    if (setter == null) {
-      _helper.warnUnresolvedSet(name, fileOffset);
-    }
-    return new PropertySet(
-        _forest.createThisExpression(token), name, value, setter)
-      ..fileOffset = fileOffset;
+  Expression _createWrite(int offset, Expression value, {bool forEffect}) {
+    return _helper.forest.createPropertySet(
+        fileOffset, _forest.createThisExpression(fileOffset), name, value,
+        interfaceTarget: setter, forEffect: forEffect);
   }
 
   @override
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
-    return new IfNullSet(_createRead(), _createWrite(offset, value),
+    return new IfNullSet(
+        _createRead(), _createWrite(offset, value, forEffect: voidContext),
         forEffect: voidContext)
       ..fileOffset = offset;
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    if (getter == null) {
-      _helper.warnUnresolvedGet(name, fileOffset);
-    }
-    PropertyGet read =
-        new PropertyGet(_forest.createThisExpression(token), name, getter)
-          ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
+  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,
+        new PropertyGet(_forest.createThisExpression(fileOffset), name)
+          ..fileOffset = fileOffset,
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _createWrite(fileOffset, binary, forEffect: voidContext);
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (setter == null) {
-      _helper.warnUnresolvedSet(name, fileOffset);
+  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);
     }
-    PropertySet write = new PropertySet(
-        _forest.createThisExpression(token), name, value, setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
+    VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
+        fileOffset,
+        new PropertyGet(_forest.createThisExpression(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, _createWrite(fileOffset, binary, forEffect: true));
+    return new PropertyPostIncDec.onReadOnly(read, write)..fileOffset = offset;
   }
 
   @override
   Expression doInvocation(int offset, Arguments arguments) {
     Member interfaceTarget = getter;
-    if (interfaceTarget == null) {
-      _helper.warnUnresolvedMethod(name, offset);
-    }
     if (interfaceTarget is Field) {
       // TODO(ahe): In strong mode we should probably rewrite this to
       // `this.name.call(arguments)`.
       interfaceTarget = null;
     }
     return _helper.buildMethodInvocation(
-        _forest.createThisExpression(null), name, arguments, offset,
+        _forest.createThisExpression(fileOffset), name, arguments, offset,
         interfaceTarget: interfaceTarget);
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapPropertyAssignment(null, rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", name: ");
@@ -1020,51 +810,52 @@
     VariableDeclaration variable = _helper.forest
         .createVariableDeclarationForValue(
             receiverExpression.fileOffset, receiverExpression);
-    PropertySet read = new PropertySet(
+    PropertySet read = _helper.forest.createPropertySet(
+        fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset),
         name,
-        value)
-      ..fileOffset = fileOffset;
+        value,
+        forEffect: voidContext,
+        readOnlyReceiver: true);
     return new NullAwarePropertySet(variable, read)
       ..fileOffset = receiverExpression.fileOffset;
   }
 
-  @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    PropertyGet read = new PropertyGet(receiverAccess(), name, getter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new NullAwareIfNullSet(receiverExpression, name, value,
+        forEffect: voidContext,
+        readOffset: fileOffset,
+        testOffset: offset,
+        writeOffset: fileOffset)
+      ..fileOffset = offset;
   }
 
-  @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    PropertySet write = new PropertySet(receiverAccess(), name, value, setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return new NullAwareCompoundSet(
+        receiverExpression, name, binaryOperator, value,
+        readOffset: fileOffset,
+        binaryOffset: offset,
+        writeOffset: fileOffset,
+        forEffect: voidContext,
+        forPostIncDec: isPostIncDec);
   }
 
-  @override
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    Expression nullAwareGuard = _forest.createConditionalExpression(
-        buildIsNull(receiverAccess(), fileOffset, _helper),
-        null,
-        _forest.createNullLiteral(null)..fileOffset = fileOffset,
-        null,
-        body)
-      ..fileOffset = fileOffset;
-    if (complexAssignment != null) {
-      body = makeLet(receiver, nullAwareGuard);
-      PropertyAssignmentJudgment kernelPropertyAssign = complexAssignment;
-      kernelPropertyAssign.nullAwareGuard = nullAwareGuard;
-      kernelPropertyAssign.desugared = body;
-      return kernelPropertyAssign;
-    } else {
-      return unhandled('${runtimeType}', "_finish", fileOffset, _uri);
-    }
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
+    return buildCompoundAssignment(
+        binaryOperator, _forest.createIntLiteral(1, null)..fileOffset = offset,
+        offset: offset,
+        voidContext: voidContext,
+        interfaceTarget: interfaceTarget,
+        isPostIncDec: true);
   }
 
   @override
@@ -1073,10 +864,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapPropertyAssignment(receiverExpression, rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", receiver: ");
@@ -1124,18 +911,6 @@
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    if (getter == null) {
-      _helper.warnUnresolvedGet(name, fileOffset, isSuper: true);
-    }
-    // TODO(ahe): Use [DirectPropertyGet] when possible.
-    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);
   }
@@ -1201,19 +976,6 @@
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (setter == null) {
-      _helper.warnUnresolvedSet(name, fileOffset, isSuper: true);
-    }
-    // TODO(ahe): Use [DirectPropertySet] when possible.
-    SuperPropertySet write = new SuperPropertySet(name, value, setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
   Expression doInvocation(int offset, Arguments arguments) {
     if (_helper.constantContext != ConstantContext.none) {
       // TODO(brianwilkerson) Fix the length
@@ -1234,10 +996,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapPropertyAssignment(null, rhs, isSuper: true);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", name: ");
@@ -1258,10 +1016,6 @@
 
   final Procedure setter;
 
-  VariableDeclaration receiverVariable;
-
-  VariableDeclaration indexVariable;
-
   IndexedAccessGenerator(ExpressionGeneratorHelper helper, Token token,
       this.receiver, this.index, this.getter, this.setter)
       : super(helper, token);
@@ -1276,7 +1030,7 @@
   Expression buildSimpleRead() {
     return _helper.buildMethodInvocation(
         receiver,
-        new Name('[]'),
+        indexGetName,
         _helper.forest.createArguments(fileOffset, <Expression>[index]),
         fileOffset,
         interfaceTarget: getter);
@@ -1287,7 +1041,7 @@
     if (voidContext) {
       return _helper.buildMethodInvocation(
           receiver,
-          new Name('[]='),
+          indexSetName,
           _helper.forest
               .createArguments(fileOffset, <Expression>[index, value]),
           fileOffset,
@@ -1300,7 +1054,10 @@
   @override
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
-    return new IfNullIndexSet(receiver, index, value, fileOffset,
+    return new IfNullIndexSet(receiver, index, value,
+        readOffset: fileOffset,
+        testOffset: offset,
+        writeOffset: fileOffset,
         forEffect: voidContext)
       ..fileOffset = offset;
   }
@@ -1332,97 +1089,6 @@
         isPostIncDec: true);
   }
 
-  Expression indexAccess() {
-    indexVariable ??= new VariableDeclaration.forValue(index);
-    return new VariableGet(indexVariable)..fileOffset = fileOffset;
-  }
-
-  Expression receiverAccess() {
-    // We cannot reuse the receiver if it is a variable since it might be
-    // reassigned in the index expression.
-    receiverVariable ??= new VariableDeclaration.forValue(receiver);
-    return new VariableGet(receiverVariable)..fileOffset = fileOffset;
-  }
-
-  @override
-  Expression _makeSimpleRead() {
-    MethodInvocationImpl read = new MethodInvocationImpl(receiver, indexGetName,
-        _forest.createArguments(fileOffset, <Expression>[index]),
-        interfaceTarget: getter)
-      ..fileOffset = fileOffset;
-    return read;
-  }
-
-  @override
-  Expression _makeSimpleWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        receiver,
-        indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[index, value]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    MethodInvocationImpl read = new MethodInvocationImpl(
-        receiverAccess(),
-        indexGetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess()]),
-        interfaceTarget: getter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
-  }
-
-  @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        receiverAccess(),
-        indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess(), value]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  // TODO(dmitryas): remove this method after the "[]=" operator of the Context
-  // class is made to return a value.
-  Expression _makeWriteAndReturn(
-      Expression value, ComplexAssignmentJudgment complexAssignment) {
-    // 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);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        receiverAccess(),
-        indexSetName,
-        _forest.createArguments(fileOffset,
-            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    VariableDeclarationImpl dummy = new VariableDeclarationImpl.forValue(write);
-    return makeLet(
-        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
-  }
-
-  @override
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    return super._finish(
-        makeLet(receiverVariable,
-            makeLet(indexVariable, body)..fileOffset = fileOffset)
-          ..fileOffset = fileOffset,
-        complexAssignment);
-  }
-
   @override
   Expression doInvocation(int offset, Arguments arguments) {
     return _helper.buildMethodInvocation(
@@ -1431,10 +1097,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapIndexAssignment(receiver, index, rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", receiver: ");
@@ -1445,10 +1107,6 @@
     printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
     sink.write(", setter: ");
     printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
-    sink.write(", receiverVariable: ");
-    printNodeOn(receiverVariable, sink, syntheticNames: syntheticNames);
-    sink.write(", indexVariable: ");
-    printNodeOn(indexVariable, sink, syntheticNames: syntheticNames);
   }
 
   static Generator make(
@@ -1477,8 +1135,6 @@
 
   final Procedure setter;
 
-  VariableDeclaration indexVariable;
-
   ThisIndexedAccessGenerator(ExpressionGeneratorHelper helper, Token token,
       this.index, this.getter, this.setter)
       : super(helper, token);
@@ -1489,79 +1145,73 @@
   @override
   String get _debugName => "ThisIndexedAccessGenerator";
 
-  Expression indexAccess() {
-    indexVariable ??= new VariableDeclaration.forValue(index);
-    return new VariableGet(indexVariable);
-  }
-
-  Expression _makeWriteAndReturn(
-      Expression value, ComplexAssignmentJudgment complexAssignment) {
-    VariableDeclaration valueVariable = new VariableDeclaration.forValue(value);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        _forest.createThisExpression(token),
-        indexSetName,
-        _forest.createArguments(fileOffset,
-            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    VariableDeclaration dummy = new VariableDeclaration.forValue(write);
-    return makeLet(
-        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
-  }
-
   @override
-  Expression _makeSimpleRead() {
-    return new MethodInvocationImpl(_forest.createThisExpression(token),
-        indexGetName, _forest.createArguments(fileOffset, <Expression>[index]),
-        interfaceTarget: getter)
-      ..fileOffset = fileOffset;
-  }
-
-  @override
-  Expression _makeSimpleWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        _forest.createThisExpression(token),
-        indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[index, value]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    MethodInvocationImpl read = new MethodInvocationImpl(
-        _forest.createThisExpression(token),
+  Expression buildSimpleRead() {
+    Expression receiver = _helper.forest.createThisExpression(fileOffset);
+    return _helper.buildMethodInvocation(
+        receiver,
         indexGetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess()]),
-        interfaceTarget: getter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
+        _helper.forest.createArguments(fileOffset, <Expression>[index]),
+        fileOffset,
+        interfaceTarget: getter);
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationImpl write = new MethodInvocationImpl(
-        _forest.createThisExpression(token),
-        indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess(), value]),
-        interfaceTarget: setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    Expression receiver = _helper.forest.createThisExpression(fileOffset);
+    if (voidContext) {
+      return _helper.buildMethodInvocation(
+          receiver,
+          indexSetName,
+          _helper.forest
+              .createArguments(fileOffset, <Expression>[index, value]),
+          fileOffset,
+          interfaceTarget: setter);
+    } else {
+      return new IndexSet(receiver, index, value)..fileOffset = fileOffset;
+    }
   }
 
   @override
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    return super._finish(makeLet(indexVariable, body), complexAssignment);
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    Expression receiver = _helper.forest.createThisExpression(fileOffset);
+    return new IfNullIndexSet(receiver, index, value,
+        readOffset: fileOffset,
+        testOffset: offset,
+        writeOffset: fileOffset,
+        forEffect: voidContext,
+        readOnlyReceiver: true)
+      ..fileOffset = offset;
+  }
+
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    Expression receiver = _helper.forest.createThisExpression(fileOffset);
+    return new CompoundIndexSet(receiver, index, binaryOperator, value,
+        readOffset: fileOffset,
+        binaryOffset: offset,
+        writeOffset: fileOffset,
+        forEffect: voidContext,
+        forPostIncDec: isPostIncDec,
+        readOnlyReceiver: true);
+  }
+
+  @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);
   }
 
   @override
@@ -1572,10 +1222,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapIndexAssignment(null, index, rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", index: ");
@@ -1584,8 +1230,6 @@
     printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
     sink.write(", setter: ");
     printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
-    sink.write(", indexVariable: ");
-    printNodeOn(indexVariable, sink, syntheticNames: syntheticNames);
   }
 }
 
@@ -1596,8 +1240,6 @@
 
   final Member setter;
 
-  VariableDeclaration indexVariable;
-
   SuperIndexedAccessGenerator(ExpressionGeneratorHelper helper, Token token,
       this.index, this.getter, this.setter)
       : super(helper, token);
@@ -1606,89 +1248,72 @@
 
   String get _debugName => "SuperIndexedAccessGenerator";
 
-  Expression indexAccess() {
-    indexVariable ??= new VariableDeclaration.forValue(index);
-    return new VariableGet(indexVariable);
-  }
-
-  Expression _makeWriteAndReturn(
-      Expression value, ComplexAssignmentJudgment complexAssignment) {
-    VariableDeclaration valueVariable = new VariableDeclaration.forValue(value);
-    if (setter == null) {
-      _helper.warnUnresolvedMethod(indexSetName, fileOffset, isSuper: true);
-    }
-    SuperMethodInvocation write = new SuperMethodInvocation(
-        indexSetName,
-        _forest.createArguments(fileOffset,
-            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
-        setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    VariableDeclaration dummy = new VariableDeclaration.forValue(write);
-    return makeLet(
-        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
-  }
-
   @override
-  Expression _makeSimpleRead() {
+  Expression buildSimpleRead() {
     if (getter == null) {
       _helper.warnUnresolvedMethod(indexGetName, fileOffset, isSuper: true);
     }
-    // TODO(ahe): Use [DirectMethodInvocation] when possible.
-    return new SuperMethodInvocation(indexGetName,
-        _forest.createArguments(fileOffset, <Expression>[index]), getter)
-      ..fileOffset = fileOffset;
-  }
-
-  @override
-  Expression _makeSimpleWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    if (setter == null) {
-      _helper.warnUnresolvedMethod(indexSetName, fileOffset, isSuper: true);
-    }
-    SuperMethodInvocation write = new SuperMethodInvocation(indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[index, value]), setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
-  }
-
-  @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    if (getter == null) {
-      _helper.warnUnresolvedMethod(indexGetName, fileOffset, isSuper: true);
-    }
-    SuperMethodInvocation read = new SuperMethodInvocation(
+    return _helper.forest.createSuperMethodInvocation(
+        fileOffset,
         indexGetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess()]),
-        getter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
-    return read;
+        getter,
+        _helper.forest.createArguments(fileOffset, <Expression>[index]));
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    if (setter == null) {
-      _helper.warnUnresolvedMethod(indexSetName, fileOffset, isSuper: true);
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    if (voidContext) {
+      if (setter == null) {
+        _helper.warnUnresolvedMethod(indexSetName, fileOffset, isSuper: true);
+      }
+      return _helper.forest.createSuperMethodInvocation(
+          fileOffset,
+          indexSetName,
+          setter,
+          _helper.forest
+              .createArguments(fileOffset, <Expression>[index, value]));
+    } else {
+      return new SuperIndexSet(setter, index, value)..fileOffset = fileOffset;
     }
-    SuperMethodInvocation write = new SuperMethodInvocation(
-        indexSetName,
-        _forest.createArguments(fileOffset, <Expression>[indexAccess(), value]),
-        setter)
-      ..fileOffset = fileOffset;
-    complexAssignment?.write = write;
-    return write;
   }
 
   @override
-  Expression _finish(
-      Expression body, ComplexAssignmentJudgment complexAssignment) {
-    return super._finish(makeLet(indexVariable, body)..fileOffset = fileOffset,
-        complexAssignment);
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullSuperIndexSet(getter, setter, index, value,
+        readOffset: fileOffset,
+        testOffset: offset,
+        writeOffset: 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 CompoundSuperIndexSet(
+        getter, setter, 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);
   }
 
   @override
@@ -1699,10 +1324,6 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapIndexAssignment(null, index, rhs, isSuper: true);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", index: ");
@@ -1711,8 +1332,6 @@
     printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
     sink.write(", setter: ");
     printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
-    sink.write(", indexVariable: ");
-    printNodeOn(indexVariable, sink, syntheticNames: syntheticNames);
   }
 }
 
@@ -1749,6 +1368,9 @@
 ///   }
 ///
 class StaticAccessGenerator extends Generator {
+  /// The name of the original target;
+  final String targetName;
+
   /// The static [Member] used for performing a read or invocation on this
   /// subexpression.
   ///
@@ -1765,12 +1387,17 @@
   final Member writeTarget;
 
   StaticAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.readTarget, this.writeTarget)
-      : assert(readTarget != null || writeTarget != null),
+      this.targetName, this.readTarget, this.writeTarget)
+      : assert(targetName != null),
+        assert(readTarget != null || writeTarget != null),
         super(helper, token);
 
-  factory StaticAccessGenerator.fromBuilder(ExpressionGeneratorHelper helper,
-      Builder declaration, Token token, Builder builderSetter) {
+  factory StaticAccessGenerator.fromBuilder(
+      ExpressionGeneratorHelper helper,
+      String targetName,
+      Builder declaration,
+      Token token,
+      Builder builderSetter) {
     if (declaration is AccessErrorBuilder) {
       AccessErrorBuilder error = declaration;
       declaration = error.builder;
@@ -1791,14 +1418,14 @@
         setter = builderSetter.target;
       }
     }
-    return new StaticAccessGenerator(helper, token, getter, setter);
+    return new StaticAccessGenerator(helper, token, targetName, getter, setter);
   }
 
   @override
   String get _debugName => "StaticAccessGenerator";
 
   @override
-  String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
+  String get _plainNameForRead => targetName;
 
   @override
   Expression buildSimpleRead() {
@@ -1882,38 +1509,6 @@
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    Expression read;
-    if (readTarget == null) {
-      read = _makeInvalidRead();
-      if (complexAssignment != null) {
-        read = _helper.desugarSyntheticExpression(read);
-      }
-    } else {
-      read = _helper.makeStaticGet(readTarget, token);
-    }
-    complexAssignment?.read = read;
-    return read;
-  }
-
-  @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
-    Expression write;
-    if (writeTarget == null) {
-      write = _makeInvalidWrite(value);
-      if (complexAssignment != null) {
-        write = _helper.desugarSyntheticExpression(write);
-      }
-    } else {
-      write = new StaticSet(writeTarget, value);
-    }
-    complexAssignment?.write = write;
-    write.fileOffset = fileOffset;
-    return write;
-  }
-
-  @override
   Expression doInvocation(int offset, Arguments arguments) {
     if (_helper.constantContext != ConstantContext.none &&
         !_helper.isIdentical(readTarget)) {
@@ -1936,12 +1531,10 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapStaticAssignment(rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
+    sink.write(", targetName: ");
+    sink.write(targetName);
     sink.write(", readTarget: ");
     printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
     sink.write(", writeTarget: ");
@@ -1968,6 +1561,9 @@
 ///
 /// These can only occur within an extension instance member.
 class ExtensionInstanceAccessGenerator extends Generator {
+  /// The original name of the target.
+  final String targetName;
+
   /// The static [Member] generated for an instance extension member which is
   /// used for performing a read on this subexpression.
   ///
@@ -2004,17 +1600,20 @@
   ExtensionInstanceAccessGenerator(
       ExpressionGeneratorHelper helper,
       Token token,
+      this.targetName,
       this.readTarget,
       this.invokeTarget,
       this.writeTarget,
       this.extensionThis,
       this.extensionTypeParameters)
-      : assert(readTarget != null || writeTarget != null),
+      : assert(targetName != null),
+        assert(readTarget != null || writeTarget != null),
         assert(extensionThis != null),
         super(helper, token);
 
   factory ExtensionInstanceAccessGenerator.fromBuilder(
       ExpressionGeneratorHelper helper,
+      String targetName,
       VariableDeclaration extensionThis,
       List<TypeParameter> extensionTypeParameters,
       Builder declaration,
@@ -2046,15 +1645,22 @@
     if (builderSetter != null && builderSetter.isSetter) {
       writeTarget = builderSetter.target;
     }
-    return new ExtensionInstanceAccessGenerator(helper, token, readTarget,
-        invokeTarget, writeTarget, extensionThis, extensionTypeParameters);
+    return new ExtensionInstanceAccessGenerator(
+        helper,
+        token,
+        targetName,
+        readTarget,
+        invokeTarget,
+        writeTarget,
+        extensionThis,
+        extensionTypeParameters);
   }
 
   @override
   String get _debugName => "InstanceExtensionAccessGenerator";
 
   @override
-  String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
+  String get _plainNameForRead => targetName;
 
   int get _extensionTypeParameterCount => extensionTypeParameters?.length ?? 0;
 
@@ -2071,13 +1677,14 @@
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
+  Expression buildSimpleRead() {
+    return _createRead();
+  }
+
+  Expression _createRead() {
     Expression read;
     if (readTarget == null) {
       read = _makeInvalidRead();
-      if (complexAssignment != null) {
-        read = _helper.desugarSyntheticExpression(read);
-      }
     } else {
       read = _helper.buildExtensionMethodInvocation(
           fileOffset,
@@ -2089,37 +1696,84 @@
               _helper.createVariableGet(extensionThis, fileOffset),
               extensionTypeArguments: _createExtensionTypeArguments()));
     }
-    complexAssignment?.read = read;
     return read;
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _createWrite(fileOffset, value, forEffect: voidContext);
+  }
+
+  Expression _createWrite(int offset, Expression value, {bool forEffect}) {
     Expression write;
     if (writeTarget == null) {
       write = _makeInvalidWrite(value);
-      if (complexAssignment != null) {
-        write = _helper.desugarSyntheticExpression(write);
-      }
     } else {
-      write = _helper.buildExtensionMethodInvocation(
-          fileOffset,
-          writeTarget,
-          _helper.forest.createArgumentsForExtensionMethod(
-              fileOffset,
-              _extensionTypeParameterCount,
-              0,
-              _helper.createVariableGet(extensionThis, fileOffset),
-              extensionTypeArguments: _createExtensionTypeArguments(),
-              positionalArguments: [value]));
+      write = new ExtensionSet(
+          _helper.createVariableGet(extensionThis, fileOffset),
+          new ExtensionAccessTarget(writeTarget, null, ProcedureKind.Setter,
+              _createExtensionTypeArguments()),
+          value,
+          forEffect: forEffect,
+          readOnlyReceiver: true);
     }
-    complexAssignment?.write = write;
-    write.fileOffset = fileOffset;
+    write.fileOffset = offset;
     return write;
   }
 
   @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullSet(
+        _createRead(), _createWrite(fileOffset, value, forEffect: voidContext),
+        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, forEffect: voidContext);
+  }
+
+  @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, forEffect: true));
+    return new PropertyPostIncDec.onReadOnly(read, write)..fileOffset = offset;
+  }
+
+  @override
   Expression doInvocation(int offset, Arguments arguments) {
     if (invokeTarget != null) {
       return _helper.buildExtensionMethodInvocation(
@@ -2143,12 +1797,10 @@
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapStaticAssignment(rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
+    sink.write(", targetName: ");
+    sink.write(targetName);
     sink.write(", readTarget: ");
     printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
     sink.write(", writeTarget: ");
@@ -2178,6 +1830,9 @@
 ///   }
 ///
 class ExplicitExtensionInstanceAccessGenerator extends Generator {
+  /// The name of the original target;
+  final String targetName;
+
   /// The static [Member] generated for an instance extension member which is
   /// used for performing a read on this subexpression.
   ///
@@ -2209,19 +1864,27 @@
   /// like `<int>` in `Extension<int>(a).method<String>()`.
   final List<DartType> explicitTypeArguments;
 
+  /// The number of type parameters declared on the extension declaration.
   final int extensionTypeParameterCount;
 
+  /// If `true` the access is null-aware, like `Extension(c)?.foo`.
+  final bool isNullAware;
+
   ExplicitExtensionInstanceAccessGenerator(
       ExpressionGeneratorHelper helper,
       Token token,
+      this.targetName,
       this.readTarget,
       this.invokeTarget,
       this.writeTarget,
       this.receiver,
       this.explicitTypeArguments,
-      this.extensionTypeParameterCount)
-      : assert(readTarget != null || writeTarget != null),
+      this.extensionTypeParameterCount,
+      {this.isNullAware})
+      : assert(targetName != null),
+        assert(readTarget != null || writeTarget != null),
         assert(receiver != null),
+        assert(isNullAware != null),
         super(helper, token);
 
   factory ExplicitExtensionInstanceAccessGenerator.fromBuilder(
@@ -2231,7 +1894,9 @@
       Builder setterBuilder,
       Expression receiver,
       List<DartType> explicitTypeArguments,
-      int extensionTypeParameterCount) {
+      int extensionTypeParameterCount,
+      {bool isNullAware}) {
+    String targetName;
     Procedure readTarget;
     Procedure invokeTarget;
     if (getterBuilder != null) {
@@ -2242,11 +1907,14 @@
         // when not explicitly looking for a setter.
         assert(getterBuilder.isSetter);
       } else if (getterBuilder.isGetter) {
-        readTarget = getterBuilder.target;
+        MemberBuilder memberBuilder = getterBuilder;
+        readTarget = memberBuilder.member;
+        targetName = memberBuilder.name;
       } else if (getterBuilder.isRegularMethod) {
         MemberBuilder procedureBuilder = getterBuilder;
         readTarget = procedureBuilder.extensionTearOff;
         invokeTarget = procedureBuilder.procedure;
+        targetName = procedureBuilder.name;
       } else {
         return unhandled(
             "${getterBuilder.runtimeType}",
@@ -2256,38 +1924,53 @@
       }
     }
     Procedure writeTarget;
-    if (setterBuilder != null && setterBuilder.isSetter) {
-      writeTarget = setterBuilder.target;
+    if (setterBuilder is AccessErrorBuilder) {
+      targetName ??= setterBuilder.name;
+    } else if (setterBuilder != null && setterBuilder.isSetter) {
+      MemberBuilder memberBuilder = setterBuilder;
+      writeTarget = memberBuilder.member;
+      targetName ??= memberBuilder.name;
     }
     return new ExplicitExtensionInstanceAccessGenerator(
         helper,
         token,
+        targetName,
         readTarget,
         invokeTarget,
         writeTarget,
         receiver,
         explicitTypeArguments,
-        extensionTypeParameterCount);
+        extensionTypeParameterCount,
+        isNullAware: isNullAware);
   }
 
   @override
   String get _debugName => "InstanceExtensionAccessGenerator";
 
   @override
-  String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
+  String get _plainNameForRead => targetName;
 
   List<DartType> _createExtensionTypeArguments() {
     return explicitTypeArguments ?? const <DartType>[];
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
+  Expression buildSimpleRead() {
+    if (isNullAware) {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      return new NullAwareExtension(variable,
+          _createRead(_helper.createVariableGet(variable, variable.fileOffset)))
+        ..fileOffset = fileOffset;
+    } else {
+      return _createRead(receiver);
+    }
+  }
+
+  Expression _createRead(Expression receiver) {
     Expression read;
     if (readTarget == null) {
       read = _makeInvalidRead();
-      if (complexAssignment != null) {
-        read = _helper.desugarSyntheticExpression(read);
-      }
     } else {
       read = _helper.buildExtensionMethodInvocation(
           fileOffset,
@@ -2296,37 +1979,190 @@
               fileOffset, extensionTypeParameterCount, 0, receiver,
               extensionTypeArguments: _createExtensionTypeArguments()));
     }
-    complexAssignment?.read = read;
     return read;
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    if (isNullAware) {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      return new NullAwareExtension(
+          variable,
+          _createWrite(fileOffset,
+              _helper.createVariableGet(variable, variable.fileOffset), value,
+              forEffect: voidContext, readOnlyReceiver: true))
+        ..fileOffset = fileOffset;
+    } else {
+      return _createWrite(fileOffset, receiver, value,
+          forEffect: voidContext, readOnlyReceiver: false);
+    }
+  }
+
+  Expression _createWrite(int offset, Expression receiver, Expression value,
+      {bool readOnlyReceiver, bool forEffect}) {
     Expression write;
     if (writeTarget == null) {
       write = _makeInvalidWrite(value);
-      if (complexAssignment != null) {
-        write = _helper.desugarSyntheticExpression(write);
-      }
     } else {
-      write = _helper.buildExtensionMethodInvocation(
-          fileOffset,
-          writeTarget,
-          _helper.forest.createArgumentsForExtensionMethod(
-              fileOffset, extensionTypeParameterCount, 0, receiver,
-              extensionTypeArguments: _createExtensionTypeArguments(),
-              positionalArguments: [value]));
+      write = new ExtensionSet(
+          receiver,
+          new ExtensionAccessTarget(writeTarget, null, ProcedureKind.Setter,
+              _createExtensionTypeArguments()),
+          value,
+          readOnlyReceiver: readOnlyReceiver,
+          forEffect: forEffect);
     }
-    complexAssignment?.write = write;
-    write.fileOffset = fileOffset;
+    write.fileOffset = offset;
     return write;
   }
 
   @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    if (isNullAware) {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      Expression read =
+          _createRead(_helper.createVariableGet(variable, receiver.fileOffset));
+      Expression write = _createWrite(fileOffset,
+          _helper.createVariableGet(variable, receiver.fileOffset), value,
+          forEffect: voidContext, readOnlyReceiver: true);
+      return new NullAwareExtension(
+          variable,
+          new IfNullSet(read, write, forEffect: voidContext)
+            ..fileOffset = offset)
+        ..fileOffset = fileOffset;
+    } else {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      Expression read =
+          _createRead(_helper.createVariableGet(variable, receiver.fileOffset));
+      Expression write = _createWrite(fileOffset,
+          _helper.createVariableGet(variable, receiver.fileOffset), value,
+          forEffect: voidContext, readOnlyReceiver: true);
+      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}) {
+    if (isNullAware) {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      MethodInvocation binary = _helper.forest.createMethodInvocation(
+          offset,
+          _createRead(_helper.createVariableGet(variable, receiver.fileOffset)),
+          binaryOperator,
+          _helper.forest.createArguments(offset, <Expression>[value]),
+          interfaceTarget: interfaceTarget);
+      Expression write = _createWrite(fileOffset,
+          _helper.createVariableGet(variable, receiver.fileOffset), binary,
+          forEffect: voidContext, readOnlyReceiver: true);
+      return new NullAwareExtension(variable, write)..fileOffset = offset;
+    } else {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      MethodInvocation binary = _helper.forest.createMethodInvocation(
+          offset,
+          _createRead(_helper.createVariableGet(variable, receiver.fileOffset)),
+          binaryOperator,
+          _helper.forest.createArguments(offset, <Expression>[value]),
+          interfaceTarget: interfaceTarget);
+      Expression write = _createWrite(fileOffset,
+          _helper.createVariableGet(variable, receiver.fileOffset), binary,
+          forEffect: voidContext, readOnlyReceiver: true);
+      return new CompoundPropertySet(variable, write)..fileOffset = offset;
+    }
+  }
+
+  @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);
+    } else if (isNullAware) {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      VariableDeclaration read = _helper.forest
+          .createVariableDeclarationForValue(
+              fileOffset,
+              _createRead(
+                  _helper.createVariableGet(variable, receiver.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,
+              _createWrite(
+                  fileOffset,
+                  _helper.createVariableGet(variable, receiver.fileOffset),
+                  binary,
+                  forEffect: voidContext,
+                  readOnlyReceiver: true)
+                ..fileOffset = fileOffset);
+      return new NullAwareExtension(
+          variable, new LocalPostIncDec(read, write)..fileOffset = offset)
+        ..fileOffset = fileOffset;
+    } else {
+      VariableDeclaration variable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      VariableDeclaration read = _helper.forest
+          .createVariableDeclarationForValue(
+              fileOffset,
+              _createRead(
+                  _helper.createVariableGet(variable, receiver.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,
+              _createWrite(
+                  fileOffset,
+                  _helper.createVariableGet(variable, receiver.fileOffset),
+                  binary,
+                  forEffect: voidContext,
+                  readOnlyReceiver: true)
+                ..fileOffset = fileOffset);
+      return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
+    }
+  }
+
+  @override
   Expression doInvocation(int offset, Arguments arguments) {
+    VariableDeclaration receiverVariable;
+    Expression receiverExpression = receiver;
+    if (isNullAware) {
+      receiverVariable = _helper.forest
+          .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+      receiverExpression = _helper.createVariableGet(
+          receiverVariable, receiverVariable.fileOffset);
+    }
+    Expression invocation;
     if (invokeTarget != null) {
-      return _helper.buildExtensionMethodInvocation(
+      invocation = _helper.buildExtensionMethodInvocation(
           fileOffset,
           invokeTarget,
           _forest.createArgumentsForExtensionMethod(
@@ -2334,25 +2170,33 @@
               extensionTypeParameterCount,
               invokeTarget.function.typeParameters.length -
                   extensionTypeParameterCount,
-              receiver,
+              receiverExpression,
               extensionTypeArguments: _createExtensionTypeArguments(),
               typeArguments: arguments.types,
               positionalArguments: arguments.positional,
               namedArguments: arguments.named));
     } else {
-      return _helper.buildMethodInvocation(buildSimpleRead(), callName,
-          arguments, adjustForImplicitCall(_plainNameForRead, offset),
+      invocation = _helper.buildMethodInvocation(
+          _createRead(receiverExpression),
+          callName,
+          arguments,
+          adjustForImplicitCall(_plainNameForRead, offset),
           isImplicitCall: true);
     }
+    if (isNullAware) {
+      assert(receiverVariable != null);
+      return new NullAwareExtension(receiverVariable, invocation)
+        ..fileOffset = fileOffset;
+    } else {
+      return invocation;
+    }
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapStaticAssignment(rhs);
-
-  @override
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
+    sink.write(", targetName: ");
+    sink.write(targetName);
     sink.write(", readTarget: ");
     printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
     sink.write(", writeTarget: ");
@@ -2405,6 +2249,38 @@
   @override
   String get _debugName => "ExplicitExtensionAccessGenerator";
 
+  @override
+  Expression buildSimpleRead() {
+    return _makeInvalidRead();
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return _makeInvalidRead();
+  }
+
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return _makeInvalidRead();
+  }
+
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
+    return _makeInvalidRead();
+  }
+
   /* Expression | Generator */ buildPropertyAccess(
       IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
     if (_helper.constantContext != ConstantContext.none) {
@@ -2425,7 +2301,8 @@
             setter,
             receiver,
             explicitTypeArguments,
-            extensionBuilder.typeParameters?.length ?? 0);
+            extensionBuilder.typeParameters?.length ?? 0,
+            isNullAware: isNullAware);
     if (send.arguments != null) {
       return generator.doInvocation(offsetForToken(send.token), send.arguments);
     } else {
@@ -2440,6 +2317,18 @@
   }
 
   @override
+  Expression _makeInvalidRead() {
+    return _helper.buildProblem(messageExplicitExtensionAsExpression,
+        fileOffset, lengthForToken(token));
+  }
+
+  @override
+  Expression _makeInvalidWrite(Expression value) {
+    return _helper.buildProblem(
+        messageExplicitExtensionAsLvalue, fileOffset, lengthForToken(token));
+  }
+
+  @override
   void printOn(StringSink sink) {
     sink.write(", extensionBuilder: ");
     sink.write(extensionBuilder);
@@ -2462,16 +2351,58 @@
   String get _debugName => "LoadLibraryGenerator";
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
+  Expression buildSimpleRead() {
     builder.importDependency.targetLibrary;
     LoadLibraryTearOff read = new LoadLibraryTearOff(
         builder.importDependency, builder.createTearoffMethod(_helper.forest))
       ..fileOffset = fileOffset;
-    complexAssignment?.read = read;
     return read;
   }
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    Expression read = buildSimpleRead();
+    Expression write = _makeInvalidWrite(value);
+    return new IfNullSet(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}) {
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        buildSimpleRead(),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _makeInvalidWrite(binary);
+  }
+
+  @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);
+  }
+
+  @override
   Expression doInvocation(int offset, Arguments arguments) {
     if (_forest.argumentsPositional(arguments).length > 0 ||
         _forest.argumentsNamed(arguments).length > 0) {
@@ -2498,31 +2429,60 @@
       : super(helper, token);
 
   @override
-  Expression _makeSimpleRead() {
-    return _helper.wrapInDeferredCheck(suffixGenerator._makeSimpleRead(),
+  Expression buildSimpleRead() {
+    return _helper.wrapInDeferredCheck(suffixGenerator.buildSimpleRead(),
         prefixGenerator.prefix, token.charOffset);
   }
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
     return _helper.wrapInDeferredCheck(
-        suffixGenerator._makeRead(complexAssignment),
+        suffixGenerator.buildAssignment(value, voidContext: voidContext),
         prefixGenerator.prefix,
         token.charOffset);
   }
 
   @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ComplexAssignmentJudgment complexAssignment) {
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
     return _helper.wrapInDeferredCheck(
-        suffixGenerator._makeWrite(value, voidContext, complexAssignment),
+        suffixGenerator.buildIfNullAssignment(value, type, offset,
+            voidContext: voidContext),
         prefixGenerator.prefix,
         token.charOffset);
   }
 
   @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
-      SyntheticWrapper.wrapStaticAssignment(rhs);
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return _helper.wrapInDeferredCheck(
+        suffixGenerator.buildCompoundAssignment(binaryOperator, value,
+            offset: offset,
+            voidContext: voidContext,
+            interfaceTarget: interfaceTarget,
+            isPreIncDec: isPreIncDec,
+            isPostIncDec: isPostIncDec),
+        prefixGenerator.prefix,
+        token.charOffset);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
+    return _helper.wrapInDeferredCheck(
+        suffixGenerator.buildPostfixIncrement(binaryOperator,
+            offset: offset,
+            voidContext: voidContext,
+            interfaceTarget: interfaceTarget),
+        prefixGenerator.prefix,
+        token.charOffset);
+  }
 
   @override
   buildPropertyAccess(
@@ -2630,8 +2590,8 @@
   final TypeDeclarationBuilder declaration;
 
   TypeUseGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.declaration, String plainNameForRead)
-      : super(helper, token, null, plainNameForRead);
+      this.declaration, String targetName)
+      : super(helper, token, null, targetName);
 
   @override
   String get _debugName => "TypeUseGenerator";
@@ -2674,7 +2634,7 @@
       }
     }
     return new NamedTypeBuilder(
-        _plainNameForRead, nullabilityBuilder, argumentBuilders)
+        targetName, nullabilityBuilder, argumentBuilders)
       ..bind(declaration);
   }
 
@@ -2710,19 +2670,14 @@
     if (super.expression == null) {
       if (declaration is InvalidTypeBuilder) {
         InvalidTypeBuilder declaration = this.declaration;
-        _helper.addProblemErrorIfConst(
+        super.expression = _helper.buildProblemErrorIfConst(
             declaration.message.messageObject, fileOffset, token.length);
-        super.expression = _helper.wrapSyntheticExpression(
-            _forest.createThrow(null,
-                _forest.createStringLiteral(declaration.message.message, token))
-              ..fileOffset = fileOffset,
-            fileOffset);
       } else {
         super.expression = _forest.createTypeLiteral(
             _helper.buildDartType(
                 new UnresolvedType(
                     buildTypeWithResolvedArguments(
-                        const NullabilityBuilder.legacy(), null),
+                        _helper.libraryBuilder.nonNullableBuilder, null),
                     fileOffset,
                     _uri),
                 nonInstanceAccessIsError: true),
@@ -2733,18 +2688,6 @@
   }
 
   @override
-  Expression _makeInvalidWrite(Expression value) {
-    return _helper.wrapSyntheticExpression(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(fileOffset),
-            _plainNameForRead,
-            _forest.createArguments(fileOffset, <Expression>[value]),
-            fileOffset,
-            isSetter: true),
-        fileOffset);
-  }
-
-  @override
   buildPropertyAccess(
       IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
     // `SomeType?.toString` is the same as `SomeType.toString`, not
@@ -2796,7 +2739,7 @@
           }
         }
         generator = new StaticAccessGenerator.fromBuilder(
-            _helper, member, send.token, setter);
+            _helper, name.name, member, send.token, setter);
       }
 
       return arguments == null
@@ -2865,38 +2808,72 @@
 ///   }
 ///
 class ReadOnlyAccessGenerator extends Generator {
-  @override
-  final String _plainNameForRead;
+  final String targetName;
 
   Expression expression;
 
   VariableDeclaration value;
 
   ReadOnlyAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.expression, this._plainNameForRead)
+      this.expression, this.targetName)
       : super(helper, token);
 
   @override
   String get _debugName => "ReadOnlyAccessGenerator";
 
   @override
-  Expression _makeSimpleRead() => expression;
+  String get _plainNameForRead => targetName;
 
   @override
-  Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    value ??= new VariableDeclaration.forValue(expression);
-    return new VariableGet(value);
+  Expression buildSimpleRead() => expression;
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _makeInvalidWrite(value);
   }
 
   @override
-  Expression _finish(
-          Expression body, ComplexAssignmentJudgment complexAssignment) =>
-      super._finish(makeLet(value, body), complexAssignment);
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    Expression read = buildSimpleRead();
+    Expression write = _makeInvalidWrite(value);
+    return new IfNullSet(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}) {
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        buildSimpleRead(),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _makeInvalidWrite(binary);
+  }
+
+  @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);
+  }
 
   @override
   doInvocation(int offset, Arguments arguments) {
     return _helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
-        adjustForImplicitCall(_plainNameForRead, offset),
+        adjustForImplicitCall(targetName, offset),
         isImplicitCall: true);
   }
 
@@ -2906,7 +2883,7 @@
     sink.write(", expression: ");
     printNodeOn(expression, sink, syntheticNames: syntheticNames);
     sink.write(", plainNameForRead: ");
-    sink.write(_plainNameForRead);
+    sink.write(targetName);
     sink.write(", value: ");
     printNodeOn(value, sink, syntheticNames: syntheticNames);
   }
@@ -2931,8 +2908,8 @@
 
   @override
   Initializer buildFieldInitializer(Map<String, int> initializedFields) {
-    return _helper.buildInvalidInitializer(_helper.desugarSyntheticExpression(
-        buildError(_forest.createArgumentsEmpty(fileOffset), isSetter: true)));
+    return _helper.buildInvalidInitializer(
+        buildError(_forest.createArgumentsEmpty(fileOffset), isSetter: true));
   }
 
   @override
@@ -3022,11 +2999,7 @@
       _forest.argumentsSetTypeArguments(
           arguments, _helper.buildDartTypeArguments(typeArguments));
     }
-    return _helper.wrapInvalidConstructorInvocation(
-        _helper.desugarSyntheticExpression(buildError(arguments)),
-        null,
-        arguments,
-        fileOffset);
+    return buildError(arguments);
   }
 }
 
@@ -3051,26 +3024,20 @@
 
   @override
   Expression doInvocation(int charOffset, Arguments arguments) {
-    return _helper.wrapUnresolvedTargetInvocation(
-        _helper.desugarSyntheticExpression(
-            buildError(arguments, offset: charOffset)),
-        arguments,
-        arguments.fileOffset);
+    return buildError(arguments, offset: charOffset);
   }
 
   @override
   Expression buildError(Arguments arguments,
       {bool isGetter: false, bool isSetter: false, int offset}) {
     offset ??= fileOffset;
-    return _helper.wrapSyntheticExpression(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(null)..fileOffset = offset,
-            _plainNameForRead,
-            arguments,
-            offset,
-            isGetter: isGetter,
-            isSetter: isSetter),
-        offset);
+    return _helper.throwNoSuchMethodError(
+        _forest.createNullLiteral(null)..fileOffset = offset,
+        _plainNameForRead,
+        arguments,
+        offset,
+        isGetter: isGetter,
+        isSetter: isSetter);
   }
 
   @override
@@ -3107,13 +3074,8 @@
 
   Expression _buildUnresolvedVariableAssignment(
       bool isCompound, Expression value) {
-    return _helper.wrapUnresolvedVariableAssignment(
-        _helper.desugarSyntheticExpression(buildError(
-            _forest.createArguments(fileOffset, <Expression>[value]),
-            isSetter: true)),
-        isCompound,
-        value,
-        token.charOffset);
+    return buildError(_forest.createArguments(fileOffset, <Expression>[value]),
+        isSetter: true);
   }
 }
 
@@ -3145,7 +3107,8 @@
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    return new PropertySet(receiver, name, value)..fileOffset = fileOffset;
+    return _helper.forest.createPropertySet(fileOffset, receiver, name, value,
+        forEffect: voidContext);
   }
 
   @override
@@ -3154,6 +3117,82 @@
   }
 
   @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 = _helper.forest.createPropertySet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name, value,
+        forEffect: voidContext);
+    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 = _helper.forest.createPropertySet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name, binary,
+        forEffect: voidContext);
+    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,
+            _helper.forest.createPropertySet(
+                fileOffset,
+                _helper.createVariableGet(variable, receiver.fileOffset),
+                name,
+                binary,
+                forEffect: true));
+    return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
+  }
+
+  @override
   Expression doInvocation(int offset, Arguments arguments) {
     return unsupported("doInvocation", offset, _uri);
   }
@@ -3368,6 +3407,35 @@
   Expression buildSimpleRead() => _makeInvalidRead();
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return _makeInvalidRead();
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return _makeInvalidRead();
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
+    return _makeInvalidRead();
+  }
+
+  @override
   /* Expression | Generator */ Object qualifiedLookup(Token name) {
     if (_helper.constantContext != ConstantContext.none && prefix.deferred) {
       _helper.addProblem(
@@ -3449,9 +3517,8 @@
       : super(helper, token);
 
   @override
-  String get _plainNameForRead {
-    return "${prefixGenerator._plainNameForRead}.${token.lexeme}";
-  }
+  String get _plainNameForRead =>
+      "${prefixGenerator._plainNameForRead}.${token.lexeme}";
 
   @override
   String get _debugName => "UnexpectedQualifiedUseGenerator";
@@ -3460,13 +3527,40 @@
   Expression buildSimpleRead() => _makeInvalidRead();
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return _makeInvalidRead();
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return _makeInvalidRead();
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    return _makeInvalidRead();
+  }
+
+  @override
   Expression doInvocation(int offset, Arguments arguments) {
-    return _helper.wrapSyntheticExpression(
-        _helper.throwNoSuchMethodError(
-            _forest.createNullLiteral(null)..fileOffset = offset,
-            _plainNameForRead,
-            arguments,
-            fileOffset),
+    return _helper.throwNoSuchMethodError(
+        _forest.createNullLiteral(null)..fileOffset = offset,
+        _plainNameForRead,
+        arguments,
         fileOffset);
   }
 
@@ -3559,8 +3653,7 @@
   Expression _makeInvalidWrite(Expression value) => buildProblem();
 
   Initializer buildFieldInitializer(Map<String, int> initializedFields) {
-    return _helper.buildInvalidInitializer(
-        _helper.desugarSyntheticExpression(buildProblem()));
+    return _helper.buildInvalidInitializer(buildProblem());
   }
 
   Expression doInvocation(int offset, Arguments arguments) {
@@ -3662,7 +3755,7 @@
       if (inFieldInitializer) {
         return buildFieldInitializerError(null);
       } else {
-        return _forest.createThisExpression(token);
+        return _forest.createThisExpression(fileOffset);
       }
     } else {
       return _helper.buildProblem(
@@ -3680,8 +3773,7 @@
 
   @override
   Initializer buildFieldInitializer(Map<String, int> initializedFields) {
-    Expression error = _helper.desugarSyntheticExpression(
-        buildFieldInitializerError(initializedFields));
+    Expression error = buildFieldInitializerError(initializedFields);
     return _helper.buildInvalidInitializer(error, error.fileOffset);
   }
 
@@ -3708,9 +3800,13 @@
         _helper.warnUnresolvedMethod(name, offsetForToken(send.token),
             isSuper: isSuper);
       }
-      return _helper.buildMethodInvocation(_forest.createThisExpression(null),
-          name, send.arguments, offsetForToken(send.token),
-          isSuper: isSuper, interfaceTarget: getter);
+      return _helper.buildMethodInvocation(
+          _forest.createThisExpression(fileOffset),
+          name,
+          send.arguments,
+          offsetForToken(send.token),
+          isSuper: isSuper,
+          interfaceTarget: getter);
     } else {
       Member setter =
           _helper.lookupInstanceMember(name, isSuper: isSuper, isSetter: true);
@@ -3741,7 +3837,7 @@
       return _helper.buildProblem(messageSuperAsExpression, offset, noLength);
     } else {
       return _helper.buildMethodInvocation(
-          _forest.createThisExpression(null), callName, arguments, offset,
+          _forest.createThisExpression(fileOffset), callName, arguments, offset,
           isImplicitCall: true);
     }
   }
@@ -3763,7 +3859,7 @@
           .withLocation(_uri, fileOffset, lengthForToken(token));
     }
     if (message != null) {
-      return _helper.buildInvalidInitializer(_helper.wrapSyntheticExpression(
+      return _helper.buildInvalidInitializer(
           _helper.throwNoSuchMethodError(
               _forest.createNullLiteral(null)..fileOffset = offset,
               _helper.constructorNameForDiagnostics(name.name,
@@ -3772,7 +3868,7 @@
               offset,
               isSuper: isSuper,
               message: message),
-          offset));
+          offset);
     } else if (isSuper) {
       return _helper.buildSuperInitializer(
           false, constructor, arguments, offset);
@@ -3815,10 +3911,10 @@
   }
 
   Expression buildAssignmentError() {
-    return _helper.desugarSyntheticExpression(_helper.buildProblem(
+    return _helper.buildProblem(
         isSuper ? messageCannotAssignToSuper : messageNotAnLvalue,
         fileOffset,
-        token.length));
+        token.length);
   }
 
   @override
@@ -4036,20 +4132,9 @@
 
   String get _debugName => "ParenthesizedExpressionGenerator";
 
-  @override
-  ComplexAssignmentJudgment startComplexAssignment(Expression rhs) {
-    return SyntheticWrapper.wrapIllegalAssignment(rhs,
-        assignmentOffset: fileOffset);
-  }
-
   Expression _makeInvalidWrite(Expression value) {
-    return _helper.wrapInvalidWrite(
-        _helper.desugarSyntheticExpression(_helper.buildProblem(
-            messageCannotAssignToParenthesizedExpression,
-            fileOffset,
-            lengthForToken(token))),
-        expression,
-        fileOffset);
+    return _helper.buildProblem(messageCannotAssignToParenthesizedExpression,
+        fileOffset, lengthForToken(token));
   }
 }
 
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 53d1baf..3231dc7 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
@@ -126,6 +126,9 @@
 
   void addProblemErrorIfConst(Message message, int charOffset, int length);
 
+  Expression buildProblemErrorIfConst(
+      Message message, int charOffset, int length);
+
   Message warnUnresolvedGet(Name name, int charOffset, {bool isSuper});
 
   Message warnUnresolvedSet(Name name, int charOffset, {bool isSuper});
@@ -148,20 +151,6 @@
   void reportDuplicatedDeclaration(
       Builder existing, String name, int charOffset);
 
-  Expression wrapSyntheticExpression(Expression node, int charOffset);
-
-  Expression wrapInvalidConstructorInvocation(Expression desugared,
-      Member constructor, Arguments arguments, int charOffset);
-
-  Expression wrapInvalidWrite(
-      Expression desugared, Expression expression, int charOffset);
-
-  Expression wrapUnresolvedTargetInvocation(
-      Expression desugared, Arguments arguments, int charOffset);
-
-  Expression wrapUnresolvedVariableAssignment(
-      Expression desugared, bool isCompound, Expression rhs, int charOffset);
-
   /// Creates a [VariableGet] of the [variable] using [charOffset] as the file
   /// offset of the created node.
   Expression createVariableGet(VariableDeclaration variable, int charOffset);
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 37926f6..1a26c43 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -26,16 +26,7 @@
         IfMapEntry,
         SpreadElement;
 
-import 'kernel_shadow_ast.dart'
-    show
-        ArgumentsImpl,
-        IntJudgment,
-        LoadLibraryImpl,
-        MethodInvocationImpl,
-        ReturnStatementImpl,
-        ShadowLargeIntLiteral,
-        SyntheticExpressionJudgment,
-        VariableDeclarationImpl;
+import 'kernel_shadow_ast.dart';
 
 /// A shadow tree factory.
 class Forest {
@@ -515,8 +506,9 @@
     return new LabeledStatement(statement);
   }
 
-  Expression createThisExpression(Token token) {
-    return new ThisExpression()..fileOffset = offsetForToken(token);
+  Expression createThisExpression(int offset) {
+    assert(offset != null);
+    return new ThisExpression()..fileOffset = offset;
   }
 
   /// Return a representation of a throw expression consisting of the
@@ -607,10 +599,6 @@
       VariableDeclaration variable = node;
       node = variable.initializer;
     }
-    if (node is SyntheticExpressionJudgment) {
-      SyntheticExpressionJudgment synth = node;
-      node = synth.desugared;
-    }
     if (node is Let) {
       Let let = node;
       node = let.variable.initializer;
@@ -716,6 +704,26 @@
     return new StaticInvocation(procedure, arguments)
       ..fileOffset = fileOffset ?? TreeNode.noOffset;
   }
+
+  SuperMethodInvocation createSuperMethodInvocation(
+      int fileOffset, Name name, Procedure procedure, Arguments arguments) {
+    return new SuperMethodInvocation(name, arguments, procedure)
+      ..fileOffset = fileOffset ?? TreeNode.noOffset;
+  }
+
+  NullCheck createNullCheck(int fileOffset, Expression expression) {
+    return new NullCheck(expression)..fileOffset = fileOffset;
+  }
+
+  PropertySet createPropertySet(
+      int fileOffset, Expression receiver, Name name, Expression value,
+      {Member interfaceTarget, bool forEffect, bool readOnlyReceiver: false}) {
+    return new PropertySetImpl(receiver, name, value,
+        interfaceTarget: interfaceTarget,
+        forEffect: forEffect,
+        readOnlyReceiver: readOnlyReceiver)
+      ..fileOffset = fileOffset;
+  }
 }
 
 class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index cdfc0b1..b761c58 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -45,20 +45,34 @@
           return visitCompoundIndexSet(node, typeContext);
         case InternalExpressionKind.CompoundPropertySet:
           return visitCompoundPropertySet(node, typeContext);
+        case InternalExpressionKind.CompoundSuperIndexSet:
+          return visitCompoundSuperIndexSet(node, typeContext);
         case InternalExpressionKind.DeferredCheck:
           return visitDeferredCheck(node, typeContext);
+        case InternalExpressionKind.ExtensionSet:
+          return visitExtensionSet(node, typeContext);
+        case InternalExpressionKind.IfNull:
+          return visitIfNull(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.IfNullSuperIndexSet:
+          return visitIfNullSuperIndexSet(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.NullAwareCompoundSet:
+          return visitNullAwareCompoundSet(node, typeContext);
+        case InternalExpressionKind.NullAwareExtension:
+          return visitNullAwareExtension(node, typeContext);
+        case InternalExpressionKind.NullAwareIfNullSet:
+          return visitNullAwareIfNullSet(node, typeContext);
         case InternalExpressionKind.NullAwareMethodInvocation:
           return visitNullAwareMethodInvocation(node, typeContext);
         case InternalExpressionKind.NullAwarePropertyGet:
@@ -69,6 +83,8 @@
           return visitPropertyPostIncDec(node, typeContext);
         case InternalExpressionKind.StaticPostIncDec:
           return visitStaticPostIncDec(node, typeContext);
+        case InternalExpressionKind.SuperIndexSet:
+          return visitSuperIndexSet(node, typeContext);
         case InternalExpressionKind.SuperPostIncDec:
           return visitSuperPostIncDec(node, typeContext);
       }
@@ -186,7 +202,9 @@
   @override
   ExpressionInferenceResult visitInvalidExpression(
       InvalidExpression node, DartType typeContext) {
-    return const ExpressionInferenceResult(const BottomType());
+    // TODO(johnniwinther): The inferred type should be an InvalidType. Using
+    // BottomType leads to cascading errors so we use DynamicType for now.
+    return const ExpressionInferenceResult(const DynamicType());
   }
 
   @override
@@ -215,13 +233,15 @@
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
+            isVoidAllowed: true)
         .inferredType;
     inferrer.ensureAssignable(
         expectedType, conditionType, node.condition, node.condition.fileOffset);
     if (node.message != null) {
       inferrer.inferExpression(
-          node.message, const UnknownType(), !inferrer.isTopLevel);
+          node.message, const UnknownType(), !inferrer.isTopLevel,
+          isVoidAllowed: true);
     }
   }
 
@@ -259,8 +279,9 @@
   }
 
   ExpressionInferenceResult visitCascade(Cascade node, DartType typeContext) {
-    ExpressionInferenceResult result =
-        inferrer.inferExpression(node.expression, typeContext, true);
+    ExpressionInferenceResult result = inferrer.inferExpression(
+        node.expression, typeContext, true,
+        isVoidAllowed: false);
     node.variable.type = result.inferredType;
     for (Expression judgment in node.cascades) {
       inferrer.inferExpression(
@@ -277,7 +298,8 @@
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
+            isVoidAllowed: true)
         .inferredType;
     inferrer.ensureAssignable(
         expectedType, conditionType, node.condition, node.condition.fileOffset);
@@ -359,6 +381,68 @@
     // No inference needs to be done.
   }
 
+  ExpressionInferenceResult visitExtensionSet(
+      ExtensionSet 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 receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+
+    DartType valueType =
+        inferrer.getSetterType(node.target, receiverResult.inferredType);
+
+    ExpressionInferenceResult valueResult = inferrer.inferExpression(
+        node.value, const UnknownType(), true,
+        isVoidAllowed: false);
+    inferrer.ensureAssignable(
+        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+
+    Expression value;
+    VariableDeclaration valueVariable;
+    if (node.forEffect) {
+      value = node.value;
+    } else {
+      valueVariable = createVariable(node.value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+    }
+
+    VariableDeclaration receiverVariable;
+    Expression receiver;
+    if (node.forEffect || node.readOnlyReceiver) {
+      receiver = node.receiver;
+    } else {
+      receiverVariable =
+          createVariable(node.receiver, receiverResult.inferredType);
+      receiver = createVariableGet(receiverVariable);
+    }
+    Expression assignment = new StaticInvocation(
+        node.target.member,
+        new Arguments(<Expression>[receiver, value],
+            types: node.target.inferredExtensionTypeArguments)
+          ..fileOffset = node.fileOffset)
+      ..fileOffset = node.fileOffset;
+
+    Expression replacement;
+    if (node.forEffect) {
+      assert(receiverVariable == null);
+      assert(valueVariable == null);
+      replacement = assignment;
+    } else {
+      assert(valueVariable != null);
+      VariableDeclaration assignmentVariable =
+          createVariable(assignment, const VoidType());
+      replacement = createLet(valueVariable,
+          createLet(assignmentVariable, createVariableGet(valueVariable)));
+      if (receiverVariable != null) {
+        replacement = createLet(receiverVariable, replacement);
+      }
+    }
+    replacement.fileOffset = node.fileOffset;
+    node.replaceWith(replacement);
+    return new ExpressionInferenceResult(valueResult.inferredType, replacement);
+  }
+
   ExpressionInferenceResult visitDeferredCheck(
       DeferredCheck node, DartType typeContext) {
     // Since the variable is not used in the body we don't need to type infer
@@ -376,7 +460,8 @@
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType conditionType = inferrer
-        .inferExpression(node.condition, boolType, !inferrer.isTopLevel)
+        .inferExpression(node.condition, boolType, !inferrer.isTopLevel,
+            isVoidAllowed: true)
         .inferredType;
     inferrer.ensureAssignable(
         boolType, conditionType, node.condition, node.condition.fileOffset);
@@ -489,8 +574,8 @@
         ? inferrer.coreTypes.streamClass
         : inferrer.coreTypes.iterableClass;
     DartType context = inferrer.wrapType(elementType, iterableClass);
-    ExpressionInferenceResult iterableResult =
-        inferrer.inferExpression(iterable, context, typeNeeded);
+    ExpressionInferenceResult iterableResult = inferrer
+        .inferExpression(iterable, context, typeNeeded, isVoidAllowed: false);
     DartType iterableType = iterableResult.inferredType;
     if (iterableResult.replacement != null) {
       iterable = iterableResult.replacement;
@@ -523,18 +608,13 @@
     DartType elementType;
     bool typeChecksNeeded = !inferrer.isTopLevel;
     DartType syntheticWriteType;
-    Expression syntheticAssignment;
     Expression rhs;
     // If `true`, the synthetic statement should not be visited.
     bool skipStatement = false;
     ExpressionStatement syntheticStatement =
         body is Block ? body.statements.first : body;
     Expression statementExpression = syntheticStatement.expression;
-    if (statementExpression is SyntheticExpressionJudgment) {
-      syntheticAssignment = statementExpression.desugared;
-    } else {
-      syntheticAssignment = statementExpression;
-    }
+    Expression syntheticAssignment = statementExpression;
     if (syntheticAssignment is VariableSet) {
       syntheticWriteType = elementType = syntheticAssignment.variable.type;
       rhs = syntheticAssignment.value;
@@ -625,7 +705,8 @@
       InterfaceType expectedType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       DartType conditionType = inferrer
-          .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+          .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
+              isVoidAllowed: true)
           .inferredType;
       inferrer.ensureAssignable(expectedType, conditionType, node.condition,
           node.condition.fileOffset);
@@ -677,13 +758,18 @@
         skipTypeArgumentInference: true);
   }
 
-  ExpressionInferenceResult visitIfNullJudgment(
-      IfNullJudgment node, DartType typeContext) {
+  ExpressionInferenceResult visitIfNull(
+      IfNullExpression node, DartType typeContext) {
     // To infer `e0 ?? e1` in context K:
     // - Infer e0 in context K to get T0
-    DartType lhsType =
-        inferrer.inferExpression(node.left, typeContext, true).inferredType;
-    node.variable.type = lhsType;
+    DartType lhsType = inferrer
+        .inferExpression(node.left, typeContext, true, isVoidAllowed: false)
+        .inferredType;
+
+    Member equalsMember = inferrer
+        .findInterfaceMember(lhsType, equalsName, node.fileOffset)
+        .member;
+
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
     DartType rhsType;
@@ -701,8 +787,15 @@
     // - Then the inferred type is T.
     DartType inferredType =
         inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType);
-    node.body.staticType = inferredType;
-    return new ExpressionInferenceResult(inferredType);
+    VariableDeclaration variable = createVariable(node.left, lhsType);
+    MethodInvocation equalsNull = createEqualsNull(
+        node.left.fileOffset, createVariableGet(variable), equalsMember);
+    ConditionalExpression conditional = new ConditionalExpression(
+        equalsNull, node.right, createVariableGet(variable), inferredType);
+    Expression replacement = new Let(variable, conditional)
+      ..fileOffset = node.fileOffset;
+    node.replaceWith(replacement);
+    return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   @override
@@ -710,7 +803,8 @@
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
+            isVoidAllowed: true)
         .inferredType;
     inferrer.ensureAssignable(
         expectedType, conditionType, node.condition, node.condition.fileOffset);
@@ -720,85 +814,6 @@
     }
   }
 
-  ExpressionInferenceResult visitIllegalAssignmentJudgment(
-      IllegalAssignmentJudgment node, DartType typeContext) {
-    if (node.write != null) {
-      inferrer.inferExpression(
-          node.write, const UnknownType(), !inferrer.isTopLevel);
-    }
-    inferrer.inferExpression(
-        node.rhs, const UnknownType(), !inferrer.isTopLevel);
-    node._replaceWithDesugared();
-    return const ExpressionInferenceResult(const DynamicType());
-  }
-
-  ExpressionInferenceResult visitIndexAssignmentJudgment(
-      IndexAssignmentJudgment node, DartType typeContext) {
-    DartType receiverType = node._inferReceiver(inferrer);
-    ObjectAccessTarget writeTarget =
-        inferrer.findMethodInvocationMember(receiverType, node.write);
-    // To replicate analyzer behavior, we base type inference on the write
-    // member.  TODO(paulberry): would it be better to use the read member
-    // when doing compound assignment?
-    DartType indexContext = const UnknownType();
-    DartType expectedIndexTypeForWrite =
-        inferrer.getIndexKeyType(writeTarget, receiverType);
-    DartType writeContext =
-        inferrer.getIndexSetValueType(writeTarget, receiverType);
-    ExpressionInferenceResult indexResult =
-        inferrer.inferExpression(node.index, indexContext, true);
-    DartType indexType = indexResult.inferredType;
-    node._storeLetType(inferrer, node.index, indexType);
-    if (indexResult.replacement != null) {
-      node.index = indexResult.replacement;
-    }
-    Expression writeIndexExpression =
-        node._getInvocationArguments(inferrer, node.write).positional[0];
-    if (writeTarget.isExtensionMember) {
-      MethodInvocation write = node.write;
-      Expression replacement = inferrer.transformExtensionMethodInvocation(
-          writeTarget, write, write.receiver, write.arguments);
-      node.write = replacement;
-    }
-    if (writeContext is! UnknownType) {
-      inferrer.ensureAssignable(expectedIndexTypeForWrite, indexType,
-          writeIndexExpression, node.write.fileOffset);
-    }
-
-    InvocationExpression read = node.read;
-    DartType readType;
-    if (read != null) {
-      ObjectAccessTarget readMember = inferrer
-          .findMethodInvocationMember(receiverType, read, instrumented: false);
-      FunctionType calleeFunctionType =
-          inferrer.getFunctionType(readMember, receiverType, false);
-      inferrer.ensureAssignable(
-          getPositionalParameterType(calleeFunctionType, 0),
-          indexType,
-          node._getInvocationArguments(inferrer, read).positional[0],
-          read.fileOffset);
-      readType = calleeFunctionType.returnType;
-      MethodInvocation desugaredInvocation =
-          read is MethodInvocation ? read : null;
-      MethodContravarianceCheckKind checkKind =
-          inferrer.preCheckInvocationContravariance(receiverType, readMember,
-              isThisReceiver: node.receiver is ThisExpression);
-      Expression replacedRead = inferrer.handleInvocationContravariance(
-          checkKind,
-          desugaredInvocation,
-          read.arguments,
-          read,
-          readType,
-          calleeFunctionType,
-          read.fileOffset);
-      node._storeLetType(inferrer, replacedRead, readType);
-    }
-    DartType inferredType =
-        node._inferRhs(inferrer, readType, writeContext).inferredType;
-    node._replaceWithDesugared();
-    return new ExpressionInferenceResult(inferredType);
-  }
-
   ExpressionInferenceResult visitIntJudgment(
       IntJudgment node, DartType typeContext) {
     if (inferrer.isDoubleContext(typeContext)) {
@@ -838,11 +853,10 @@
 
     int intValue = node.asInt64();
     if (intValue == null) {
-      Expression replacement = inferrer.helper.desugarSyntheticExpression(
-          inferrer.helper.buildProblem(
-              templateIntegerLiteralIsOutOfRange.withArguments(node.literal),
-              node.fileOffset,
-              node.literal.length));
+      Expression replacement = inferrer.helper.buildProblem(
+          templateIntegerLiteralIsOutOfRange.withArguments(node.literal),
+          node.fileOffset,
+          node.literal.length);
       node.parent.replaceChild(node, replacement);
       return const ExpressionInferenceResult(const BottomType());
     }
@@ -861,18 +875,21 @@
 
   void visitShadowInvalidInitializer(ShadowInvalidInitializer node) {
     inferrer.inferExpression(
-        node.variable.initializer, const UnknownType(), !inferrer.isTopLevel);
+        node.variable.initializer, const UnknownType(), !inferrer.isTopLevel,
+        isVoidAllowed: false);
   }
 
   void visitShadowInvalidFieldInitializer(ShadowInvalidFieldInitializer node) {
-    inferrer.inferExpression(node.value, node.field.type, !inferrer.isTopLevel);
+    inferrer.inferExpression(node.value, node.field.type, !inferrer.isTopLevel,
+        isVoidAllowed: false);
   }
 
   @override
   ExpressionInferenceResult visitIsExpression(
       IsExpression node, DartType typeContext) {
     inferrer.inferExpression(
-        node.operand, const UnknownType(), !inferrer.isTopLevel);
+        node.operand, const UnknownType(), !inferrer.isTopLevel,
+        isVoidAllowed: false);
     return new ExpressionInferenceResult(
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable));
   }
@@ -922,28 +939,25 @@
               !element.isNullAware) {
             parent.replaceChild(
                 element,
-                inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                    .buildProblem(messageNonNullAwareSpreadIsNull,
-                        element.expression.fileOffset, 1)));
+                inferrer.helper.buildProblem(messageNonNullAwareSpreadIsNull,
+                    element.expression.fileOffset, 1));
           } else {
             parent.replaceChild(
                 element,
-                inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                    .buildProblem(
-                        templateSpreadTypeMismatch.withArguments(spreadType),
-                        element.expression.fileOffset,
-                        1)));
+                inferrer.helper.buildProblem(
+                    templateSpreadTypeMismatch.withArguments(spreadType),
+                    element.expression.fileOffset,
+                    1));
           }
         } else if (spreadType is InterfaceType) {
           if (!inferrer.isAssignable(inferredTypeArgument, spreadElementType)) {
             parent.replaceChild(
                 element,
-                inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                    .buildProblem(
-                        templateSpreadElementTypeMismatch.withArguments(
-                            spreadElementType, inferredTypeArgument),
-                        element.expression.fileOffset,
-                        1)));
+                inferrer.helper.buildProblem(
+                    templateSpreadElementTypeMismatch.withArguments(
+                        spreadElementType, inferredTypeArgument),
+                    element.expression.fileOffset,
+                    1));
           }
         }
       }
@@ -1187,10 +1201,12 @@
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType leftType = inferrer
-        .inferExpression(node.left, boolType, !inferrer.isTopLevel)
+        .inferExpression(node.left, boolType, !inferrer.isTopLevel,
+            isVoidAllowed: false)
         .inferredType;
     DartType rightType = inferrer
-        .inferExpression(node.right, boolType, !inferrer.isTopLevel)
+        .inferExpression(node.right, boolType, !inferrer.isTopLevel,
+            isVoidAllowed: false)
         .inferredType;
     inferrer.ensureAssignable(
         boolType, leftType, node.left, node.left.fileOffset);
@@ -1262,9 +1278,10 @@
             parent.replaceChild(
                 entry,
                 new MapEntry(
-                    inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                        .buildProblem(messageNonNullAwareSpreadIsNull,
-                            entry.expression.fileOffset, 1)),
+                    inferrer.helper.buildProblem(
+                        messageNonNullAwareSpreadIsNull,
+                        entry.expression.fileOffset,
+                        1),
                     new NullLiteral())
                   ..fileOffset = entry.fileOffset);
           } else if (actualElementType != null) {
@@ -1275,12 +1292,11 @@
             parent.replaceChild(
                 entry,
                 new MapEntry(
-                    inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                        .buildProblem(
-                            templateSpreadMapEntryTypeMismatch
-                                .withArguments(spreadType),
-                            entry.expression.fileOffset,
-                            1)),
+                    inferrer.helper.buildProblem(
+                        templateSpreadMapEntryTypeMismatch
+                            .withArguments(spreadType),
+                        entry.expression.fileOffset,
+                        1),
                     new NullLiteral())
                   ..fileOffset = entry.fileOffset);
           }
@@ -1288,20 +1304,18 @@
           Expression keyError;
           Expression valueError;
           if (!inferrer.isAssignable(inferredKeyType, actualKeyType)) {
-            keyError = inferrer.helper.desugarSyntheticExpression(
-                inferrer.helper.buildProblem(
-                    templateSpreadMapEntryElementKeyTypeMismatch.withArguments(
-                        actualKeyType, inferredKeyType),
-                    entry.expression.fileOffset,
-                    1));
+            keyError = inferrer.helper.buildProblem(
+                templateSpreadMapEntryElementKeyTypeMismatch.withArguments(
+                    actualKeyType, inferredKeyType),
+                entry.expression.fileOffset,
+                1);
           }
           if (!inferrer.isAssignable(inferredValueType, actualValueType)) {
-            valueError = inferrer.helper.desugarSyntheticExpression(
-                inferrer.helper.buildProblem(
-                    templateSpreadMapEntryElementValueTypeMismatch
-                        .withArguments(actualValueType, inferredValueType),
-                    entry.expression.fileOffset,
-                    1));
+            valueError = inferrer.helper.buildProblem(
+                templateSpreadMapEntryElementValueTypeMismatch.withArguments(
+                    actualValueType, inferredValueType),
+                entry.expression.fileOffset,
+                1);
           }
           if (keyError != null || valueError != null) {
             keyError ??= new NullLiteral();
@@ -1502,12 +1516,11 @@
       parent.replaceChild(
           entry,
           new MapEntry(
-              inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                  .buildProblem(
-                      templateSpreadMapEntryTypeMismatch
-                          .withArguments(iterableSpreadType),
-                      iterableSpreadOffset,
-                      1)),
+              inferrer.helper.buildProblem(
+                  templateSpreadMapEntryTypeMismatch
+                      .withArguments(iterableSpreadType),
+                  iterableSpreadOffset,
+                  1),
               new NullLiteral()));
     }
     if (entry is SpreadMapEntry) {
@@ -1714,18 +1727,20 @@
       if (canBeSet && canBeMap && node.entries.isNotEmpty) {
         node.parent.replaceChild(
             node,
-            inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                .buildProblem(messageCantDisambiguateNotEnoughInformation,
-                    node.fileOffset, 1)));
+            inferrer.helper.buildProblem(
+                messageCantDisambiguateNotEnoughInformation,
+                node.fileOffset,
+                1));
         return const ExpressionInferenceResult(const BottomType());
       }
       if (!canBeSet && !canBeMap) {
         if (!inferrer.isTopLevel) {
           node.parent.replaceChild(
               node,
-              inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                  .buildProblem(messageCantDisambiguateAmbiguousInformation,
-                      node.fileOffset, 1)));
+              inferrer.helper.buildProblem(
+                  messageCantDisambiguateAmbiguousInformation,
+                  node.fileOffset,
+                  1));
         }
         return const ExpressionInferenceResult(const BottomType());
       }
@@ -1824,12 +1839,11 @@
           }
           int intValue = receiver.asInt64(negated: true);
           if (intValue == null) {
-            Expression error = inferrer.helper.desugarSyntheticExpression(
-                inferrer.helper.buildProblem(
-                    templateIntegerLiteralIsOutOfRange
-                        .withArguments(receiver.literal),
-                    receiver.fileOffset,
-                    receiver.literal.length));
+            Expression error = inferrer.helper.buildProblem(
+                templateIntegerLiteralIsOutOfRange
+                    .withArguments(receiver.literal),
+                receiver.fileOffset,
+                receiver.literal.length);
             node.parent.replaceChild(node, error);
             return const ExpressionInferenceResult(const BottomType());
           }
@@ -1874,6 +1888,20 @@
     return new ExpressionInferenceResult(boolType);
   }
 
+  @override
+  ExpressionInferenceResult visitNullCheck(
+      NullCheck node, DartType typeContext) {
+    // TODO(johnniwinther): Should the typeContext for the operand be
+    //  `Nullable(typeContext)`?
+    DartType inferredType = inferrer
+        .inferExpression(node.operand, typeContext, !inferrer.isTopLevel)
+        .inferredType;
+    // TODO(johnniwinther): Check that the inferred type is potentially
+    //  nullable.
+    // TODO(johnniwinther): Return `NonNull(inferredType)`.
+    return new ExpressionInferenceResult(inferredType);
+  }
+
   ExpressionInferenceResult visitNullAwareMethodInvocation(
       NullAwareMethodInvocation node, DartType typeContext) {
     inferrer.inferStatement(node.variable);
@@ -1881,8 +1909,7 @@
         node.invocation, typeContext, true,
         isVoidAllowed: true);
     Member equalsMember = inferrer
-        .findInterfaceMember(
-            node.variable.type, new Name('=='), node.fileOffset)
+        .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
 
     DartType inferredType = readResult.inferredType;
@@ -1908,8 +1935,7 @@
     ExpressionInferenceResult readResult =
         inferrer.inferExpression(node.read, const UnknownType(), true);
     Member equalsMember = inferrer
-        .findInterfaceMember(
-            node.variable.type, new Name('=='), node.fileOffset)
+        .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
 
     DartType inferredType = readResult.inferredType;
@@ -1935,8 +1961,7 @@
     ExpressionInferenceResult writeResult =
         inferrer.inferExpression(node.write, typeContext, true);
     Member equalsMember = inferrer
-        .findInterfaceMember(
-            node.variable.type, new Name('=='), node.fileOffset)
+        .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
 
     DartType inferredType = writeResult.inferredType;
@@ -1956,6 +1981,32 @@
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
+  ExpressionInferenceResult visitNullAwareExtension(
+      NullAwareExtension node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult expressionResult =
+        inferrer.inferExpression(node.expression, const UnknownType(), true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
+        .member;
+
+    DartType inferredType = expressionResult.inferredType;
+
+    Expression replacement;
+    MethodInvocation equalsNull = createEqualsNull(
+        node.fileOffset,
+        new VariableGet(node.variable)..fileOffset = node.fileOffset,
+        equalsMember);
+    ConditionalExpression condition = new ConditionalExpression(
+        equalsNull,
+        new NullLiteral()..fileOffset = node.fileOffset,
+        node.expression,
+        inferredType);
+    node.replaceWith(replacement = new Let(node.variable, condition)
+      ..fileOffset = node.fileOffset);
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
   ExpressionInferenceResult visitStaticPostIncDec(
       StaticPostIncDec node, DartType typeContext) {
     inferrer.inferStatement(node.read);
@@ -1996,8 +2047,8 @@
   ExpressionInferenceResult visitCompoundPropertySet(
       CompoundPropertySet node, DartType typeContext) {
     inferrer.inferStatement(node.variable);
-    ExpressionInferenceResult writeResult =
-        inferrer.inferExpression(node.write, typeContext, true);
+    ExpressionInferenceResult writeResult = inferrer
+        .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
     Expression replacement = node.replace();
     return new ExpressionInferenceResult(writeResult.inferredType, replacement);
   }
@@ -2005,13 +2056,14 @@
   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);
+    ExpressionInferenceResult readResult = inferrer.inferExpression(
+        node.read, const UnknownType(), true,
+        isVoidAllowed: true);
+    ExpressionInferenceResult writeResult = inferrer
+        .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
     Member equalsMember = inferrer
         .findInterfaceMember(
-            readResult.inferredType, new Name('=='), node.fileOffset)
+            readResult.inferredType, equalsName, node.fileOffset)
         .member;
 
     DartType inferredType = inferrer.typeSchemaEnvironment
@@ -2058,11 +2110,11 @@
       IfNullSet node, DartType typeContext) {
     ExpressionInferenceResult readResult =
         inferrer.inferExpression(node.read, const UnknownType(), true);
-    ExpressionInferenceResult writeResult =
-        inferrer.inferExpression(node.write, typeContext, true);
+    ExpressionInferenceResult writeResult = inferrer
+        .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
     Member equalsMember = inferrer
         .findInterfaceMember(
-            readResult.inferredType, new Name('=='), node.fileOffset)
+            readResult.inferredType, equalsName, node.fileOffset)
         .member;
 
     DartType inferredType = inferrer.typeSchemaEnvironment
@@ -2110,7 +2162,7 @@
         createVariable(node.receiver, receiverType);
 
     ObjectAccessTarget indexSetTarget = inferrer.findInterfaceMember(
-        receiverType, new Name('[]='), node.fileOffset,
+        receiverType, indexSetName, node.fileOffset,
         includeExtensionMethods: true);
 
     DartType indexType = inferrer.getIndexKeyType(indexSetTarget, receiverType);
@@ -2143,9 +2195,9 @@
       assignment = inferrer.helper.buildProblem(
           templateUndefinedMethod.withArguments('[]=', receiverType),
           node.fileOffset,
-          '[]='.length,
-          wrapInSyntheticExpression: false);
+          '[]='.length);
     } else if (indexSetTarget.isExtensionMember) {
+      assert(indexSetTarget.extensionMethodKind != ProcedureKind.Setter);
       assignment = new StaticInvocation(
           indexSetTarget.member,
           new Arguments(<Expression>[
@@ -2158,7 +2210,7 @@
     } else {
       assignment = new MethodInvocation(
           createVariableGet(receiverVariable),
-          new Name('[]='),
+          indexSetName,
           new Arguments(<Expression>[
             createVariableGet(indexVariable),
             createVariableGet(valueVariable)
@@ -2181,17 +2233,88 @@
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
+  ExpressionInferenceResult visitSuperIndexSet(
+      SuperIndexSet node, DartType typeContext) {
+    ObjectAccessTarget indexSetTarget = node.setter != null
+        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        : const ObjectAccessTarget.missing();
+
+    DartType indexType =
+        inferrer.getIndexKeyType(indexSetTarget, inferrer.thisType);
+    DartType valueType =
+        inferrer.getIndexSetValueType(indexSetTarget, inferrer.thisType);
+
+    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(
+          templateSuperclassHasNoMethod.withArguments('[]='),
+          node.fileOffset,
+          '[]='.length);
+    } else {
+      assert(indexSetTarget.isInstanceMember);
+      inferrer.instrumentation?.record(inferrer.uri, node.fileOffset, 'target',
+          new InstrumentationValueForMember(node.setter));
+      assignment = new SuperMethodInvocation(
+          indexSetName,
+          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(
+        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);
+    VariableDeclaration receiverVariable;
+    Expression readReceiver;
+    Expression writeReceiver;
+    if (node.readOnlyReceiver) {
+      readReceiver = node.receiver;
+      writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
+    } else {
+      receiverVariable = createVariable(node.receiver, receiverType);
+      readReceiver = createVariableGet(receiverVariable);
+      writeReceiver = createVariableGet(receiverVariable);
+    }
 
     ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
-        receiverType, new Name('[]'), node.readOffset,
+        receiverType, indexGetName, node.readOffset,
         includeExtensionMethods: true);
 
     MethodContravarianceCheckKind checkKind =
@@ -2202,11 +2325,11 @@
     DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
 
     Member equalsMember = inferrer
-        .findInterfaceMember(readType, new Name('=='), node.fileOffset)
+        .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
-        receiverType, new Name('[]='), node.fileOffset,
+        receiverType, indexSetName, node.writeOffset,
         includeExtensionMethods: true);
 
     DartType writeIndexType =
@@ -2244,21 +2367,20 @@
       read = inferrer.helper.buildProblem(
           templateUndefinedMethod.withArguments('[]', receiverType),
           node.readOffset,
-          '[]'.length,
-          wrapInSyntheticExpression: false);
+          '[]'.length);
     } else if (readTarget.isExtensionMember) {
       read = new StaticInvocation(
           readTarget.member,
           new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
+            readReceiver,
             readIndex,
           ], types: readTarget.inferredExtensionTypeArguments)
             ..fileOffset = node.readOffset)
         ..fileOffset = node.readOffset;
     } else {
       read = new MethodInvocation(
-          createVariableGet(receiverVariable),
-          new Name('[]'),
+          readReceiver,
+          indexGetName,
           new Arguments(<Expression>[
             readIndex,
           ])
@@ -2291,48 +2413,50 @@
     if (writeTarget.isMissing) {
       write = inferrer.helper.buildProblem(
           templateUndefinedMethod.withArguments('[]=', receiverType),
-          node.fileOffset,
-          '[]='.length,
-          wrapInSyntheticExpression: false);
+          node.writeOffset,
+          '[]='.length);
     } else if (writeTarget.isExtensionMember) {
+      assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
       write = new StaticInvocation(
           writeTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            writeIndex,
-            valueExpression
-          ], types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.fileOffset)
-        ..fileOffset = node.fileOffset;
+          new Arguments(
+              <Expression>[writeReceiver, writeIndex, valueExpression],
+              types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.writeOffset)
+        ..fileOffset = node.writeOffset;
     } else {
       write = new MethodInvocation(
-          createVariableGet(receiverVariable),
-          new Name('[]='),
+          writeReceiver,
+          indexSetName,
           new Arguments(<Expression>[writeIndex, valueExpression])
-            ..fileOffset = node.fileOffset,
+            ..fileOffset = node.writeOffset,
           writeTarget.member)
-        ..fileOffset = node.fileOffset;
+        ..fileOffset = node.writeOffset;
     }
 
-    Expression replacement;
+    Expression inner;
     if (node.forEffect) {
-      // Encode `o[a] ??= b` as:
+      // Encode `o[a] ??= b`, if `node.readOnlyReceiver` is false, as:
       //
       //     let v1 = o in
       //     let v2 = a in
       //     let v3 = v1[v2] in
       //        v3 == null ? v1.[]=(v2, b) : null
       //
+      // and if `node.readOnlyReceiver` is true as:
+      //
+      //     let v2 = a in
+      //     let v3 = o[v2] in
+      //        v3 == null ? o.[]=(v2, b) : null
+      //
       MethodInvocation equalsNull =
-          createEqualsNull(node.fileOffset, read, equalsMember);
+          createEqualsNull(node.testOffset, 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);
+          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+        ..fileOffset = node.testOffset;
+      inner = createLet(indexVariable, conditional);
     } else {
-      // Encode `o[a] ??= b` as:
+      // Encode `o[a] ??= b` as, if `node.readOnlyReceiver` is false, as:
       //
       //     let v1 = o in
       //     let v2 = a in
@@ -2343,11 +2467,22 @@
       //           v4)
       //        : v3
       //
+      // and if `node.readOnlyReceiver` is true as:
+      //
+      //     let v2 = a in
+      //     let v3 = o[v2] in
+      //       v3 == null
+      //        ? (let v4 = b in
+      //           let _ = o.[]=(v2, v4) in
+      //           v4)
+      //        : v3
+      //
+      //
       assert(valueVariable != null);
 
       VariableDeclaration readVariable = createVariable(read, readType);
       MethodInvocation equalsNull = createEqualsNull(
-          node.fileOffset, createVariableGet(readVariable), equalsMember);
+          node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
       ConditionalExpression conditional = new ConditionalExpression(
@@ -2357,10 +2492,157 @@
           createVariableGet(readVariable),
           inferredType)
         ..fileOffset = node.fileOffset;
-      node.replaceWith(replacement = new Let(receiverVariable,
-          createLet(indexVariable, createLet(readVariable, conditional)))
-        ..fileOffset = node.fileOffset);
+      inner = createLet(indexVariable, createLet(readVariable, conditional));
     }
+
+    Expression replacement;
+    if (receiverVariable != null) {
+      node.replaceWith(replacement = new Let(receiverVariable, inner)
+        ..fileOffset = node.fileOffset);
+    } else {
+      node.replaceWith(replacement = inner);
+    }
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitIfNullSuperIndexSet(
+      IfNullSuperIndexSet node, DartType typeContext) {
+    ObjectAccessTarget readTarget = node.getter != null
+        ? new ObjectAccessTarget.interfaceMember(node.getter)
+        : const ObjectAccessTarget.missing();
+
+    DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
+    DartType readIndexType =
+        inferrer.getIndexKeyType(readTarget, inferrer.thisType);
+
+    Member equalsMember = inferrer
+        .findInterfaceMember(readType, equalsName, node.testOffset)
+        .member;
+
+    ObjectAccessTarget writeTarget = node.setter != null
+        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        : const ObjectAccessTarget.missing();
+
+    DartType writeIndexType =
+        inferrer.getIndexKeyType(writeTarget, inferrer.thisType);
+    DartType valueType =
+        inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
+
+    ExpressionInferenceResult indexResult = inferrer
+        .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
+
+    VariableDeclaration indexVariable =
+        createVariable(node.index, indexResult.inferredType);
+
+    VariableGet readIndex = createVariableGet(indexVariable);
+    inferrer.ensureAssignable(readIndexType, indexResult.inferredType,
+        readIndex, readIndex.fileOffset);
+
+    VariableGet writeIndex = createVariableGet(indexVariable);
+    inferrer.ensureAssignable(writeIndexType, indexResult.inferredType,
+        writeIndex, writeIndex.fileOffset);
+
+    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(
+          templateSuperclassHasNoMethod.withArguments('[]'),
+          node.readOffset,
+          '[]'.length);
+    } else {
+      assert(readTarget.isInstanceMember);
+      inferrer.instrumentation?.record(inferrer.uri, node.readOffset, 'target',
+          new InstrumentationValueForMember(node.getter));
+      read = new SuperMethodInvocation(
+          indexGetName,
+          new Arguments(<Expression>[
+            readIndex,
+          ])
+            ..fileOffset = node.readOffset,
+          readTarget.member)
+        ..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(
+          templateSuperclassHasNoMethod.withArguments('[]='),
+          node.writeOffset,
+          '[]='.length);
+    } else {
+      assert(writeTarget.isInstanceMember);
+      inferrer.instrumentation?.record(inferrer.uri, node.writeOffset, 'target',
+          new InstrumentationValueForMember(node.setter));
+      write = new SuperMethodInvocation(
+          indexSetName,
+          new Arguments(
+              <Expression>[createVariableGet(indexVariable), valueExpression])
+            ..fileOffset = node.writeOffset,
+          writeTarget.member)
+        ..fileOffset = node.writeOffset;
+    }
+
+    Expression replacement;
+    if (node.forEffect) {
+      // Encode `o[a] ??= b` as:
+      //
+      //     let v1 = a in
+      //        super[v1] == null ? super.[]=(v1, b) : null
+      //
+      MethodInvocation equalsNull =
+          createEqualsNull(node.testOffset, read, equalsMember);
+      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+        ..fileOffset = node.testOffset;
+      replacement = createLet(indexVariable, conditional);
+    } else {
+      // Encode `o[a] ??= b` as:
+      //
+      //     let v1 = a in
+      //     let v2 = super[v1] in
+      //       v2 == null
+      //        ? (let v3 = b in
+      //           let _ = super.[]=(v1, v3) in
+      //           v3)
+      //        : v2
+      //
+      assert(valueVariable != null);
+
+      VariableDeclaration readVariable = createVariable(read, readType);
+      MethodInvocation equalsNull = createEqualsNull(
+          node.testOffset, 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;
+      replacement =
+          createLet(indexVariable, createLet(readVariable, conditional));
+    }
+
+    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2370,11 +2652,20 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: true);
     DartType receiverType = receiverResult.inferredType;
-    VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+    VariableDeclaration receiverVariable;
+    Expression readReceiver;
+    Expression writeReceiver;
+    if (node.readOnlyReceiver) {
+      readReceiver = node.receiver;
+      writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
+    } else {
+      receiverVariable = createVariable(node.receiver, receiverType);
+      readReceiver = createVariableGet(receiverVariable);
+      writeReceiver = createVariableGet(receiverVariable);
+    }
 
     ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
-        receiverType, new Name('[]'), node.readOffset,
+        receiverType, indexGetName, node.readOffset,
         includeExtensionMethods: true);
 
     MethodContravarianceCheckKind readCheckKind =
@@ -2402,21 +2693,20 @@
       read = inferrer.helper.buildProblem(
           templateUndefinedMethod.withArguments('[]', receiverType),
           node.readOffset,
-          '[]'.length,
-          wrapInSyntheticExpression: false);
+          '[]'.length);
     } else if (readTarget.isExtensionMember) {
       read = new StaticInvocation(
           readTarget.member,
           new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
+            readReceiver,
             readIndex,
           ], types: readTarget.inferredExtensionTypeArguments)
             ..fileOffset = node.readOffset)
         ..fileOffset = node.readOffset;
     } else {
       read = new MethodInvocation(
-          createVariableGet(receiverVariable),
-          new Name('[]'),
+          readReceiver,
+          indexGetName,
           new Arguments(<Expression>[
             readIndex,
           ])
@@ -2471,11 +2761,247 @@
     Expression binary;
     if (binaryTarget.isMissing) {
       binary = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              node.binaryName.name, receiverType),
+          templateUndefinedMethod.withArguments(node.binaryName.name, readType),
           node.binaryOffset,
-          node.binaryName.name.length,
-          wrapInSyntheticExpression: false);
+          node.binaryName.name.length);
+    } else if (binaryTarget.isExtensionMember) {
+      assert(binaryTarget.extensionMethodKind != ProcedureKind.Setter);
+      binary = new StaticInvocation(
+          binaryTarget.member,
+          new Arguments(<Expression>[
+            left,
+            node.rhs,
+          ], types: binaryTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.binaryOffset)
+        ..fileOffset = node.binaryOffset;
+    } else {
+      binary = new MethodInvocation(
+          left,
+          node.binaryName,
+          new Arguments(<Expression>[
+            node.rhs,
+          ])
+            ..fileOffset = node.binaryOffset,
+          binaryTarget.member)
+        ..fileOffset = node.binaryOffset;
+
+      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(inferrer.uri, node.binaryOffset,
+              'checkReturn', new InstrumentationValueForType(readType));
+        }
+        binary = new AsExpression(binary, binaryType)
+          ..isTypeError = true
+          ..fileOffset = node.binaryOffset;
+      }
+    }
+
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, indexSetName, 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;
+    }
+
+    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);
+    } else if (writeTarget.isExtensionMember) {
+      assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
+      write = new StaticInvocation(
+          writeTarget.member,
+          new Arguments(
+              <Expression>[writeReceiver, writeIndex, valueExpression],
+              types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.writeOffset)
+        ..fileOffset = node.writeOffset;
+    } else {
+      write = new MethodInvocation(
+          writeReceiver,
+          indexSetName,
+          new Arguments(<Expression>[writeIndex, valueExpression])
+            ..fileOffset = node.writeOffset,
+          writeTarget.member)
+        ..fileOffset = node.writeOffset;
+    }
+
+    Expression inner;
+    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)
+      //
+      inner = createLet(indexVariable, write);
+    } 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());
+      inner = createLet(
+          indexVariable,
+          createLet(leftVariable,
+              createLet(writeVariable, createVariableGet(leftVariable))));
+    } 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());
+      inner = createLet(
+          indexVariable,
+          createLet(valueVariable,
+              createLet(writeVariable, createVariableGet(valueVariable))));
+    }
+
+    Expression replacement;
+    if (receiverVariable != null) {
+      node.replaceWith(replacement = new Let(receiverVariable, inner)
+        ..fileOffset = node.fileOffset);
+    } else {
+      node.replaceWith(replacement = inner);
+    }
+    return new ExpressionInferenceResult(
+        node.forPostIncDec ? readType : binaryType, replacement);
+  }
+
+  ExpressionInferenceResult visitNullAwareCompoundSet(
+      NullAwareCompoundSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: true);
+    DartType receiverType = receiverResult.inferredType;
+    VariableDeclaration receiverVariable =
+        createVariable(node.receiver, receiverType);
+    Expression readReceiver = createVariableGet(receiverVariable);
+    Expression writeReceiver = createVariableGet(receiverVariable);
+
+    Member equalsMember = inferrer
+        .findInterfaceMember(receiverType, equalsName, node.receiver.fileOffset)
+        .member;
+
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, node.propertyName, node.readOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind readCheckKind =
+        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
+            isThisReceiver: node.receiver is ThisExpression);
+
+    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+
+    Expression read;
+    if (readTarget.isMissing) {
+      read = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments(
+              node.propertyName.name, receiverType),
+          node.readOffset,
+          node.propertyName.name.length);
+    } else if (readTarget.isExtensionMember) {
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            readReceiver,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.readOffset)
+        ..fileOffset = node.readOffset;
+    } else {
+      read = new PropertyGet(readReceiver, node.propertyName, readTarget.member)
+        ..fileOffset = node.readOffset;
+      if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(inferrer.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, readType),
+          node.binaryOffset,
+          node.binaryName.name.length);
     } else if (binaryTarget.isExtensionMember) {
       binary = new StaticInvocation(
           binaryTarget.member,
@@ -2508,28 +3034,16 @@
     }
 
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
-        receiverType, new Name('[]='), node.writeOffset,
-        includeExtensionMethods: true);
+        receiverType, node.propertyName, node.writeOffset,
+        setter: true, 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);
+    DartType valueType = inferrer.getSetterType(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) {
@@ -2543,62 +3057,295 @@
 
     if (writeTarget.isMissing) {
       write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]=', receiverType),
+          templateUndefinedMethod.withArguments(
+              node.propertyName.name, receiverType),
           node.writeOffset,
-          '[]='.length,
-          wrapInSyntheticExpression: false);
+          node.propertyName.name.length);
     } else if (writeTarget.isExtensionMember) {
       write = new StaticInvocation(
           writeTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            writeIndex,
-            valueExpression
-          ], types: writeTarget.inferredExtensionTypeArguments)
+          new Arguments(<Expression>[writeReceiver, 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)
+      write = new PropertySet(
+          writeReceiver, node.propertyName, valueExpression, writeTarget.member)
         ..fileOffset = node.writeOffset;
     }
 
+    DartType resultType = node.forPostIncDec ? readType : binaryType;
+
+    Expression replacement;
     if (node.forEffect) {
       assert(leftVariable == null);
       assert(valueVariable == null);
-      // Encode `o[a] += b` as:
+      // Encode `receiver?.propertyName binaryName= rhs` as:
       //
-      //     let v1 = o in let v2 = a in v1.[]=(v2, v1.[](v2) + b)
+      //     let receiverVariable = receiver in
+      //       receiverVariable == null ? null :
+      //         receiverVariable.propertyName =
+      //             receiverVariable.propertyName + rhs
       //
-      node.replaceWith(replacement =
-          new Let(receiverVariable, createLet(indexVariable, write))
-            ..fileOffset = node.fileOffset);
+
+      MethodInvocation equalsNull = createEqualsNull(
+          receiverVariable.fileOffset,
+          createVariableGet(receiverVariable),
+          equalsMember);
+      ConditionalExpression condition = new ConditionalExpression(equalsNull,
+          new NullLiteral()..fileOffset = node.readOffset, write, resultType);
+      replacement = createLet(receiverVariable, condition);
     } else if (node.forPostIncDec) {
-      // Encode `o[a]++` as:
+      // Encode `receiver?.propertyName binaryName= rhs` from a postfix
+      // expression like `o?.a++` as:
       //
-      //     let v1 = o in
-      //     let v2 = a in
-      //     let v3 = v1.[](v2)
-      //     let v4 = v1.[]=(v2, c3 + b) in v3
+      //     let receiverVariable = receiver in
+      //       receiverVariable == null ? null :
+      //         let leftVariable = receiverVariable.propertyName in
+      //           let writeVariable =
+      //               receiverVariable.propertyName =
+      //                   leftVariable binaryName rhs in
+      //             leftVariable
       //
       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);
+      MethodInvocation equalsNull = createEqualsNull(
+          receiverVariable.fileOffset,
+          createVariableGet(receiverVariable),
+          equalsMember);
+      ConditionalExpression condition = new ConditionalExpression(
+          equalsNull,
+          new NullLiteral()..fileOffset = node.readOffset,
+          createLet(leftVariable,
+              createLet(writeVariable, createVariableGet(leftVariable))),
+          resultType);
+      replacement = createLet(receiverVariable, condition);
     } else {
-      // Encode `o[a] += b` as:
+      // Encode `receiver?.propertyName binaryName= rhs` as:
+      //
+      //     let receiverVariable = receiver in
+      //       receiverVariable == null ? null :
+      //         let leftVariable = receiverVariable.propertyName in
+      //           let valueVariable = leftVariable binaryName rhs in
+      //             let writeVariable =
+      //                 receiverVariable.propertyName = valueVariable in
+      //               valueVariable
+      //
+      // TODO(johnniwinther): Do we need the `leftVariable` in this case?
+      assert(leftVariable == null);
+      assert(valueVariable != null);
+
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      MethodInvocation equalsNull = createEqualsNull(
+          receiverVariable.fileOffset,
+          createVariableGet(receiverVariable),
+          equalsMember);
+      ConditionalExpression condition = new ConditionalExpression(
+          equalsNull,
+          new NullLiteral()..fileOffset = node.readOffset,
+          createLet(valueVariable,
+              createLet(writeVariable, createVariableGet(valueVariable))),
+          resultType);
+      replacement = createLet(receiverVariable, condition);
+    }
+
+    node.replaceWith(replacement);
+    return new ExpressionInferenceResult(resultType, replacement);
+  }
+
+  ExpressionInferenceResult visitCompoundSuperIndexSet(
+      CompoundSuperIndexSet node, DartType typeContext) {
+    ObjectAccessTarget readTarget = node.getter != null
+        ? new ObjectAccessTarget.interfaceMember(node.getter)
+        : const ObjectAccessTarget.missing();
+
+    DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
+    DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
+        readTarget, inferrer.thisType, 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(
+          templateSuperclassHasNoMethod.withArguments('[]'),
+          node.readOffset,
+          '[]'.length);
+    } else {
+      assert(readTarget.isInstanceMember);
+      inferrer.instrumentation?.record(inferrer.uri, node.readOffset, 'target',
+          new InstrumentationValueForMember(node.getter));
+      read = new SuperMethodInvocation(
+          indexGetName,
+          new Arguments(<Expression>[
+            readIndex,
+          ])
+            ..fileOffset = node.readOffset,
+          readTarget.member)
+        ..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, readType),
+          node.binaryOffset,
+          node.binaryName.name.length);
+    } else if (binaryTarget.isExtensionMember) {
+      binary = new StaticInvocation(
+          binaryTarget.member,
+          new Arguments(<Expression>[
+            left,
+            node.rhs,
+          ], types: binaryTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.binaryOffset)
+        ..fileOffset = node.binaryOffset;
+    } else {
+      binary = new MethodInvocation(
+          left,
+          node.binaryName,
+          new Arguments(<Expression>[
+            node.rhs,
+          ])
+            ..fileOffset = node.binaryOffset,
+          binaryTarget.member)
+        ..fileOffset = node.binaryOffset;
+
+      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(inferrer.uri, node.binaryOffset,
+              'checkReturn', new InstrumentationValueForType(readType));
+        }
+        binary = new AsExpression(binary, binaryType)
+          ..isTypeError = true
+          ..fileOffset = node.binaryOffset;
+      }
+    }
+
+    ObjectAccessTarget writeTarget = node.setter != null
+        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        : const ObjectAccessTarget.missing();
+
+    DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
+        writeTarget, inferrer.thisType, 0);
+    Expression writeIndex = createVariableGet(indexVariable);
+    Expression writeIndexReplacement = inferrer.ensureAssignable(writeIndexType,
+        indexResult.inferredType, writeIndex, writeIndex.fileOffset);
+    if (writeIndexReplacement != null) {
+      writeIndex = writeIndexReplacement;
+    }
+
+    DartType valueType =
+        inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
+    Expression binaryReplacement = inferrer.ensureAssignable(
+        valueType, binaryType, binary, node.fileOffset);
+    if (binaryReplacement != null) {
+      binary = binaryReplacement;
+    }
+
+    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(
+          templateSuperclassHasNoMethod.withArguments('[]='),
+          node.writeOffset,
+          '[]='.length);
+    } else {
+      assert(writeTarget.isInstanceMember);
+      inferrer.instrumentation?.record(inferrer.uri, node.writeOffset, 'target',
+          new InstrumentationValueForMember(node.setter));
+      write = new SuperMethodInvocation(
+          indexSetName,
+          new Arguments(<Expression>[writeIndex, valueExpression])
+            ..fileOffset = node.writeOffset,
+          writeTarget.member)
+        ..fileOffset = node.writeOffset;
+    }
+
+    Expression replacement;
+    if (node.forEffect) {
+      assert(leftVariable == null);
+      assert(valueVariable == null);
+      // Encode `super[a] += b` as:
+      //
+      //     let v1 = a in super.[]=(v1, super.[](v1) + b)
+      //
+      replacement = createLet(indexVariable, write);
+    } else if (node.forPostIncDec) {
+      // Encode `super[a]++` as:
+      //
+      //     let v2 = a in
+      //     let v3 = v1.[](v2)
+      //     let v4 = v1.[]=(v2, v3 + 1) in v3
+      //
+      assert(leftVariable != null);
+      assert(valueVariable == null);
+
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      replacement = createLet(
+          indexVariable,
+          createLet(leftVariable,
+              createLet(writeVariable, createVariableGet(leftVariable))));
+    } else {
+      // Encode `super[a] += b` as:
       //
       //     let v1 = o in
       //     let v2 = a in
@@ -2610,14 +3357,13 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      node.replaceWith(replacement = new Let(
-          receiverVariable,
-          createLet(
-              indexVariable,
-              createLet(valueVariable,
-                  createLet(writeVariable, createVariableGet(valueVariable)))))
-        ..fileOffset = node.fileOffset);
+      replacement = createLet(
+          indexVariable,
+          createLet(valueVariable,
+              createLet(writeVariable, createVariableGet(valueVariable))));
     }
+
+    node.replaceWith(replacement);
     return new ExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType, replacement);
   }
@@ -2631,9 +3377,6 @@
   @override
   ExpressionInferenceResult visitLet(Let node, DartType typeContext) {
     DartType variableType = node.variable.type;
-    if (variableType == const DynamicType()) {
-      return defaultExpression(node, typeContext);
-    }
     inferrer.inferExpression(node.variable.initializer, variableType, true,
         isVoidAllowed: true);
     ExpressionInferenceResult result = inferrer
@@ -2644,15 +3387,11 @@
 
   @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;
-    }
+      covariant PropertySetImpl node, DartType typeContext) {
+    DartType receiverType = inferrer
+        .inferExpression(node.receiver, const UnknownType(), true,
+            isVoidAllowed: false)
+        .inferredType;
     ObjectAccessTarget target =
         inferrer.findPropertySetMember(receiverType, node);
     DartType writeContext = inferrer.getSetterType(target, receiverType);
@@ -2665,70 +3404,215 @@
         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])));
+      if (node.forEffect) {
+        replacement = new StaticInvocation(
+            target.member,
+            new Arguments(<Expression>[node.receiver, node.value],
+                types: target.inferredExtensionTypeArguments)
+              ..fileOffset = node.fileOffset)
+          ..fileOffset = node.fileOffset;
+      } else {
+        Expression receiver;
+        VariableDeclaration receiverVariable;
+        if (node.readOnlyReceiver) {
+          receiver = node.receiver;
+        } else {
+          receiverVariable = createVariable(node.receiver, receiverType);
+          receiver = createVariableGet(receiverVariable);
+        }
+        VariableDeclaration valueVariable = createVariable(node.value, rhsType);
+        VariableDeclaration assignmentVariable = createVariable(
+            new StaticInvocation(
+                target.member,
+                new Arguments(
+                    <Expression>[receiver, createVariableGet(valueVariable)],
+                    types: target.inferredExtensionTypeArguments)
+                  ..fileOffset = node.fileOffset)
+              ..fileOffset = node.fileOffset,
+            const VoidType());
+        replacement = createLet(valueVariable,
+            createLet(assignmentVariable, createVariableGet(valueVariable)));
+        if (receiverVariable != null) {
+          replacement = createLet(receiverVariable, replacement);
+        }
+        replacement..fileOffset = node.fileOffset;
+      }
+      node.replaceWith(replacement);
     }
     return new ExpressionInferenceResult(rhsType, replacement);
   }
 
-  ExpressionInferenceResult visitPropertyAssignmentJudgment(
-      PropertyAssignmentJudgment node, DartType typeContext) {
-    DartType receiverType = node._inferReceiver(inferrer);
+  ExpressionInferenceResult visitNullAwareIfNullSet(
+      NullAwareIfNullSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+    DartType receiverType = receiverResult.inferredType;
+    VariableDeclaration receiverVariable =
+        createVariable(node.receiver, receiverType);
+    Expression readReceiver = createVariableGet(receiverVariable);
+    Expression writeReceiver = createVariableGet(receiverVariable);
 
-    DartType readType;
-    if (node.read != null) {
-      ObjectAccessTarget readTarget = inferrer
-          .findPropertyGetMember(receiverType, node.read, instrumented: false);
-      readType = inferrer.getGetterType(readTarget, receiverType);
-      inferrer.handlePropertyGetContravariance(
-          node.receiver,
-          readTarget,
-          node.read is PropertyGet ? node.read : null,
-          node.read,
-          readType,
-          node.read.fileOffset);
-      node._storeLetType(inferrer, node.read, readType);
-    }
-    ObjectAccessTarget writeTarget;
-    if (node.write != null) {
-      writeTarget = node._handleWriteContravariance(inferrer, receiverType);
-    }
-    // To replicate analyzer behavior, we base type inference on the write
-    // member.  TODO(paulberry): would it be better to use the read member when
-    // doing compound assignment?
-    DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
-    DartType inferredType =
-        node._inferRhs(inferrer, readType, writeContext).inferredType;
-    node.nullAwareGuard?.staticType = inferredType;
-    Expression replacement;
-    if (writeTarget.isExtensionMember) {
-      node.parent.replaceChild(
-          node,
-          replacement = inferrer.helper.forest.createStaticInvocation(
-              node.fileOffset,
-              writeTarget.member,
-              inferrer.helper.forest.createArgumentsForExtensionMethod(
-                  node.fileOffset,
-                  writeTarget.inferredExtensionTypeArguments.length,
-                  0,
-                  node.receiver,
-                  extensionTypeArguments:
-                      writeTarget.inferredExtensionTypeArguments,
-                  positionalArguments: [node.rhs])));
+    Member receiverEqualsMember = inferrer
+        .findInterfaceMember(receiverType, equalsName, node.receiver.fileOffset)
+        .member;
+
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, node.name, node.readOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind readCheckKind =
+        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
+            isThisReceiver: node.receiver is ThisExpression);
+
+    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+
+    Member readEqualsMember = inferrer
+        .findInterfaceMember(readType, equalsName, node.testOffset)
+        .member;
+
+    Expression read;
+    if (readTarget.isMissing) {
+      read = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments(node.name.name, receiverType),
+          node.readOffset,
+          node.name.name.length);
+    } else if (readTarget.isExtensionMember) {
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            readReceiver,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.readOffset)
+        ..fileOffset = node.readOffset;
     } else {
-      node._replaceWithDesugared();
+      read = new PropertyGet(readReceiver, node.name, 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 readVariable;
+    if (!node.forEffect) {
+      readVariable = createVariable(read, readType);
+      read = createVariableGet(readVariable);
+    }
+
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, node.name, node.writeOffset,
+        setter: true, includeExtensionMethods: true);
+
+    DartType valueType = inferrer.getSetterType(writeTarget, receiverType);
+
+    ExpressionInferenceResult valueResult = inferrer
+        .inferExpression(node.value, valueType, true, isVoidAllowed: true);
+    inferrer.ensureAssignable(
+        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+
+    Expression write;
+
+    if (writeTarget.isMissing) {
+      write = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments(node.name.name, receiverType),
+          node.writeOffset,
+          node.name.name.length);
+    } else if (writeTarget.isExtensionMember) {
+      if (node.forEffect) {
+        write = new StaticInvocation(
+            writeTarget.member,
+            new Arguments(<Expression>[writeReceiver, node.value],
+                types: writeTarget.inferredExtensionTypeArguments)
+              ..fileOffset = node.writeOffset)
+          ..fileOffset = node.writeOffset;
+      } else {
+        VariableDeclaration valueVariable =
+            createVariable(node.value, valueResult.inferredType);
+        VariableDeclaration assignmentVariable = createVariable(
+            new StaticInvocation(
+                writeTarget.member,
+                new Arguments(<Expression>[
+                  writeReceiver,
+                  createVariableGet(valueVariable)
+                ], types: writeTarget.inferredExtensionTypeArguments)
+                  ..fileOffset = node.writeOffset)
+              ..fileOffset = node.writeOffset,
+            const VoidType());
+        write = createLet(valueVariable,
+            createLet(assignmentVariable, createVariableGet(valueVariable)))
+          ..fileOffset = node.writeOffset;
+      }
+    } else {
+      write = new PropertySet(
+          writeReceiver, node.name, node.value, writeTarget.member)
+        ..fileOffset = node.writeOffset;
+    }
+
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .getStandardUpperBound(readType, valueResult.inferredType);
+
+    Expression replacement;
+    if (node.forEffect) {
+      assert(readVariable == null);
+      // Encode `receiver?.name ??= value` as:
+      //
+      //     let receiverVariable = receiver in
+      //       receiverVariable == null ? null :
+      //         (receiverVariable.name == null ?
+      //           receiverVariable.name = value : null)
+      //
+
+      MethodInvocation receiverEqualsNull = createEqualsNull(
+          receiverVariable.fileOffset,
+          createVariableGet(receiverVariable),
+          receiverEqualsMember);
+      MethodInvocation readEqualsNull =
+          createEqualsNull(node.readOffset, read, readEqualsMember);
+      ConditionalExpression innerCondition = new ConditionalExpression(
+          readEqualsNull,
+          write,
+          new NullLiteral()..fileOffset = node.writeOffset,
+          inferredType);
+      ConditionalExpression outerCondition = new ConditionalExpression(
+          receiverEqualsNull,
+          new NullLiteral()..fileOffset = node.readOffset,
+          innerCondition,
+          inferredType);
+      replacement = createLet(receiverVariable, outerCondition);
+    } else {
+      // Encode `receiver?.name ??= value` as:
+      //
+      //     let receiverVariable = receiver in
+      //       receiverVariable == null ? null :
+      //         (let readVariable = receiverVariable.name in
+      //           readVariable == null ?
+      //             receiverVariable.name = value : readVariable)
+      //
+      assert(readVariable != null);
+
+      MethodInvocation receiverEqualsNull = createEqualsNull(
+          receiverVariable.fileOffset,
+          createVariableGet(receiverVariable),
+          receiverEqualsMember);
+      MethodInvocation readEqualsNull =
+          createEqualsNull(receiverVariable.fileOffset, read, readEqualsMember);
+      ConditionalExpression innerCondition = new ConditionalExpression(
+          readEqualsNull, write, createVariableGet(readVariable), inferredType);
+      ConditionalExpression outerCondition = new ConditionalExpression(
+          receiverEqualsNull,
+          new NullLiteral()..fileOffset = node.readOffset,
+          createLet(readVariable, innerCondition),
+          inferredType);
+      replacement = createLet(receiverVariable, outerCondition);
+    }
+
+    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2880,28 +3764,6 @@
     return new ExpressionInferenceResult(rhsType);
   }
 
-  ExpressionInferenceResult visitStaticAssignmentJudgment(
-      StaticAssignmentJudgment node, DartType typeContext) {
-    DartType readType = const DynamicType(); // Only used in error recovery
-    Expression read = node.read;
-    if (read is StaticGet) {
-      readType = read.target.getterType;
-      node._storeLetType(inferrer, read, readType);
-    }
-    Member writeMember;
-    DartType writeContext = const UnknownType();
-    Expression write = node.write;
-    if (write is StaticSet) {
-      writeContext = write.target.setterType;
-      writeMember = write.target;
-      TypeInferenceEngine.resolveInferenceNode(writeMember);
-    }
-    DartType inferredType =
-        node._inferRhs(inferrer, readType, writeContext).inferredType;
-    node._replaceWithDesugared();
-    return new ExpressionInferenceResult(inferredType);
-  }
-
   @override
   ExpressionInferenceResult visitStaticGet(
       StaticGet node, DartType typeContext) {
@@ -2940,7 +3802,8 @@
     if (!inferrer.isTopLevel) {
       for (Expression expression in node.expressions) {
         inferrer.inferExpression(
-            expression, const UnknownType(), !inferrer.isTopLevel);
+            expression, const UnknownType(), !inferrer.isTopLevel,
+            isVoidAllowed: false);
       }
     }
     return new ExpressionInferenceResult(
@@ -3027,13 +3890,15 @@
   @override
   void visitSwitchStatement(SwitchStatement node) {
     DartType expressionType = inferrer
-        .inferExpression(node.expression, const UnknownType(), true)
+        .inferExpression(node.expression, const UnknownType(), true,
+            isVoidAllowed: false)
         .inferredType;
 
     for (SwitchCase switchCase in node.cases) {
       for (Expression caseExpression in switchCase.expressions) {
         ExpressionInferenceResult caseExpressionResult =
-            inferrer.inferExpression(caseExpression, expressionType, true);
+            inferrer.inferExpression(caseExpression, expressionType, true,
+                isVoidAllowed: false);
         if (caseExpressionResult.replacement != null) {
           caseExpression = caseExpressionResult.replacement;
         }
@@ -3065,41 +3930,6 @@
     return new ExpressionInferenceResult(inferredType);
   }
 
-  ExpressionInferenceResult visitInvalidConstructorInvocationJudgment(
-      InvalidConstructorInvocationJudgment node, DartType typeContext) {
-    FunctionType calleeType;
-    DartType returnType;
-    if (node.constructor != null) {
-      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.arguments);
-    node._replaceWithDesugared();
-    return new ExpressionInferenceResult(inferredType);
-  }
-
-  ExpressionInferenceResult visitInvalidWriteJudgment(
-      InvalidWriteJudgment node, DartType typeContext) {
-    // When a compound assignment, the expression is already wrapping in
-    // VariableDeclaration in _makeRead(). Otherwise, temporary associate
-    // the expression with this node.
-    node.expression.parent ??= node;
-
-    inferrer.inferExpression(
-        node.expression, const UnknownType(), !inferrer.isTopLevel);
-    return visitSyntheticExpressionJudgment(node, typeContext);
-  }
-
-  ExpressionInferenceResult visitSyntheticExpressionJudgment(
-      SyntheticExpressionJudgment node, DartType typeContext) {
-    node._replaceWithDesugared();
-    return const ExpressionInferenceResult(const DynamicType());
-  }
-
   ExpressionInferenceResult visitThisExpression(
       ThisExpression node, DartType typeContext) {
     return new ExpressionInferenceResult(inferrer.thisType);
@@ -3108,7 +3938,8 @@
   @override
   ExpressionInferenceResult visitThrow(Throw node, DartType typeContext) {
     inferrer.inferExpression(
-        node.expression, const UnknownType(), !inferrer.isTopLevel);
+        node.expression, const UnknownType(), !inferrer.isTopLevel,
+        isVoidAllowed: false);
     return const ExpressionInferenceResult(const BottomType());
   }
 
@@ -3152,27 +3983,6 @@
     return new ExpressionInferenceResult(rhsType);
   }
 
-  ExpressionInferenceResult visitVariableAssignmentJudgment(
-      VariableAssignmentJudgment node, DartType typeContext) {
-    DartType readType;
-    Expression read = node.read;
-    if (read is VariableGet) {
-      readType = read.promotedType ?? read.variable.type;
-    }
-    DartType writeContext = const UnknownType();
-    Expression write = node.write;
-    if (write is VariableSet) {
-      writeContext = write.variable.type;
-      if (read != null) {
-        node._storeLetType(inferrer, read, writeContext);
-      }
-    }
-    DartType inferredType =
-        node._inferRhs(inferrer, readType, writeContext).inferredType;
-    node._replaceWithDesugared();
-    return new ExpressionInferenceResult(inferredType);
-  }
-
   @override
   void visitVariableDeclaration(covariant VariableDeclarationImpl node) {
     DartType declaredType =
@@ -3213,29 +4023,6 @@
     }
   }
 
-  ExpressionInferenceResult visitUnresolvedTargetInvocationJudgment(
-      UnresolvedTargetInvocationJudgment node, DartType typeContext) {
-    ExpressionInferenceResult result =
-        visitSyntheticExpressionJudgment(node, typeContext);
-    inferrer.inferInvocation(
-        typeContext,
-        node.fileOffset,
-        TypeInferrerImpl.unknownFunction,
-        const DynamicType(),
-        node.argumentsJudgment);
-    return result;
-  }
-
-  ExpressionInferenceResult visitUnresolvedVariableAssignmentJudgment(
-      UnresolvedVariableAssignmentJudgment node, DartType typeContext) {
-    DartType rhsType = inferrer
-        .inferExpression(node.rhs, const UnknownType(), true)
-        .inferredType;
-    DartType inferredType = node.isCompound ? const DynamicType() : rhsType;
-    node._replaceWithDesugared();
-    return new ExpressionInferenceResult(inferredType);
-  }
-
   @override
   ExpressionInferenceResult visitVariableGet(
       covariant VariableGetImpl node, DartType typeContext) {
@@ -3262,7 +4049,8 @@
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
+            isVoidAllowed: false)
         .inferredType;
     inferrer.ensureAssignable(
         expectedType, conditionType, node.condition, node.condition.fileOffset);
@@ -3283,11 +4071,13 @@
                 : inferrer.coreTypes.iterableClass);
       }
       inferredType = inferrer
-          .inferExpression(node.expression, typeContext, true)
+          .inferExpression(node.expression, typeContext, true,
+              isVoidAllowed: true)
           .inferredType;
     } else {
       inferredType = inferrer
-          .inferExpression(node.expression, const UnknownType(), true)
+          .inferExpression(node.expression, const UnknownType(), true,
+              isVoidAllowed: true)
           .inferredType;
     }
     closureContext.handleYield(inferrer, node.isYieldStar, inferredType,
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 65f8ccf..975c09a 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
@@ -86,11 +86,9 @@
     show
         ArgumentsImpl,
         Cascade,
-        ComplexAssignmentJudgment,
         DeferredCheck,
         FactoryConstructorInvocationJudgment,
         FunctionDeclarationImpl,
-        IfNullJudgment,
         InvalidSuperInitializerJudgment,
         LoadLibraryTearOff,
         MethodInvocationImpl,
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 99d2714..294aa54 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
@@ -24,6 +24,8 @@
 
 import 'package:kernel/type_algebra.dart' show Substitution;
 
+import 'package:kernel/clone.dart';
+
 import '../../base/instrumentation.dart'
     show
         Instrumentation,
@@ -50,11 +52,14 @@
         templateSpreadMapEntryElementValueTypeMismatch,
         templateSpreadMapEntryTypeMismatch,
         templateSpreadTypeMismatch,
+        templateSuperclassHasNoMethod,
         templateSwitchExpressionNotAssignable,
         templateUndefinedMethod,
         templateWebLiteralCannotBeRepresentedExactly;
 
-import '../problems.dart' show getFileUri, unhandled, unsupported;
+import '../names.dart';
+
+import '../problems.dart' show unhandled, unsupported;
 
 import '../source/source_class_builder.dart' show SourceClassBuilder;
 
@@ -75,7 +80,7 @@
 import '../type_inference/type_schema_elimination.dart' show greatestClosure;
 
 import '../type_inference/type_schema_environment.dart'
-    show TypeSchemaEnvironment, getPositionalParameterType;
+    show TypeSchemaEnvironment;
 
 import 'body_builder.dart' show combineStatements;
 
@@ -181,18 +186,26 @@
   Cascade,
   CompoundIndexSet,
   CompoundPropertySet,
+  CompoundSuperIndexSet,
   DeferredCheck,
+  ExtensionSet,
+  IfNull,
   IfNullIndexSet,
   IfNullPropertySet,
   IfNullSet,
+  IfNullSuperIndexSet,
   IndexSet,
   LoadLibraryTearOff,
   LocalPostIncDec,
+  NullAwareCompoundSet,
+  NullAwareExtension,
+  NullAwareIfNullSet,
   NullAwareMethodInvocation,
   NullAwarePropertyGet,
   NullAwarePropertySet,
   PropertyPostIncDec,
   StaticPostIncDec,
+  SuperIndexSet,
   SuperPostIncDec,
 }
 
@@ -387,216 +400,6 @@
   }
 }
 
-/// Abstract shadow object representing a complex assignment in kernel form.
-///
-/// Since there are many forms a complex assignment might have been desugared
-/// to, this class wraps the desugared assignment rather than extending it.
-///
-/// TODO(paulberry): once we know exactly what constitutes a "complex
-/// assignment", document it here.
-abstract class ComplexAssignmentJudgment extends SyntheticExpressionJudgment {
-  /// In a compound assignment, the expression that reads the old value, or
-  /// `null` if this is not a compound assignment.
-  Expression read;
-
-  /// The expression appearing on the RHS of the assignment.
-  Expression rhs;
-
-  /// The expression that performs the write (e.g. `a.[]=(b, a.[](b) + 1)` in
-  /// `++a[b]`).
-  Expression write;
-
-  /// In a compound assignment without shortcut semantics, the expression that
-  /// combines the old and new values, or `null` if this is not a compound
-  /// assignment.
-  ///
-  /// Note that in a compound assignment with shortcut semantics, this is not
-  /// used; [nullAwareCombiner] is used instead.
-  MethodInvocation combiner;
-
-  /// In a compound assignment with shortcut semantics, the conditional
-  /// expression that determines whether the assignment occurs.
-  ///
-  /// Note that in a compound assignment without shortcut semantics, this is not
-  /// used; [combiner] is used instead.
-  ConditionalExpression nullAwareCombiner;
-
-  /// Indicates whether the expression arose from a post-increment or
-  /// post-decrement.
-  bool isPostIncDec = false;
-
-  /// Indicates whether the expression arose from a pre-increment or
-  /// pre-decrement.
-  bool isPreIncDec = false;
-
-  ComplexAssignmentJudgment._(this.rhs) : super._(null);
-
-  String toString() {
-    List<String> parts = _getToStringParts();
-    return '${runtimeType}(${parts.join(', ')})';
-  }
-
-  List<String> _getToStringParts() {
-    List<String> parts = [];
-    if (desugared != null) parts.add('desugared=$desugared');
-    if (read != null) parts.add('read=$read');
-    if (rhs != null) parts.add('rhs=$rhs');
-    if (write != null) parts.add('write=$write');
-    if (combiner != null) parts.add('combiner=$combiner');
-    if (nullAwareCombiner != null) {
-      parts.add('nullAwareCombiner=$nullAwareCombiner');
-    }
-    if (isPostIncDec) parts.add('isPostIncDec=true');
-    if (isPreIncDec) parts.add('isPreIncDec=true');
-    return parts;
-  }
-
-  _ComplexAssignmentInferenceResult _inferRhs(
-      ShadowTypeInferrer inferrer, DartType readType, DartType writeContext) {
-    assert(writeContext != null);
-    if (readType is VoidType &&
-        (combiner != null || nullAwareCombiner != null)) {
-      inferrer.helper
-          ?.addProblem(messageVoidExpression, read.fileOffset, noLength);
-    }
-    int writeOffset = write == null ? -1 : write.fileOffset;
-    ObjectAccessTarget combinerTarget = const ObjectAccessTarget.unresolved();
-    DartType combinedType;
-    if (combiner != null) {
-      bool isOverloadedArithmeticOperator = false;
-      combinerTarget = inferrer.findMethodInvocationMember(readType, combiner,
-          instrumented: false);
-      assert(!combinerTarget.isCallFunction);
-      if (combinerTarget.isInstanceMember &&
-          combinerTarget.member is Procedure) {
-        isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
-            .isOverloadedArithmeticOperatorAndType(
-                combinerTarget.member, readType);
-      }
-      DartType rhsType;
-      FunctionType combinerType =
-          inferrer.getFunctionType(combinerTarget, readType, false);
-      if (isPreIncDec || isPostIncDec) {
-        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
-        // temporary variable first.
-        assert(identical(combiner.arguments.positional.first, rhs));
-        // Analyzer uses a null context for the RHS here.
-        // TODO(paulberry): improve on this.
-        ExpressionInferenceResult rhsResult =
-            inferrer.inferExpression(rhs, const UnknownType(), true);
-        if (rhsResult.replacement != null) {
-          rhs = rhsResult.replacement;
-        }
-        rhsType = rhsResult.inferredType;
-        // Do not use rhs after this point because it may be a Shadow node
-        // that has been replaced in the tree with its desugaring.
-        DartType expectedType = getPositionalParameterType(combinerType, 0);
-        inferrer.ensureAssignable(expectedType, rhsType,
-            combiner.arguments.positional.first, combiner.fileOffset);
-      }
-      if (isOverloadedArithmeticOperator) {
-        combinedType = inferrer.typeSchemaEnvironment
-            .getTypeOfOverloadedArithmetic(readType, rhsType);
-      } else {
-        combinedType = combinerType.returnType;
-      }
-      MethodContravarianceCheckKind checkKind =
-          inferrer.preCheckInvocationContravariance(readType, combinerTarget,
-              isThisReceiver: read is ThisExpression);
-      Expression replacedCombiner = inferrer.handleInvocationContravariance(
-          checkKind,
-          combiner,
-          combiner.arguments,
-          combiner,
-          combinedType,
-          combinerType,
-          combiner.fileOffset);
-      Expression replacedCombiner2 = inferrer.ensureAssignable(
-          writeContext, combinedType, replacedCombiner, writeOffset);
-      if (replacedCombiner2 != null) {
-        replacedCombiner = replacedCombiner2;
-      }
-      _storeLetType(inferrer, replacedCombiner, combinedType);
-    } else {
-      ExpressionInferenceResult rhsResult = inferrer.inferExpression(
-          rhs, writeContext ?? const UnknownType(), true,
-          isVoidAllowed: true);
-      if (rhsResult.replacement != null) {
-        rhs = rhsResult.replacement;
-      }
-      DartType rhsType = rhsResult.inferredType;
-      Expression replacedRhs = inferrer.ensureAssignable(
-          writeContext, rhsType, rhs, writeOffset,
-          isVoidAllowed: writeContext is VoidType);
-      _storeLetType(inferrer, replacedRhs ?? rhs, rhsType);
-      if (nullAwareCombiner != null) {
-        MethodInvocation equalsInvocation = nullAwareCombiner.condition;
-        inferrer.findMethodInvocationMember(
-            greatestClosure(inferrer.coreTypes, writeContext), equalsInvocation,
-            instrumented: false);
-        // Note: the case of readType=null only happens for erroneous code.
-        combinedType = readType == null
-            ? rhsType
-            : inferrer.typeSchemaEnvironment
-                .getStandardUpperBound(readType, rhsType);
-        nullAwareCombiner.staticType = combinedType;
-      } else {
-        combinedType = rhsType;
-      }
-    }
-    if (this is IndexAssignmentJudgment) {
-      _storeLetType(inferrer, write, const VoidType());
-    } else {
-      _storeLetType(inferrer, write, combinedType);
-    }
-    DartType inferredType =
-        isPostIncDec ? (readType ?? const DynamicType()) : combinedType;
-    return new _ComplexAssignmentInferenceResult(
-        combinerTarget.member, inferredType);
-  }
-}
-
-/// Abstract shadow object representing a complex assignment involving a
-/// receiver.
-abstract class ComplexAssignmentJudgmentWithReceiver
-    extends ComplexAssignmentJudgment {
-  /// The receiver of the assignment target (e.g. `a` in `a[b] = c`).
-  final Expression receiver;
-
-  /// Indicates whether this assignment uses `super`.
-  final bool isSuper;
-
-  ComplexAssignmentJudgmentWithReceiver._(
-      this.receiver, Expression rhs, this.isSuper)
-      : super._(rhs);
-
-  @override
-  List<String> _getToStringParts() {
-    List<String> parts = super._getToStringParts();
-    if (receiver != null) parts.add('receiver=$receiver');
-    if (isSuper) parts.add('isSuper=true');
-    return parts;
-  }
-
-  DartType _inferReceiver(ShadowTypeInferrer inferrer) {
-    if (receiver != null) {
-      DartType receiverType = inferrer
-          .inferExpression(receiver, const UnknownType(), true)
-          .inferredType;
-      _storeLetType(inferrer, receiver, receiverType);
-      return receiverType;
-    } else if (isSuper) {
-      return inferrer.classHierarchy.getTypeAsInstanceOf(
-          inferrer.thisType, inferrer.thisType.classNode.supertype.classNode);
-    } else {
-      return inferrer.thisType;
-    }
-  }
-}
-
 /// Internal expression representing a deferred check.
 // TODO(johnniwinther): Change the representation to be direct and perform
 // the [Let] encoding in [replace].
@@ -695,84 +498,40 @@
   }
 }
 
-/// Concrete shadow object representing an if-null expression.
+/// Internal expression representing an if-null expression.
 ///
-/// An if-null expression of the form `a ?? b` is represented as the kernel
-/// expression:
+/// An if-null expression of the form `a ?? b` is encoded as:
 ///
 ///     let v = a in v == null ? b : v
-class IfNullJudgment extends Let implements ExpressionJudgment {
-  IfNullJudgment(VariableDeclaration variable, Expression body)
-      : super(variable, body);
+///
+class IfNullExpression extends InternalExpression {
+  Expression left;
+  Expression right;
 
-  @override
-  ConditionalExpression get body => super.body;
-
-  /// Returns the expression to the left of `??`.
-  Expression get left => variable.initializer;
-
-  /// Returns the expression to the right of `??`.
-  Expression get right => body.then;
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitIfNullJudgment(this, typeContext);
-  }
-}
-
-/// Concrete shadow object representing an assignment to a target for which
-/// assignment is not allowed.
-class IllegalAssignmentJudgment extends ComplexAssignmentJudgment {
-  /// The offset at which the invalid assignment should be stored.
-  /// If `-1`, then there is no separate location for invalid assignment.
-  final int assignmentOffset;
-
-  IllegalAssignmentJudgment._(Expression rhs, {this.assignmentOffset: -1})
-      : super._(rhs) {
-    rhs.parent = this;
+  IfNullExpression(this.left, this.right) {
+    left?.parent = this;
+    right?.parent = this;
   }
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitIllegalAssignmentJudgment(this, typeContext);
+  InternalExpressionKind get kind => InternalExpressionKind.IfNull;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    left?.accept(v);
+    right?.accept(v);
   }
-}
 
-/// Concrete shadow object representing an assignment to a target of the form
-/// `a[b]`.
-class IndexAssignmentJudgment extends ComplexAssignmentJudgmentWithReceiver {
-  /// In an assignment to an index expression, the index expression.
-  Expression index;
-
-  IndexAssignmentJudgment._(Expression receiver, this.index, Expression rhs,
-      {bool isSuper: false})
-      : super._(receiver, rhs, isSuper);
-
-  Arguments _getInvocationArguments(
-      ShadowTypeInferrer inferrer, Expression invocation) {
-    if (invocation is MethodInvocation) {
-      return invocation.arguments;
-    } else if (invocation is SuperMethodInvocation) {
-      return invocation.arguments;
-    } else {
-      throw unhandled("${invocation.runtimeType}", "_getInvocationArguments",
-          fileOffset, inferrer.uri);
+  @override
+  void transformChildren(Transformer v) {
+    if (left != null) {
+      left = left.accept<TreeNode>(v);
+      left?.parent = this;
     }
-  }
-
-  @override
-  List<String> _getToStringParts() {
-    List<String> parts = super._getToStringParts();
-    if (index != null) parts.add('index=$index');
-    return parts;
-  }
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitIndexAssignmentJudgment(this, typeContext);
+    if (right != null) {
+      right = right.accept<TreeNode>(v);
+      right?.parent = this;
+    }
   }
 }
 
@@ -798,12 +557,10 @@
       ? '0x${asDouble.toRadixString(16)}'
       : asDouble.toString();
   int length = literal?.length ?? noLength;
-  return inferrer.helper.desugarSyntheticExpression(inferrer.helper
-      .buildProblem(
-          templateWebLiteralCannotBeRepresentedExactly.withArguments(
-              text, nearest),
-          charOffset,
-          length));
+  return inferrer.helper.buildProblem(
+      templateWebLiteralCannotBeRepresentedExactly.withArguments(text, nearest),
+      charOffset,
+      length);
 }
 
 /// Concrete shadow object representing an integer literal in kernel form.
@@ -1039,35 +796,6 @@
   }
 }
 
-/// Concrete shadow object representing an assignment to a property.
-class PropertyAssignmentJudgment extends ComplexAssignmentJudgmentWithReceiver {
-  /// If this assignment uses null-aware access (`?.`), the conditional
-  /// expression that guards the access; otherwise `null`.
-  ConditionalExpression nullAwareGuard;
-
-  PropertyAssignmentJudgment._(Expression receiver, Expression rhs,
-      {bool isSuper: false})
-      : super._(receiver, rhs, isSuper);
-
-  @override
-  List<String> _getToStringParts() {
-    List<String> parts = super._getToStringParts();
-    if (nullAwareGuard != null) parts.add('nullAwareGuard=$nullAwareGuard');
-    return parts;
-  }
-
-  ObjectAccessTarget _handleWriteContravariance(
-      ShadowTypeInferrer inferrer, DartType receiverType) {
-    return inferrer.findPropertySetMember(receiverType, write);
-  }
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitPropertyAssignmentJudgment(this, typeContext);
-  }
-}
-
 /// Front end specific implementation of [ReturnStatement].
 class ReturnStatementImpl extends ReturnStatement {
   final bool isArrow;
@@ -1076,140 +804,6 @@
       : super(expression);
 }
 
-/// Concrete shadow object representing an assignment to a static variable.
-class StaticAssignmentJudgment extends ComplexAssignmentJudgment {
-  StaticAssignmentJudgment._(Expression rhs) : super._(rhs);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitStaticAssignmentJudgment(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.
-// TODO(ahe): Remove this?
-class InvalidConstructorInvocationJudgment extends SyntheticExpressionJudgment {
-  final Member constructor;
-  final Arguments arguments;
-
-  InvalidConstructorInvocationJudgment._(
-      Expression desugared, this.constructor, this.arguments)
-      : super._(desugared);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitInvalidConstructorInvocationJudgment(this, typeContext);
-  }
-}
-
-/// Synthetic judgment class representing an attempt to assign to the
-/// [expression] which is not assignable.
-class InvalidWriteJudgment extends SyntheticExpressionJudgment {
-  final Expression expression;
-
-  InvalidWriteJudgment._(Expression desugared, this.expression)
-      : super._(desugared);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitInvalidWriteJudgment(this, typeContext);
-  }
-}
-
-/// Shadow object for expressions that are introduced by the front end as part
-/// of desugaring or the handling of error conditions.
-///
-/// These expressions are removed by type inference and replaced with their
-/// desugared equivalents.
-class SyntheticExpressionJudgment extends Let implements ExpressionJudgment {
-  SyntheticExpressionJudgment._(Expression desugared)
-      : super(new VariableDeclaration('_', initializer: new NullLiteral()),
-            desugared);
-
-  /// The desugared kernel representation of this synthetic expression.
-  Expression get desugared => body;
-
-  void set desugared(Expression value) {
-    this.body = value;
-    value.parent = this;
-  }
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitSyntheticExpressionJudgment(this, typeContext);
-  }
-
-  /// Removes this expression from the expression tree, replacing it with
-  /// [desugared].
-  Expression _replaceWithDesugared() {
-    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 replacement;
-  }
-
-  /// Updates any [Let] nodes in the desugared expression to account for the
-  /// fact that [expression] has the given [type].
-  void _storeLetType(
-      TypeInferrerImpl inferrer, Expression expression, DartType type) {
-    Expression desugared = this.desugared;
-    while (true) {
-      if (desugared is Let) {
-        Let desugaredLet = desugared;
-        VariableDeclaration variable = desugaredLet.variable;
-        if (identical(variable.initializer, expression)) {
-          variable.type = type;
-          return;
-        }
-        desugared = desugaredLet.body;
-      } else if (desugared is ConditionalExpression) {
-        // When a null-aware assignment is desugared, often the "then" or "else"
-        // branch of the conditional expression often contains "let" nodes that
-        // need to be updated.
-        ConditionalExpression desugaredConditionalExpression = desugared;
-        if (desugaredConditionalExpression.then is Let) {
-          desugared = desugaredConditionalExpression.then;
-        } else {
-          desugared = desugaredConditionalExpression.otherwise;
-        }
-      } else {
-        break;
-      }
-    }
-  }
-
-  @override
-  R accept<R>(ExpressionVisitor<R> v) {
-    // This is designed to throw an exception during serialization. It can also
-    // 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("${runtimeType}.accept", fileOffset, getFileUri(this));
-  }
-
-  @override
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) {
-    throw unsupported("${runtimeType}.accept1", fileOffset, getFileUri(this));
-  }
-
-  @override
-  visitChildren(Visitor<dynamic> v) {
-    unsupported("${runtimeType}.visitChildren", fileOffset, getFileUri(this));
-  }
-}
-
 /// Concrete implementation of [TypeInferenceEngine] specialized to work with
 /// kernel objects.
 class ShadowTypeInferenceEngine extends TypeInferenceEngine {
@@ -1381,16 +975,6 @@
   }
 }
 
-class VariableAssignmentJudgment extends ComplexAssignmentJudgment {
-  VariableAssignmentJudgment._(Expression rhs) : super._(rhs);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitVariableAssignmentJudgment(this, typeContext);
-  }
-}
-
 /// Front end specific implementation of [VariableDeclaration].
 class VariableDeclarationImpl extends VariableDeclaration {
   final bool forSyntheticToken;
@@ -1467,39 +1051,6 @@
       variable._isLocalFunction;
 }
 
-/// Synthetic judgment class representing an attempt to invoke an unresolved
-/// target.
-class UnresolvedTargetInvocationJudgment extends SyntheticExpressionJudgment {
-  final ArgumentsImpl argumentsJudgment;
-
-  UnresolvedTargetInvocationJudgment._(
-      Expression desugared, this.argumentsJudgment)
-      : super._(desugared);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitUnresolvedTargetInvocationJudgment(this, typeContext);
-  }
-}
-
-/// Synthetic judgment class representing an attempt to assign to an unresolved
-/// variable.
-class UnresolvedVariableAssignmentJudgment extends SyntheticExpressionJudgment {
-  final bool isCompound;
-  final Expression rhs;
-
-  UnresolvedVariableAssignmentJudgment._(
-      Expression desugared, this.isCompound, this.rhs)
-      : super._(desugared);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitUnresolvedVariableAssignmentJudgment(this, typeContext);
-  }
-}
-
 /// Front end specific implementation of [VariableGet].
 class VariableGetImpl extends VariableGet {
   final TypePromotionFact _fact;
@@ -1552,18 +1103,6 @@
   }
 }
 
-/// The result of inference for a RHS of an assignment.
-class _ComplexAssignmentInferenceResult {
-  /// The resolved combiner [Procedure], e.g. `operator+` for `a += 2`, or
-  /// `null` if the assignment is not compound.
-  final Procedure combiner;
-
-  /// The inferred type of the RHS.
-  final DartType inferredType;
-
-  _ComplexAssignmentInferenceResult(this.combiner, this.inferredType);
-}
-
 class _UnfinishedCascade extends Expression {
   R accept<R>(v) => unsupported("accept", -1, null);
 
@@ -1576,67 +1115,6 @@
   void visitChildren(v) => unsupported("visitChildren", -1, null);
 }
 
-class SyntheticWrapper {
-  static Expression wrapIllegalAssignment(Expression rhs,
-      {int assignmentOffset: -1}) {
-    return new IllegalAssignmentJudgment._(rhs,
-        assignmentOffset: assignmentOffset)
-      ..fileOffset = rhs.fileOffset;
-  }
-
-  static Expression wrapIndexAssignment(
-      Expression receiver, Expression index, Expression rhs,
-      {bool isSuper: false}) {
-    return new IndexAssignmentJudgment._(receiver, index, rhs, isSuper: isSuper)
-      ..fileOffset = index.fileOffset;
-  }
-
-  static Expression wrapInvalidConstructorInvocation(
-      Expression desugared, Member constructor, Arguments arguments) {
-    return new InvalidConstructorInvocationJudgment._(
-        desugared, constructor, arguments)
-      ..fileOffset = desugared.fileOffset;
-  }
-
-  static Expression wrapInvalidWrite(
-      Expression desugared, Expression expression) {
-    return new InvalidWriteJudgment._(desugared, expression)
-      ..fileOffset = desugared.fileOffset;
-  }
-
-  static Expression wrapPropertyAssignment(Expression receiver, Expression rhs,
-      {bool isSuper: false}) {
-    return new PropertyAssignmentJudgment._(receiver, rhs, isSuper: isSuper)
-      ..fileOffset = rhs.fileOffset;
-  }
-
-  static Expression wrapStaticAssignment(Expression rhs) {
-    return new StaticAssignmentJudgment._(rhs)..fileOffset = rhs.fileOffset;
-  }
-
-  static Expression wrapSyntheticExpression(Expression desugared) {
-    return new SyntheticExpressionJudgment._(desugared)
-      ..fileOffset = desugared.fileOffset;
-  }
-
-  static Expression wrapUnresolvedTargetInvocation(
-      Expression desugared, Arguments arguments) {
-    return new UnresolvedTargetInvocationJudgment._(desugared, arguments)
-      ..fileOffset = desugared.fileOffset;
-  }
-
-  static Expression wrapUnresolvedVariableAssignment(
-      Expression desugared, bool isCompound, Expression rhs) {
-    return new UnresolvedVariableAssignmentJudgment._(
-        desugared, isCompound, rhs)
-      ..fileOffset = desugared.fileOffset;
-  }
-
-  static Expression wrapVariableAssignment(Expression rhs) {
-    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,
@@ -1803,6 +1281,9 @@
 ///
 class PropertyPostIncDec extends InternalExpression {
   /// The synthetic variable whose initializer hold the receiver.
+  ///
+  /// This is `null` if the receiver is read-only and therefore does not need to
+  /// be stored in a temporary variable.
   VariableDeclaration variable;
 
   /// The expression that reads the property on [variable].
@@ -1818,15 +1299,25 @@
     write?.parent = this;
   }
 
+  PropertyPostIncDec.onReadOnly(
+      VariableDeclaration read, VariableDeclaration write)
+      : this(null, read, write);
+
   @override
   InternalExpressionKind get kind => InternalExpressionKind.PropertyPostIncDec;
 
   @override
   Expression replace() {
     Expression replacement;
-    replaceWith(replacement = new Let(
-        variable, createLet(read, createLet(write, createVariableGet(read))))
-      ..fileOffset = fileOffset);
+    if (variable != null) {
+      replaceWith(replacement = new Let(
+          variable, createLet(read, createLet(write, createVariableGet(read))))
+        ..fileOffset = fileOffset);
+    } else {
+      replaceWith(
+          replacement = new Let(read, createLet(write, createVariableGet(read)))
+            ..fileOffset = fileOffset);
+    }
     return replacement;
   }
 
@@ -2026,6 +1517,7 @@
   /// The value expression of the operation.
   Expression value;
 
+  // TODO(johnniwinther): Add `readOnlyReceiver` capability.
   IndexSet(this.receiver, this.index, this.value) {
     receiver?.parent = this;
     index?.parent = this;
@@ -2059,6 +1551,56 @@
   }
 }
 
+/// Internal expression representing a  super index set expression.
+///
+/// A super index set expression of the form `super[a] = b` used for value is
+/// encoded as the expression:
+///
+///     let v1 = a in let v2 = b in let _ = super.[]=(v1, v2) in v2
+///
+/// An index set expression used for effect is encoded as
+///
+///    super.[]=(a, b)
+///
+/// using [SuperMethodInvocation].
+///
+class SuperIndexSet extends InternalExpression {
+  /// The []= member.
+  Member setter;
+
+  /// The index expression of the operation.
+  Expression index;
+
+  /// The value expression of the operation.
+  Expression value;
+
+  SuperIndexSet(this.setter, this.index, this.value) {
+    index?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.SuperIndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    index?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    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,
@@ -2080,6 +1622,8 @@
 ///     let v3 = v1[v2] in
 ///        v3 == null ? v1.[]=(v2, b) : null
 ///
+/// If the [readOnlyReceiver] is true, no temporary variable is created for the
+/// receiver and its use is inlined.
 class IfNullIndexSet extends InternalExpression {
   /// The receiver on which the index set operation is performed.
   Expression receiver;
@@ -2093,12 +1637,29 @@
   /// The file offset for the [] operation.
   final int readOffset;
 
+  /// The file offset for the == operation.
+  final int testOffset;
+
+  /// The file offset for the []= operation.
+  final int writeOffset;
+
   /// 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) {
+  /// If `true`, the receiver is read-only and therefore doesn't need a
+  /// temporary variable for its value.
+  final bool readOnlyReceiver;
+
+  IfNullIndexSet(this.receiver, this.index, this.value,
+      {this.readOffset,
+      this.testOffset,
+      this.writeOffset,
+      this.forEffect,
+      this.readOnlyReceiver: false})
+      : assert(readOffset != null),
+        assert(testOffset != null),
+        assert(writeOffset != null),
+        assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
@@ -2131,7 +1692,83 @@
   }
 }
 
-/// Internal expression representing an if-null index assignment.
+/// Internal expression representing an if-null super index set expression.
+///
+/// An if-null super index set expression of the form `super[a] ??= b` is, if
+/// used for value, encoded as the expression:
+///
+///     let v1 = a in
+///     let v2 = super.[](v1) in
+///       v2 == null
+///        ? (let v3 = b in
+///           let _ = super.[]=(v1, v3) in
+///           v3)
+///        : v2
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let v1 = a in
+///     let v2 = super.[](v1) in
+///        v2 == null ? super.[]=(v1, b) : null
+///
+class IfNullSuperIndexSet extends InternalExpression {
+  /// The [] member;
+  Member getter;
+
+  /// The []= member;
+  Member setter;
+
+  /// 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;
+
+  /// The file offset for the == operation.
+  final int testOffset;
+
+  /// The file offset for the []= operation.
+  final int writeOffset;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  IfNullSuperIndexSet(this.getter, this.setter, this.index, this.value,
+      {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
+      : assert(readOffset != null),
+        assert(testOffset != null),
+        assert(writeOffset != null),
+        assert(forEffect != null) {
+    index?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.IfNullSuperIndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    index?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    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 a compound index assignment.
 ///
 /// An if-null index assignment of the form `o[a] += b` is, if used for value,
 /// encoded as the expression:
@@ -2173,12 +1810,17 @@
   /// If `true`, the expression is a post-fix inc/dec expression.
   final bool forPostIncDec;
 
+  /// If `true`, the receiver is read-only and therefore doesn't need a
+  /// temporary variable for its value.
+  final bool readOnlyReceiver;
+
   CompoundIndexSet(this.receiver, this.index, this.binaryName, this.rhs,
       {this.readOffset,
       this.binaryOffset,
       this.writeOffset,
       this.forEffect,
-      this.forPostIncDec})
+      this.forPostIncDec,
+      this.readOnlyReceiver: false})
       : assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
@@ -2213,6 +1855,386 @@
   }
 }
 
+/// Internal expression representing a null-aware compound assignment.
+///
+/// A null-aware compound assignment of the form
+///
+///     receiver?.property binaryName= rhs
+///
+/// is, if used for value as a normal compound or prefix operation, encoded as
+/// the expression:
+///
+///     let receiverVariable = receiver in
+///       receiverVariable == null ? null :
+///         let leftVariable = receiverVariable.propertyName in
+///           let valueVariable = leftVariable binaryName rhs in
+///             let writeVariable =
+///                 receiverVariable.propertyName = valueVariable in
+///               valueVariable
+///
+/// and, if used for value as a postfix operation, encoded as
+///
+///     let receiverVariable = receiver in
+///       receiverVariable == null ? null :
+///         let leftVariable = receiverVariable.propertyName in
+///           let writeVariable =
+///               receiverVariable.propertyName =
+///                   leftVariable binaryName rhs in
+///             leftVariable
+///
+/// and, if used for effect, encoded as:
+///
+///     let receiverVariable = receiver in
+///       receiverVariable == null ? null :
+///         receiverVariable.propertyName = receiverVariable.propertyName + rhs
+///
+class NullAwareCompoundSet extends InternalExpression {
+  /// The receiver on which the null aware operation is performed.
+  Expression receiver;
+
+  /// The name of the null-aware property.
+  Name propertyName;
+
+  /// The name of the binary operation.
+  Name binaryName;
+
+  /// The right-hand side of the binary expression.
+  Expression rhs;
+
+  /// The file offset for the read operation.
+  final int readOffset;
+
+  /// The file offset for the write 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 postfix inc/dec expression.
+  final bool forPostIncDec;
+
+  NullAwareCompoundSet(
+      this.receiver, this.propertyName, this.binaryName, this.rhs,
+      {this.readOffset,
+      this.binaryOffset,
+      this.writeOffset,
+      this.forEffect,
+      this.forPostIncDec})
+      : assert(readOffset != null),
+        assert(binaryOffset != null),
+        assert(writeOffset != null),
+        assert(forEffect != null),
+        assert(forPostIncDec != null) {
+    receiver?.parent = this;
+    rhs?.parent = this;
+    fileOffset = binaryOffset;
+  }
+
+  @override
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.NullAwareCompoundSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    rhs?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an null-aware if-null property set.
+///
+/// A null-aware if-null property set of the form
+///
+///    receiver?.name ??= value
+///
+/// is, if used for value, encoded as the expression:
+///
+///     let receiverVariable = receiver in
+///       receiverVariable == null ? null :
+///         (let readVariable = receiverVariable.name in
+///           readVariable == null ?
+///             receiverVariable.name = value : readVariable)
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let receiverVariable = receiver in
+///       receiverVariable == null ? null :
+///         (receiverVariable.name == null ?
+///           receiverVariable.name = value : null)
+///
+///
+class NullAwareIfNullSet extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  Expression receiver;
+
+  /// The expression that reads the property from [variable].
+  Name name;
+
+  /// The expression that writes the value to the property on [variable].
+  Expression value;
+
+  /// The file offset for the read operation.
+  final int readOffset;
+
+  /// The file offset for the write operation.
+  final int writeOffset;
+
+  /// The file offset for the == operation.
+  final int testOffset;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  NullAwareIfNullSet(this.receiver, this.name, this.value,
+      {this.readOffset, this.writeOffset, this.testOffset, this.forEffect})
+      : assert(readOffset != null),
+        assert(writeOffset != null),
+        assert(testOffset != null),
+        assert(forEffect != null) {
+    receiver?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.NullAwareIfNullSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing a compound super index assignment.
+///
+/// An if-null index assignment of the form `super[a] += b` is, if used for
+/// value, encoded as the expression:
+///
+///     let v1 = a in
+///     let v2 = super.[](v1) + b
+///     let v3 = super.[]=(v1, v2) in v2
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let v1 = a in super.[]=(v2, super.[](v2) + b)
+///
+class CompoundSuperIndexSet extends InternalExpression {
+  /// The [] member.
+  Member getter;
+
+  /// The []= member.
+  Member setter;
+
+  /// 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;
+
+  CompoundSuperIndexSet(
+      this.getter, this.setter, this.index, this.binaryName, this.rhs,
+      {this.readOffset,
+      this.binaryOffset,
+      this.writeOffset,
+      this.forEffect,
+      this.forPostIncDec})
+      : assert(forEffect != null) {
+    index?.parent = this;
+    rhs?.parent = this;
+    fileOffset = binaryOffset;
+  }
+
+  @override
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.CompoundSuperIndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    index?.accept(v);
+    rhs?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (index != null) {
+      index = index.accept<TreeNode>(v);
+      index?.parent = this;
+    }
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an assignment to an extension setter.
+///
+/// An extension set of the form `receiver.target = value` is, if used for
+/// value, encoded as the expression:
+///
+///     let receiverVariable = receiver in
+///     let valueVariable = value in
+///     let writeVariable = target(receiverVariable, valueVariable) in
+///        valueVariable
+///
+/// or if the receiver is read-only, like `this` or a final variable,
+///
+///     let valueVariable = value in
+///     let writeVariable = target(receiver, valueVariable) in
+///        valueVariable
+///
+/// and, if used for effect, encoded as a [StaticInvocation]:
+///
+///     target(receiver, value)
+///
+// TODO(johnniwinther): Rename read-only to side-effect-free.
+class ExtensionSet extends InternalExpression {
+  /// The receiver for the assignment.
+  Expression receiver;
+
+  /// The extension member called for the assignment.
+  ObjectAccessTarget target;
+
+  /// The right-hand side value of the assignment.
+  Expression value;
+
+  /// If `true` the assignment is only needed for effect and not its result
+  /// value.
+  final bool forEffect;
+
+  /// If `true` the receiver can be cloned instead of creating a temporary
+  /// variable.
+  final bool readOnlyReceiver;
+
+  ExtensionSet(this.receiver, this.target, this.value,
+      {this.readOnlyReceiver, this.forEffect})
+      : assert(readOnlyReceiver != null),
+        assert(forEffect != null) {
+    receiver?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.ExtensionSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an null-aware extension expression.
+///
+/// An null-aware extension expression of the form `Extension(receiver)?.target`
+/// is encoded as the expression:
+///
+///     let variable = receiver in
+///       variable == null ? null : expression
+///
+/// where `expression` is an encoding of `receiverVariable.target`.
+class NullAwareExtension extends InternalExpression {
+  VariableDeclaration variable;
+  Expression expression;
+
+  NullAwareExtension(this.variable, this.expression) {
+    variable?.parent = this;
+    expression?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.NullAwareExtension;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    expression?.accept(v);
+  }
+
+  @override
+  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;
+    }
+  }
+}
+
+class PropertySetImpl extends PropertySet {
+  /// If `true` the assignment is need for its effect and not for its value.
+  final bool forEffect;
+
+  /// If `true` the receiver can be cloned and doesn't need a temporary variable
+  /// for multiple reads.
+  final bool readOnlyReceiver;
+
+  PropertySetImpl(Expression receiver, Name name, Expression value,
+      {Member interfaceTarget, this.forEffect, this.readOnlyReceiver})
+      : assert(forEffect != null),
+        super(receiver, name, value, interfaceTarget);
+}
+
 /// Creates a [Let] of [variable] with the given [body] using
 /// `variable.fileOffset` as the file offset for the let.
 ///
@@ -2247,7 +2269,7 @@
     int fileOffset, Expression left, Member equalsMember) {
   return new MethodInvocation(
       left,
-      new Name('=='),
+      equalsName,
       new Arguments(<Expression>[new NullLiteral()..fileOffset = fileOffset])
         ..fileOffset = fileOffset)
     ..fileOffset = fileOffset
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 1c4a783..6be7601 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -465,7 +465,7 @@
       unhandled("${type.runtimeType}", "installForwardingConstructors",
           builder.charOffset, builder.fileUri);
     }
-    if (supertype.isMixinApplication) {
+    if (supertype.isMixinApplication && supertype is SourceClassBuilder) {
       installForwardingConstructors(supertype);
     }
     if (supertype is ClassBuilder) {
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 010f327..544ff1d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -15,14 +15,15 @@
         TypeParameter,
         TypeParameterType,
         TypedefType,
+        Variance,
         VoidType;
 
 import 'package:kernel/type_algebra.dart' show containsTypeVariable;
 
-import 'package:kernel/src/bounds_checks.dart' show Variance;
-
 import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
 
+import '../builder/builder.dart';
+
 import 'kernel_builder.dart'
     show
         ClassBuilder,
@@ -47,7 +48,7 @@
         templateNonSimpleBoundViaReference,
         templateNonSimpleBoundViaVariable;
 
-export 'package:kernel/src/bounds_checks.dart' show Variance;
+export 'package:kernel/ast.dart' show Variance;
 
 // Computes the variance of a variable in a type.  The function can be run
 // before the types are resolved to compute variances of typedefs' type
@@ -123,35 +124,91 @@
     TypeBuilder type,
     Map<TypeVariableBuilder, TypeBuilder> upperSubstitution,
     Map<TypeVariableBuilder, TypeBuilder> lowerSubstitution,
-    {bool isCovariant = true}) {
+    List<TypeBuilder> unboundTypes,
+    List<TypeVariableBuilder> unboundTypeVariables,
+    {final int variance = Variance.covariant}) {
   if (type is NamedTypeBuilder) {
     if (type.declaration is TypeVariableBuilder) {
-      if (isCovariant) {
-        return upperSubstitution[type.declaration] ?? type;
+      if (variance == Variance.contravariant) {
+        return lowerSubstitution[type.declaration] ?? type;
       }
-      return lowerSubstitution[type.declaration] ?? type;
+      return upperSubstitution[type.declaration] ?? type;
     }
     if (type.arguments == null || type.arguments.length == 0) {
       return type;
     }
     List<TypeBuilder> arguments;
-    for (int i = 0; i < type.arguments.length; i++) {
-      TypeBuilder substitutedArgument = substituteRange(
-          type.arguments[i], upperSubstitution, lowerSubstitution,
-          isCovariant: isCovariant);
-      if (substitutedArgument != type.arguments[i]) {
-        arguments ??= type.arguments.toList();
-        arguments[i] = substitutedArgument;
+    TypeDeclarationBuilder declaration = type.declaration;
+    if (declaration == null) {
+      assert(unboundTypes != null,
+          "Can not handle unbound named type builders without `unboundTypes`.");
+      assert(
+          unboundTypeVariables != null,
+          "Can not handle unbound named type builders without "
+          "`unboundTypeVariables`.");
+      assert(
+          identical(upperSubstitution, lowerSubstitution),
+          "Can only handle unbound named type builders identical "
+          "`upperSubstitution` and `lowerSubstitution`.");
+      for (int i = 0; i < type.arguments.length; ++i) {
+        TypeBuilder substitutedArgument = substituteRange(
+            type.arguments[i],
+            upperSubstitution,
+            lowerSubstitution,
+            unboundTypes,
+            unboundTypeVariables,
+            variance: variance);
+        if (substitutedArgument != type.arguments[i]) {
+          arguments ??= type.arguments.toList();
+          arguments[i] = substitutedArgument;
+        }
       }
+    } else if (declaration is ClassBuilder) {
+      for (int i = 0; i < type.arguments.length; ++i) {
+        TypeBuilder substitutedArgument = substituteRange(
+            type.arguments[i],
+            upperSubstitution,
+            lowerSubstitution,
+            unboundTypes,
+            unboundTypeVariables,
+            variance: variance);
+        if (substitutedArgument != type.arguments[i]) {
+          arguments ??= type.arguments.toList();
+          arguments[i] = substitutedArgument;
+        }
+      }
+    } else if (declaration is TypeAliasBuilder) {
+      for (int i = 0; i < type.arguments.length; ++i) {
+        TypeVariableBuilder variable = declaration.typeVariables[i];
+        TypeBuilder substitutedArgument = substituteRange(
+            type.arguments[i],
+            upperSubstitution,
+            lowerSubstitution,
+            unboundTypes,
+            unboundTypeVariables,
+            variance: Variance.combine(variance, variable.variance));
+        if (substitutedArgument != type.arguments[i]) {
+          arguments ??= type.arguments.toList();
+          arguments[i] = substitutedArgument;
+        }
+      }
+    } else if (declaration is InvalidTypeBuilder) {
+      // Don't substitute.
+    } else {
+      assert(false, "Unexpected named type builder declaration: $declaration.");
     }
     if (arguments != null) {
-      return new NamedTypeBuilder(type.name, type.nullabilityBuilder, arguments)
-        ..bind(type.declaration);
+      NamedTypeBuilder newTypeBuilder =
+          new NamedTypeBuilder(type.name, type.nullabilityBuilder, arguments);
+      if (declaration != null) {
+        newTypeBuilder.bind(declaration);
+      } else {
+        unboundTypes.add(newTypeBuilder);
+      }
+      return newTypeBuilder;
     }
     return type;
-  }
-
-  if (type is FunctionTypeBuilder) {
+  } else if (type is FunctionTypeBuilder) {
     List<TypeVariableBuilder> variables;
     if (type.typeVariables != null) {
       variables = new List<TypeVariableBuilder>(type.typeVariables.length);
@@ -163,29 +220,45 @@
     TypeBuilder returnType;
     bool changed = false;
 
+    Map<TypeVariableBuilder, TypeBuilder> functionTypeUpperSubstitution;
+    Map<TypeVariableBuilder, TypeBuilder> functionTypeLowerSubstitution;
     if (type.typeVariables != null) {
       for (int i = 0; i < variables.length; i++) {
         TypeVariableBuilder variable = type.typeVariables[i];
-        TypeBuilder bound = substituteRange(
-            variable.bound, upperSubstitution, lowerSubstitution,
-            isCovariant: isCovariant);
+        TypeBuilder bound = substituteRange(variable.bound, upperSubstitution,
+            lowerSubstitution, unboundTypes, unboundTypeVariables,
+            variance: Variance.invariant);
         if (bound != variable.bound) {
-          variables[i] = new TypeVariableBuilder(
-              variable.name, variable.parent, variable.charOffset,
-              bound: bound);
+          TypeVariableBuilder newTypeVariableBuilder = variables[i] =
+              new TypeVariableBuilder(
+                  variable.name, variable.parent, variable.charOffset,
+                  bound: bound);
+          unboundTypeVariables.add(newTypeVariableBuilder);
+          if (functionTypeUpperSubstitution == null) {
+            functionTypeUpperSubstitution = {}..addAll(upperSubstitution);
+            functionTypeLowerSubstitution = {}..addAll(lowerSubstitution);
+          }
+          functionTypeUpperSubstitution[variable] =
+              functionTypeLowerSubstitution[variable] =
+                  new NamedTypeBuilder.fromTypeDeclarationBuilder(
+                      newTypeVariableBuilder,
+                      const NullabilityBuilder.omitted());
           changed = true;
         } else {
           variables[i] = variable;
         }
       }
     }
-
     if (type.formals != null) {
       for (int i = 0; i < formals.length; i++) {
         FormalParameterBuilder formal = type.formals[i];
         TypeBuilder parameterType = substituteRange(
-            formal.type, upperSubstitution, lowerSubstitution,
-            isCovariant: !isCovariant);
+            formal.type,
+            functionTypeUpperSubstitution ?? upperSubstitution,
+            functionTypeLowerSubstitution ?? lowerSubstitution,
+            unboundTypes,
+            unboundTypeVariables,
+            variance: Variance.combine(variance, Variance.contravariant));
         if (parameterType != formal.type) {
           formals[i] = new FormalParameterBuilder(
               formal.metadata,
@@ -193,34 +266,39 @@
               parameterType,
               formal.name,
               formal.parent,
-              formal.charOffset);
+              formal.charOffset,
+              formal.fileUri);
           changed = true;
         } else {
           formals[i] = formal;
         }
       }
     }
-
     returnType = substituteRange(
-        type.returnType, upperSubstitution, lowerSubstitution,
-        isCovariant: true);
-    if (returnType != type.returnType) {
-      changed = true;
-    }
+        type.returnType,
+        functionTypeUpperSubstitution ?? upperSubstitution,
+        functionTypeLowerSubstitution ?? lowerSubstitution,
+        unboundTypes,
+        unboundTypeVariables,
+        variance: variance);
+    changed = changed || returnType != type.returnType;
 
     if (changed) {
       return new FunctionTypeBuilder(
           returnType, variables, formals, type.nullabilityBuilder);
     }
-
     return type;
   }
   return type;
 }
 
 TypeBuilder substitute(
-    TypeBuilder type, Map<TypeVariableBuilder, TypeBuilder> substitution) {
-  return substituteRange(type, substitution, substitution, isCovariant: true);
+    TypeBuilder type, Map<TypeVariableBuilder, TypeBuilder> substitution,
+    {List<TypeBuilder> unboundTypes,
+    List<TypeVariableBuilder> unboundTypeVariables}) {
+  return substituteRange(
+      type, substitution, substitution, unboundTypes, unboundTypeVariables,
+      variance: Variance.covariant);
 }
 
 /// Calculates bounds to be provided as type arguments in place of missing type
@@ -249,9 +327,10 @@
       nullSubstitution[variables[variableIndex]] = bottomType;
     }
     for (int variableIndex in component) {
-      bounds[variableIndex] = substituteRange(
-          bounds[variableIndex], dynamicSubstitution, nullSubstitution,
-          isCovariant: true);
+      TypeVariableBuilder variable = variables[variableIndex];
+      bounds[variableIndex] = substituteRange(bounds[variableIndex],
+          dynamicSubstitution, nullSubstitution, null, null,
+          variance: variable.variance);
     }
   }
 
@@ -263,8 +342,10 @@
     substitution[variables[i]] = bounds[i];
     nullSubstitution[variables[i]] = bottomType;
     for (int j = 0; j < variables.length; j++) {
-      bounds[j] = substituteRange(bounds[j], substitution, nullSubstitution,
-          isCovariant: true);
+      TypeVariableBuilder variable = variables[j];
+      bounds[j] = substituteRange(
+          bounds[j], substitution, nullSubstitution, null, null,
+          variance: variable.variance);
     }
   }
 
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 1c060a6..d54e02f 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
@@ -81,10 +81,8 @@
         arguments[i] = kernelArguments[i].accept(this);
       }
     }
-    // TODO(dmitryas): Compute the nullabilityBuilder field for the result from
-    //  the nullability field of 'node'.
-    return new NamedTypeBuilder(
-        cls.name, const NullabilityBuilder.pendingImplementation(), arguments)
+    return new NamedTypeBuilder(cls.name,
+        new NullabilityBuilder.fromNullability(node.nullability), arguments)
       ..bind(cls);
   }
 
@@ -104,15 +102,16 @@
       if (i >= node.requiredParameterCount) {
         kind = FormalParameterKind.optionalPositional;
       }
-      formals[i] = new FormalParameterBuilder(null, 0, type, null, null, -1)
-        ..kind = kind;
+      formals[i] =
+          new FormalParameterBuilder(null, 0, type, null, null, -1, null)
+            ..kind = kind;
     }
     for (int i = 0; i < namedParameters.length; i++) {
       NamedType parameter = namedParameters[i];
       TypeBuilder type = positionalParameters[i].accept(this);
-      formals[i + positionalParameters.length] =
-          new FormalParameterBuilder(null, 0, type, parameter.name, null, -1)
-            ..kind = FormalParameterKind.optionalNamed;
+      formals[i + positionalParameters.length] = new FormalParameterBuilder(
+          null, 0, type, parameter.name, null, -1, null)
+        ..kind = FormalParameterKind.optionalNamed;
     }
     return new FunctionTypeBuilder(returnType, typeVariables, formals,
         new NullabilityBuilder.fromNullability(node.nullability));
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 4f0387f..2762157 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -13,7 +13,6 @@
         ExpressionStatement,
         Field,
         FunctionType,
-        Let,
         Library,
         Member,
         Procedure,
@@ -37,8 +36,6 @@
 
 import '../type_inference/type_schema.dart' show UnknownType;
 
-import 'kernel_shadow_ast.dart' show SyntheticExpressionJudgment;
-
 import 'redirecting_factory_body.dart'
     show RedirectingFactoryBody, getRedirectingFactoryBody;
 
@@ -140,14 +137,6 @@
   }
 
   @override
-  visitLet(Let node) {
-    if (node is SyntheticExpressionJudgment) {
-      problem(node, "Leaking shadow node: ${node.runtimeType}");
-    }
-    super.visitLet(node);
-  }
-
-  @override
   visitLibrary(Library node) {
     // Issue(http://dartbug.com/32530)
     if (skipPlatform && node.importUri.scheme == 'dart') {
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index e569a14..af3ed3b 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -1555,6 +1555,11 @@
   }
 
   @override
+  void handleVarianceModifier(Token variance) {
+    listener?.handleVarianceModifier(variance);
+  }
+
+  @override
   void handleVoidKeyword(Token token) {
     listener?.handleVoidKeyword(token);
   }
@@ -1578,4 +1583,9 @@
   void reportNonNullAssertExpressionNotEnabled(Token bang) {
     listener?.reportNonNullAssertExpressionNotEnabled(bang);
   }
+
+  @override
+  void reportVarianceModifierNotEnabled(Token variance) {
+    listener?.reportVarianceModifierNotEnabled(variance);
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 7d24308..9c67ac4 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -1230,6 +1230,19 @@
     logEvent("TypeVariables");
   }
 
+  void handleVarianceModifier(Token variance) {
+    logEvent("VarianceModifier");
+  }
+
+  void reportVarianceModifierNotEnabled(Token variance) {
+    if (variance != null) {
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments('variance'),
+          variance,
+          variance);
+    }
+  }
+
   void beginFunctionExpression(Token token) {}
 
   /// Handle the end of a function expression (e.g. "() { ... }").
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index c185f92..e139297 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1752,7 +1752,8 @@
     listener.beginClassOrNamedMixinApplicationPrelude(begin);
     Token name = ensureIdentifier(
         classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
-    Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+    Token token =
+        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
     if (optional('=', token.next)) {
       listener.beginNamedMixinApplication(begin, abstractToken, name);
       return parseNamedMixinApplication(token, begin, classKeyword);
@@ -1959,7 +1960,7 @@
     Token name = ensureIdentifier(
         mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
     Token headerStart =
-        computeTypeParamOrArg(name, true).parseVariables(name, this);
+        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
     listener.beginMixinDeclaration(mixinKeyword, name);
     Token token = parseMixinHeaderOpt(headerStart, mixinKeyword);
     if (!optional('{', token.next)) {
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index cf59846..f18f43e 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -307,7 +307,7 @@
 /// If [inDeclaration] is `true`, then this will more aggressively recover
 /// given unbalanced `<` `>` and invalid parameters or arguments.
 TypeParamOrArgInfo computeTypeParamOrArg(Token token,
-    [bool inDeclaration = false]) {
+    [bool inDeclaration = false, bool allowsVariance = false]) {
   Token beginGroup = token.next;
   if (!optional('<', beginGroup)) {
     return noTypeParamOrArg;
@@ -329,7 +329,8 @@
   }
 
   // TODO(danrubel): Consider adding additional const for common situations.
-  return new ComplexTypeParamOrArgInfo(token, inDeclaration).compute();
+  return new ComplexTypeParamOrArgInfo(token, inDeclaration, allowsVariance)
+      .compute();
 }
 
 /// Called by the parser to obtain information about a possible group of type
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 28e7ba9..2a16412 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -844,6 +844,11 @@
   /// given unbalanced `<` `>` and invalid parameters or arguments.
   final bool inDeclaration;
 
+  // Only support variance parsing if it makes sense.
+  // Allows parsing of variance for certain structures.
+  // See https://github.com/dart-lang/language/issues/524
+  final bool allowsVariance;
+
   @override
   int typeArgumentCount;
 
@@ -853,9 +858,11 @@
   /// and may not be part of the token stream.
   Token skipEnd;
 
-  ComplexTypeParamOrArgInfo(Token token, this.inDeclaration)
+  ComplexTypeParamOrArgInfo(
+      Token token, this.inDeclaration, this.allowsVariance)
       : assert(optional('<', token.next)),
         assert(inDeclaration != null),
+        assert(allowsVariance != null),
         start = token.next;
 
   /// Parse the tokens and return the receiver or [noTypeParamOrArg] if there
@@ -978,9 +985,35 @@
 
     Link<Token> typeStarts = const Link<Token>();
     Link<TypeInfo> superTypeInfos = const Link<TypeInfo>();
+    Link<Token> variances = const Link<Token>();
 
     while (true) {
       token = parser.parseMetadataStar(next);
+
+      Token variance = next.next;
+      Token identifier = variance.next;
+      if (allowsVariance &&
+          isVariance(variance) &&
+          identifier != null &&
+          identifier.isKeywordOrIdentifier) {
+        variances = variances.prepend(variance);
+
+        // Recovery for multiple variance modifiers
+        while (isVariance(identifier) &&
+            identifier.next != null &&
+            identifier.next.isKeywordOrIdentifier) {
+          // Report an error and skip actual identifier
+          parser.reportRecoverableError(
+              identifier, fasta.messageMultipleVarianceModifiers);
+          variance = variance.next;
+          identifier = identifier.next;
+        }
+
+        token = variance;
+      } else {
+        variances = variances.prepend(null);
+      }
+
       next = parser.ensureIdentifier(
           token, IdentifierContext.typeVariableDeclaration);
       token = next;
@@ -1015,12 +1048,18 @@
     assert(count > 0);
     assert(typeStarts.slowLength() == count);
     assert(superTypeInfos.slowLength() == count);
+    assert(variances.slowLength() == count);
     listener.handleTypeVariablesDefined(token, count);
 
     token = null;
     while (typeStarts.isNotEmpty) {
       Token token2 = typeStarts.head;
       TypeInfo typeInfo = superTypeInfos.head;
+      Token variance = variances.head;
+
+      if (variance != null) {
+        listener.handleVarianceModifier(variance);
+      }
 
       Token extendsOrSuper = null;
       Token next2 = token2.next;
@@ -1040,6 +1079,7 @@
 
       typeStarts = typeStarts.tail;
       superTypeInfos = superTypeInfos.tail;
+      variances = variances.tail;
     }
 
     if (!parseCloser(token)) {
@@ -1171,6 +1211,13 @@
   }
 }
 
+// Return `true` if [token] is one of `in`, `inout`, or `out`
+bool isVariance(Token token) {
+  return optional('in', token) ||
+      optional('inout', token) ||
+      optional('out', token);
+}
+
 /// Return `true` if [token] is one of `>`, `>>`, `>>>`, `>=`, `>>=`, or `>>>=`.
 bool isCloser(Token token) {
   final String value = token.stringValue;
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 cae857c..e34362d 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -73,10 +73,6 @@
   /// 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.
    *
@@ -143,7 +139,6 @@
       _enableExtensionMethods = config.enableExtensionMethods;
       _enableNonNullable = config.enableNonNullable;
       _enableTripleShift = config.enableTripleShift;
-      _enableVariance = config.enableVariance;
     }
   }
 
@@ -1488,10 +1483,6 @@
         (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, $_) ||
@@ -1916,19 +1907,13 @@
   /// 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.enableVariance = enableVariance ?? false;
+        this.enableTripleShift = enableTripleShift ?? false;
 }
 
 bool _isIdentifierChar(int next, bool allowDollar) {
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index b855f5b..400fba9 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -554,6 +554,11 @@
   }
 
   @override
+  void handleVarianceModifier(Token variance) {
+    debugEvent("VarianceModifier");
+  }
+
+  @override
   void endConstructorReference(
       Token start, Token periodBeforeName, Token endToken) {
     debugEvent("ConstructorReference");
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 d2272da..77ca872 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -45,6 +45,8 @@
         NamedTypeBuilder,
         TypeBuilder;
 
+import '../kernel/type_algorithms.dart';
+
 import '../modifier.dart'
     show
         Const,
@@ -488,6 +490,8 @@
       if (extensionThisType is TypeBuilder) {
         library.currentTypeParameterScopeBuilder
             .registerExtensionThisType(extensionThisType);
+      } else {
+        // TODO(johnniwinther): Supply an invalid type as the extension on type.
       }
     }
     debugEvent("beginClassOrMixinBody");
@@ -974,7 +978,7 @@
           substitution[extension.typeVariables[i]] =
               new NamedTypeBuilder.fromTypeDeclarationBuilder(
                   synthesizedTypeVariables[i],
-                  const NullabilityBuilder.pendingImplementation());
+                  const NullabilityBuilder.omitted());
         }
         if (typeVariables != null) {
           typeVariables = synthesizedTypeVariables..addAll(typeVariables);
@@ -985,14 +989,18 @@
       List<FormalParameterBuilder> synthesizedFormals = [];
       TypeBuilder thisType = extension.extensionThisType;
       if (substitution != null) {
-        List<NamedTypeBuilder> unboundTypes = [];
-        thisType = thisType.subst(substitution, unboundTypes);
-        for (NamedTypeBuilder unboundType in unboundTypes) {
+        List<TypeBuilder> unboundTypes = [];
+        List<TypeVariableBuilder> unboundTypeVariables = [];
+        thisType = substitute(thisType, substitution,
+            unboundTypes: unboundTypes,
+            unboundTypeVariables: unboundTypeVariables);
+        for (TypeBuilder unboundType in unboundTypes) {
           extension.addType(new UnresolvedType(unboundType, -1, null));
         }
+        library.boundlessTypeVariables.addAll(unboundTypeVariables);
       }
       synthesizedFormals.add(new FormalParameterBuilder(
-          null, finalMask, thisType, "#this", null, charOffset));
+          null, finalMask, thisType, "#this", null, charOffset, uri));
       if (formals != null) {
         synthesizedFormals.addAll(formals);
       }
@@ -1145,7 +1153,7 @@
     } else {
       push(library.addNamedType(
           name,
-          library.computeNullabilityFromToken(isMarkedAsNullable),
+          library.nullableBuilderIfTrue(isMarkedAsNullable),
           arguments,
           charOffset));
     }
@@ -1391,7 +1399,7 @@
         returnType,
         typeVariables,
         formals,
-        library.computeNullabilityFromToken(questionMark != null),
+        library.nullableBuilderIfTrue(questionMark != null),
         functionToken.charOffset));
   }
 
@@ -1406,7 +1414,7 @@
       reportErrorIfNullableType(question);
     }
     push(library.addFunctionType(returnType, typeVariables, formals,
-        library.computeNullabilityFromToken(question != null), formalsOffset));
+        library.nullableBuilderIfTrue(question != null), formalsOffset));
   }
 
   @override
@@ -1623,8 +1631,8 @@
                 : templateCycleInTypeVariables.withArguments(
                     builder.name, via.join("', '"));
             addProblem(message, builder.charOffset, builder.name.length);
-            builder.bound = new NamedTypeBuilder(builder.name,
-                const NullabilityBuilder.pendingImplementation(), null)
+            builder.bound = new NamedTypeBuilder(
+                builder.name, const NullabilityBuilder.omitted(), null)
               ..bind(new InvalidTypeBuilder(
                   builder.name,
                   message.withLocation(
@@ -1642,6 +1650,13 @@
   }
 
   @override
+  void handleVarianceModifier(Token variance) {
+    if (!library.loader.target.enableVariance) {
+      reportVarianceModifierNotEnabled(variance);
+    }
+  }
+
+  @override
   void endPartOf(
       Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
     debugEvent("endPartOf");
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index a55b41d..6499fc8 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -258,8 +258,8 @@
       }
     }
     if (message != null) {
-      return new NamedTypeBuilder(supertype.name,
-          const NullabilityBuilder.pendingImplementation(), null)
+      return new NamedTypeBuilder(
+          supertype.name, const NullabilityBuilder.omitted(), null)
         ..bind(new InvalidTypeBuilder(supertype.name,
             message.withLocation(fileUri, charOffset, noLength)));
     }
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 1961514..fd7df17 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -50,8 +50,17 @@
 
   Extension get extension => _extension;
 
+  /// Builds the [Extension] for this extension build and inserts the members
+  /// into the [Library] of [libraryBuilder].
+  ///
+  /// [addMembersToLibrary] is `true` if the extension members should be added
+  /// to the library. This is `false` if the extension is in conflict with
+  /// another library member. In this case, the extension member should not be
+  /// added to the library to avoid name clashes with other members in the
+  /// library.
   Extension build(
-      SourceLibraryBuilder libraryBuilder, LibraryBuilder coreLibrary) {
+      SourceLibraryBuilder libraryBuilder, LibraryBuilder coreLibrary,
+      {bool addMembersToLibrary}) {
     void buildBuilders(String name, Builder declaration) {
       do {
         if (declaration.parent != this) {
@@ -64,48 +73,52 @@
           }
         } else if (declaration is FieldBuilder) {
           Field field = declaration.build(libraryBuilder);
-          libraryBuilder.library.addMember(field);
-          _extension.members.add(new ExtensionMemberDescriptor(
-              name: new Name(declaration.name, libraryBuilder.library),
-              member: field.reference,
-              isStatic: declaration.isStatic,
-              kind: ExtensionMemberKind.Field));
-        } else if (declaration is ProcedureBuilder) {
-          Member function = declaration.build(libraryBuilder);
-          libraryBuilder.library.addMember(function);
-          ExtensionMemberKind kind;
-          switch (declaration.kind) {
-            case ProcedureKind.Method:
-              kind = ExtensionMemberKind.Method;
-              break;
-            case ProcedureKind.Getter:
-              kind = ExtensionMemberKind.Getter;
-              break;
-            case ProcedureKind.Setter:
-              kind = ExtensionMemberKind.Setter;
-              break;
-            case ProcedureKind.Operator:
-              kind = ExtensionMemberKind.Operator;
-              break;
-            case ProcedureKind.Factory:
-              unsupported("Extension method kind: ${declaration.kind}",
-                  declaration.charOffset, declaration.fileUri);
-          }
-          _extension.members.add(new ExtensionMemberDescriptor(
-              name: new Name(declaration.name, libraryBuilder.library),
-              member: function.reference,
-              isStatic: declaration.isStatic,
-              isExternal: declaration.isExternal,
-              kind: kind));
-          Procedure tearOff = declaration.extensionTearOff;
-          if (tearOff != null) {
-            libraryBuilder.library.addMember(tearOff);
+          if (addMembersToLibrary && declaration.next == null) {
+            libraryBuilder.library.addMember(field);
             _extension.members.add(new ExtensionMemberDescriptor(
                 name: new Name(declaration.name, libraryBuilder.library),
-                member: tearOff.reference,
-                isStatic: false,
-                isExternal: false,
-                kind: ExtensionMemberKind.TearOff));
+                member: field.reference,
+                isStatic: declaration.isStatic,
+                kind: ExtensionMemberKind.Field));
+          }
+        } else if (declaration is ProcedureBuilder) {
+          Member function = declaration.build(libraryBuilder);
+          if (addMembersToLibrary && declaration.next == null) {
+            libraryBuilder.library.addMember(function);
+            ExtensionMemberKind kind;
+            switch (declaration.kind) {
+              case ProcedureKind.Method:
+                kind = ExtensionMemberKind.Method;
+                break;
+              case ProcedureKind.Getter:
+                kind = ExtensionMemberKind.Getter;
+                break;
+              case ProcedureKind.Setter:
+                kind = ExtensionMemberKind.Setter;
+                break;
+              case ProcedureKind.Operator:
+                kind = ExtensionMemberKind.Operator;
+                break;
+              case ProcedureKind.Factory:
+                unsupported("Extension method kind: ${declaration.kind}",
+                    declaration.charOffset, declaration.fileUri);
+            }
+            _extension.members.add(new ExtensionMemberDescriptor(
+                name: new Name(declaration.name, libraryBuilder.library),
+                member: function.reference,
+                isStatic: declaration.isStatic,
+                isExternal: declaration.isExternal,
+                kind: kind));
+            Procedure tearOff = declaration.extensionTearOff;
+            if (tearOff != null) {
+              libraryBuilder.library.addMember(tearOff);
+              _extension.members.add(new ExtensionMemberDescriptor(
+                  name: new Name(declaration.name, libraryBuilder.library),
+                  member: tearOff.reference,
+                  isStatic: false,
+                  isExternal: false,
+                  kind: ExtensionMemberKind.TearOff));
+            }
           }
         } else {
           unhandled("${declaration.runtimeType}", "buildBuilders",
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 3ef57cb..811db64 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
@@ -195,6 +195,7 @@
 import '../kernel/type_algorithms.dart'
     show
         calculateBounds,
+        computeVariance,
         findGenericFunctionTypes,
         getNonSimplicityIssuesForDeclaration,
         getNonSimplicityIssuesForTypeVariables;
@@ -298,6 +299,13 @@
   // TODO(dmitryas):  Find a way to mark inferred types.
   final Set<DartType> inferredTypes = new Set<DartType>.identity();
 
+  // While the bounds of type parameters aren't compiled yet, we can't tell the
+  // default nullability of the corresponding type-parameter types.  This list
+  // is used to collect such type-parameter types in order to set the
+  // nullability after the bounds are built.
+  final List<TypeParameterType> pendingNullabilities =
+      new List<TypeParameterType>();
+
   // A library to use for Names generated when compiling code in this library.
   // This allows code generated in one library to use the private namespace of
   // another, for example during expression compilation (debugging).
@@ -720,8 +728,10 @@
                 .withLocation(
                     existing.fileUri, existing.charOffset, fullName.length)
           ]);
-    }
-    if (declaration.isExtension) {
+    } else if (declaration.isExtension) {
+      // We add the extension declaration to the extension scope only if its
+      // name is unique. Only the first of duplicate extensions is accessible
+      // by name or by resolution and the remaining are dropped for the output.
       currentTypeParameterScopeBuilder.extensions.add(declaration);
     }
     return members[name] = declaration;
@@ -1647,11 +1657,8 @@
 
             applicationTypeArguments = <TypeBuilder>[];
             for (TypeVariableBuilder typeVariable in typeVariables) {
-              applicationTypeArguments.add(addNamedType(
-                  typeVariable.name,
-                  const NullabilityBuilder.pendingImplementation(),
-                  null,
-                  charOffset)
+              applicationTypeArguments.add(addNamedType(typeVariable.name,
+                  const NullabilityBuilder.omitted(), null, charOffset)
                 ..bind(
                     // The type variable types passed as arguments to the
                     // generic class representing the anonymous mixin
@@ -1702,11 +1709,8 @@
         // handle that :(
         application.cls.isAnonymousMixin = !isNamedMixinApplication;
         addBuilder(fullname, application, charOffset);
-        supertype = addNamedType(
-            fullname,
-            const NullabilityBuilder.pendingImplementation(),
-            applicationTypeArguments,
-            charOffset);
+        supertype = addNamedType(fullname, const NullabilityBuilder.omitted(),
+            applicationTypeArguments, charOffset);
       }
       return supertype;
     } else {
@@ -1976,6 +1980,12 @@
       List<TypeVariableBuilder> typeVariables,
       FunctionTypeBuilder type,
       int charOffset) {
+    if (typeVariables != null) {
+      for (int i = 0; i < typeVariables.length; ++i) {
+        TypeVariableBuilder variable = typeVariables[i];
+        variable.variance = computeVariance(variable, type);
+      }
+    }
     TypeAliasBuilder typedefBuilder = new TypeAliasBuilder(
         metadata, name, typeVariables, type, this, charOffset);
     loader.target.metadataCollector
@@ -2015,7 +2025,7 @@
       modifiers |= initializingFormalMask;
     }
     FormalParameterBuilder formal = new FormalParameterBuilder(
-        metadata, modifiers, type, name, this, charOffset);
+        metadata, modifiers, type, name, this, charOffset, uri);
     formal.initializerToken = initializerToken;
     return formal;
   }
@@ -2041,7 +2051,8 @@
     if (declaration is SourceClassBuilder) {
       cls = declaration.build(this, coreLibrary);
     } else if (declaration is SourceExtensionBuilder) {
-      extension = declaration.build(this, coreLibrary);
+      extension = declaration.build(this, coreLibrary,
+          addMembersToLibrary: declaration.next == null);
     } else if (declaration is FieldBuilder) {
       member = declaration.build(this)..isStatic = true;
     } else if (declaration is ProcedureBuilder) {
@@ -2364,6 +2375,10 @@
       builder.finish(this, object, dynamicType);
     }
     boundlessTypeVariables.clear();
+
+    TypeVariableBuilder.finishNullabilities(this, pendingNullabilities);
+    pendingNullabilities.clear();
+
     return count;
   }
 
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 eeb0bac..cd2c0bf 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -37,6 +37,8 @@
 
 import '../blacklisted_classes.dart' show blacklistedCoreClasses;
 
+import '../builder/extension_builder.dart';
+
 import '../export.dart' show Export;
 
 import '../import.dart' show Import;
@@ -968,6 +970,8 @@
           Builder declaration = iterator.current;
           if (declaration is ClassBuilder) {
             declaration.buildOutlineExpressions(library);
+          } else if (declaration is ExtensionBuilder) {
+            declaration.buildOutlineExpressions(library);
           } else if (declaration is MemberBuilder) {
             declaration.buildOutlineExpressions(library);
           }
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index ebf430a..8a1c08d 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -1361,6 +1361,12 @@
   }
 
   @override
+  void handleNonNullAssertExpression(Token token) {
+    debugEvent("NonNullAssertExpression", token);
+    state.popPushNull("%NonNullAssertExpression%", token);
+  }
+
+  @override
   void handleUnescapeError(
       Message message, Token location, int stringOffset, int length) {
     debugEvent("UnescapeError", location);
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 4aa0538..d0506c9 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -51,6 +51,7 @@
   bool enableExtensionMethods;
   bool enableNonNullable;
   bool enableTripleShift;
+  bool enableVariance;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
       : enableExtensionMethods = CompilerContext.current.options
@@ -59,6 +60,8 @@
             .isExperimentEnabled(ExperimentalFlag.nonNullable),
         enableTripleShift = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.tripleShift),
+        enableVariance = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.variance),
         super(ticker);
 
   /// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
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 f01923c..3f1988c 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,9 +22,7 @@
   set transformSetLiterals(bool value);
 
   Expression buildProblem(Message message, int charOffset, int length,
-      {List<LocatedMessage> context,
-      bool suppressMessage,
-      bool wrapInSyntheticExpression: true});
+      {List<LocatedMessage> context, bool suppressMessage});
 
   LocatedMessage checkArgumentsForType(
       FunctionType function, Arguments arguments, int offset);
@@ -37,6 +35,4 @@
 
   String constructorNameForDiagnostics(String name,
       {String className, bool isSuper});
-
-  Expression desugarSyntheticExpression(Expression node);
 }
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 0fb91de..f2243b2 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
@@ -27,8 +27,8 @@
   Class get futureClass;
   Class get futureOrClass;
   InterfaceType get nullType;
-  InterfaceType get objectType;
-  InterfaceType get rawFunctionType;
+  InterfaceType get objectLegacyRawType;
+  InterfaceType get functionLegacyRawType;
 
   bool isSubtypeOf(DartType subtype, DartType supertype);
 
@@ -74,10 +74,10 @@
     }
 
     // SLB(Object, T) = SLB(T, Object) = T if T is not void or dynamic.
-    if (type1 == objectType) {
+    if (type1 == objectLegacyRawType) {
       return type2;
     }
-    if (type2 == objectType) {
+    if (type2 == objectLegacyRawType) {
       return type1;
     }
 
@@ -182,10 +182,10 @@
     }
 
     // SUB(Object, T) = SUB(T, Object) = Object if T is not void or dynamic.
-    if (type1 == objectType) {
+    if (type1 == objectLegacyRawType) {
       return type1;
     }
-    if (type2 == objectType) {
+    if (type2 == objectLegacyRawType) {
       return type2;
     }
 
@@ -202,10 +202,10 @@
     // The standard upper bound of a function type and an interface type T is
     // the standard upper bound of Function and T.
     if (type1 is FunctionType && type2 is InterfaceType) {
-      type1 = rawFunctionType;
+      type1 = functionLegacyRawType;
     }
     if (type2 is FunctionType && type1 is InterfaceType) {
-      type2 = rawFunctionType;
+      type2 = functionLegacyRawType;
     }
 
     // At this point type1 and type2 should both either be interface types or
@@ -474,13 +474,13 @@
       // C<T extends U, U extends List>, T gets resolved directly to List.  Do
       // we need to replicate that behavior?
       return getStandardUpperBound(
-          Substitution.fromMap({type1.parameter: objectType})
+          Substitution.fromMap({type1.parameter: objectLegacyRawType})
               .substituteType(type1.parameter.bound),
           type2);
     } else if (type2 is TypeParameterType) {
       return getStandardUpperBound(
           type1,
-          Substitution.fromMap({type2.parameter: objectType})
+          Substitution.fromMap({type2.parameter: objectLegacyRawType})
               .substituteType(type2.parameter.bound));
     } else {
       // We should only be called when at least one of the types is a
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 9bb90d0..4717c77 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
@@ -6,7 +6,7 @@
 
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
 
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' hide Variance;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -716,14 +716,26 @@
           new InstrumentationValueForMember(target.member));
     }
 
-    if (target.isUnresolved && includeExtensionMethods) {
+    if (target.isUnresolved &&
+        receiverType is! DynamicType &&
+        includeExtensionMethods) {
+      Member otherMember =
+          _getInterfaceMember(classNode, name, !setter, fileOffset);
+      if (otherMember != null) {
+        // If we're looking for `foo` and `foo=` can be found or vice-versa then
+        // extension methods should not be found.
+        return target;
+      }
+
       ExtensionAccessCandidate bestSoFar;
       List<ExtensionAccessCandidate> noneMoreSpecific = [];
       library.scope.forEachExtension((ExtensionBuilder extensionBuilder) {
-        MemberBuilder memberBuilder =
-            extensionBuilder.lookupLocalMember(name.name, setter: setter);
-        if (memberBuilder != null && !memberBuilder.isStatic) {
-          Extension extension = extensionBuilder.extension;
+        MemberBuilder getterBuilder =
+            extensionBuilder.lookupLocalMember(name.name, setter: false);
+        MemberBuilder setterBuilder =
+            extensionBuilder.lookupLocalMember(name.name, setter: true);
+        if ((getterBuilder != null && !getterBuilder.isStatic) ||
+            (setterBuilder != null && !setterBuilder.isStatic)) {
           DartType onType;
           DartType onTypeInstantiateToBounds;
           List<DartType> inferredTypeArguments;
@@ -762,15 +774,20 @@
           }
 
           if (typeSchemaEnvironment.isSubtypeOf(receiverType, onType)) {
+            MemberBuilder memberBuilder =
+                setter ? setterBuilder : getterBuilder;
+
             ExtensionAccessCandidate candidate = new ExtensionAccessCandidate(
-                extension,
                 onType,
                 onTypeInstantiateToBounds,
-                new ObjectAccessTarget.extensionMember(
-                    memberBuilder.procedure,
-                    memberBuilder.extensionTearOff,
-                    memberBuilder.kind,
-                    inferredTypeArguments));
+                memberBuilder != null
+                    ? new ObjectAccessTarget.extensionMember(
+                        memberBuilder.procedure,
+                        memberBuilder.extensionTearOff,
+                        memberBuilder.kind,
+                        inferredTypeArguments)
+                    : const ObjectAccessTarget.missing(),
+                isPlatform: extensionBuilder.library.uri.scheme == 'dart');
             if (noneMoreSpecific.isNotEmpty) {
               bool isMostSpecific = true;
               for (ExtensionAccessCandidate other in noneMoreSpecific) {
@@ -852,11 +869,11 @@
       }
       expression.parent.replaceChild(
           expression,
-          helper.desugarSyntheticExpression(helper.buildProblem(
+          helper.buildProblem(
               errorTemplate.withArguments(
                   name.name, resolveTypeParameter(receiverType)),
               fileOffset,
-              length)));
+              length));
     }
     return target;
   }
@@ -1772,11 +1789,10 @@
     if (named.length == 2) {
       if (named[0].name == named[1].name) {
         String name = named[1].name;
-        Expression error = helper.desugarSyntheticExpression(
-            helper.buildProblem(
-                templateDuplicatedNamedArgument.withArguments(name),
-                named[1].fileOffset,
-                name.length));
+        Expression error = helper.buildProblem(
+            templateDuplicatedNamedArgument.withArguments(name),
+            named[1].fileOffset,
+            name.length);
         arguments.named = [new NamedExpression(named[1].name, error)];
         formalTypes.removeLast();
         actualTypes.removeLast();
@@ -1791,11 +1807,10 @@
         if (seenNames.containsKey(name)) {
           hasProblem = true;
           NamedExpression prevNamedExpression = seenNames[name];
-          prevNamedExpression.value = helper.desugarSyntheticExpression(
-              helper.buildProblem(
-                  templateDuplicatedNamedArgument.withArguments(name),
-                  expression.fileOffset,
-                  name.length))
+          prevNamedExpression.value = helper.buildProblem(
+              templateDuplicatedNamedArgument.withArguments(name),
+              expression.fileOffset,
+              name.length)
             ..parent = prevNamedExpression;
           formalTypes.removeAt(namedTypeIndex);
           actualTypes.removeAt(namedTypeIndex);
@@ -2549,7 +2564,7 @@
       expectedType = (expectedType as InterfaceType).typeArguments[0];
     }
     if (expectedType is FunctionType) return true;
-    if (expectedType == typeSchemaEnvironment.rawFunctionType) {
+    if (expectedType == typeSchemaEnvironment.functionLegacyRawType) {
       if (!typeSchemaEnvironment.isSubtypeOf(actualType, expectedType)) {
         return true;
       }
@@ -2841,11 +2856,11 @@
   final bool isPlatform;
   final DartType onType;
   final DartType onTypeInstantiateToBounds;
-  final ExtensionAccessTarget target;
+  final ObjectAccessTarget target;
 
-  ExtensionAccessCandidate(Extension extension, this.onType,
-      this.onTypeInstantiateToBounds, this.target)
-      : isPlatform = extension.enclosingLibrary.importUri.scheme == 'dart';
+  ExtensionAccessCandidate(
+      this.onType, this.onTypeInstantiateToBounds, this.target,
+      {this.isPlatform});
 
   bool isMoreSpecificThan(TypeSchemaEnvironment typeSchemaEnvironment,
       ExtensionAccessCandidate other) {
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 ad77c76..5f8280e 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
@@ -120,11 +120,11 @@
     // TODO(paulberry): this matches what is defined in the spec.  It would be
     // nice if we could change kernel to match the spec and not have to
     // override.
-    if (type1 == intType) {
-      if (type2 == intType) return type2;
-      if (type2 == doubleType) return type2;
+    if (type1 == coreTypes.intLegacyRawType) {
+      if (type2 == coreTypes.intLegacyRawType) return type2;
+      if (type2 == coreTypes.doubleLegacyRawType) return type2;
     }
-    return numType;
+    return coreTypes.numLegacyRawType;
   }
 
   /// Infers a generic type, function, method, or list/map literal
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 5c99198..3742020 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -197,6 +197,10 @@
 ExplicitExtensionArgumentMismatch/example: Fail
 ExplicitExtensionTypeArgumentMismatch/analyzerCode: Fail
 ExplicitExtensionTypeArgumentMismatch/example: Fail
+ExplicitExtensionAsExpression/analyzerCode: Fail
+ExplicitExtensionAsExpression/example: Fail
+ExplicitExtensionAsLvalue/analyzerCode: Fail
+ExplicitExtensionAsLvalue/example: Fail
 ExportAfterPart/part_wrapped_script1: Fail
 ExportAfterPart/script1: Fail
 ExpressionNotMetadata/analyzerCode: Fail
@@ -310,6 +314,8 @@
 ImplementsFutureOr/analyzerCode: Fail # The analyzer doesn't report this error.
 ImplementsFutureOr/part_wrapped_script1: Fail # Importing file in the (now) part.
 ImplicitCallOfNonMethod/example: Fail
+ImplicitMixinOverride/analyzerCode: Fail
+ImplicitMixinOverride/example: Fail
 ImportAfterPart/part_wrapped_script1: Fail
 ImportAfterPart/script1: Fail
 IncompatibleRedirecteeFunctionType/part_wrapped_script6: Fail
@@ -319,6 +325,8 @@
 InputFileNotFound/analyzerCode: Fail
 InputFileNotFound/example: Fail
 IntegerLiteralIsOutOfRange/example: Fail
+InterfaceCheck/analyzerCode: Fail
+InterfaceCheck/example: Fail
 InterpolationInUri/example: Fail
 IntersectionTypeAsTypeArgument/analyzerCode: Fail # Analyzer doesn't catch this error.
 InvalidBreakTarget/analyzerCode: Fail
@@ -387,7 +395,10 @@
 MultipleOnClauses/script: Fail
 MultipleWith/part_wrapped_script: Fail
 MultipleWith/script: Fail
+MultipleVarianceModifiers/example: Fail # All trigger multiple errors for variance experiment
 NamedFunctionExpression/example: Fail
+NamedMixinOverride/analyzerCode: Fail
+NamedMixinOverride/example: Fail
 NativeClauseShouldBeAnnotation/example: Fail
 NoFormals/example: Fail
 NoSuchNamedParameter/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 0436850..8568a27 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1430,17 +1430,14 @@
   template: "'#name' is defined here."
   severity: CONTEXT
 
-InterfaceCheckContext:
-  template: "Both members are inherited by the non-abstract class '#name'."
-  severity: CONTEXT
+InterfaceCheck:
+  template: "The implementation of '#name' in the non-abstract class '#name2' does not conform to its interface."
 
-NamedMixinOverrideContext:
-  template: "Override was introduced in the mixin application class '#name'."
-  severity: CONTEXT
+NamedMixinOverride:
+  template: "The mixin application class '#name' introduces an erroneous override of '#name2'."
 
-ImplicitMixinOverrideContext:
-  template: "Override was introduced when the mixin '#name' was applied to '#name2'."
-  severity: CONTEXT
+ImplicitMixinOverride:
+  template: "Applying the mixin '#name' to '#name2' introduces an erroneous override of '#name3'."
 
 ListLiteralTooManyTypeArguments:
   template: "List literal requires exactly one type argument."
@@ -1700,6 +1697,10 @@
   template: "Unexpected usage of label inside declaration of variables."
   severity: INTERNAL_PROBLEM
 
+InternalProblemUnfinishedTypeVariable:
+  template: "Unfinished type variable '#name' found in non-source library '#uri'."
+  severity: INTERNAL_PROBLEM
+
 LocalDefinitionHidesExport:
   template: "Local definition of '#name' hides export from '#uri'."
   severity: IGNORED
@@ -3706,3 +3707,15 @@
 
 ExplicitExtensionTypeArgumentMismatch:
   template: "Explicit extension application of extension '#name' takes '#count' type argument(s)."
+
+ExplicitExtensionAsExpression:
+  template: "Explicit extension application cannot be used as an expression."
+
+ExplicitExtensionAsLvalue:
+  template: "Explicit extension application cannot be a target for assignment."
+
+MultipleVarianceModifiers:
+  index: 97
+  template: "Each type parameter can have at most one variance modifier."
+  tip: "Use at most one of the 'in', 'out', or 'inout' modifiers."
+  analyzerCode: ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index e39bb2e..83a7f7d 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,17 +1,18 @@
 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.25
+version: 0.1.26
 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.25
+  kernel: 0.3.26
   package_config: '^1.1.0'
+  meta: ^1.0.2
 dev_dependencies:
-  analyzer: 0.38.3
+  analyzer: 0.38.4
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
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 273a013..fe1bbc0 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -149,22 +149,22 @@
         new SuperPropertyAccessGenerator(helper, token, name, getter, setter));
     check(
         "IndexedAccessGenerator(offset: 4, receiver: expression, index: index,"
-        " getter: $uri::myGetter, setter: $uri::mySetter,"
-        " receiverVariable: null, indexVariable: null)",
+        " getter: $uri::myGetter, setter: $uri::mySetter)",
         new IndexedAccessGenerator(
             helper, token, expression, index, getter, setter));
     check(
         "ThisIndexedAccessGenerator(offset: 4, index: index,"
-        " getter: $uri::myGetter, setter: $uri::mySetter, indexVariable: null)",
+        " getter: $uri::myGetter, setter: $uri::mySetter)",
         new ThisIndexedAccessGenerator(helper, token, index, getter, setter));
     check(
         "SuperIndexedAccessGenerator(offset: 4, index: index,"
-        " getter: $uri::myGetter, setter: $uri::mySetter, indexVariable: null)",
+        " getter: $uri::myGetter, setter: $uri::mySetter)",
         new SuperIndexedAccessGenerator(helper, token, index, getter, setter));
     check(
-        "StaticAccessGenerator(offset: 4, readTarget: $uri::myGetter,"
+        "StaticAccessGenerator(offset: 4, targetName: foo,"
+        " readTarget: $uri::myGetter,"
         " writeTarget: $uri::mySetter)",
-        new StaticAccessGenerator(helper, token, getter, setter));
+        new StaticAccessGenerator(helper, token, 'foo', getter, setter));
     check(
         "LoadLibraryGenerator(offset: 4,"
         " builder: Instance of 'LoadLibraryBuilder')",
diff --git a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
index 3e79fd5..b3c3aba 100644
--- a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' hide Variance;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/front_end/test/fasta/types/dill_hierachy_test.dart b/pkg/front_end/test/fasta/types/dill_hierachy_test.dart
index 80393e4..56053fa 100644
--- a/pkg/front_end/test/fasta/types/dill_hierachy_test.dart
+++ b/pkg/front_end/test/fasta/types/dill_hierachy_test.dart
@@ -69,7 +69,7 @@
   Longest path to Object: 3
   superclasses:
     Object
-  interfaces: B<T>*, A, C<U>*
+  interfaces: B<T>, A, C<U>
   classMembers:
   classSetters:
   interfaceMembers:
@@ -79,7 +79,7 @@
   Longest path to Object: 4
   superclasses:
     Object
-  interfaces: D<int, double>*, B<int>*, A, C<double>*
+  interfaces: D<int, double>, B<int>, A, C<double>
   classMembers:
   classSetters:
   interfaceMembers:
@@ -89,7 +89,7 @@
   Longest path to Object: 4
   superclasses:
     Object
-  interfaces: D<int, bool>*, B<int>*, A, C<bool>*
+  interfaces: D<int, bool>, B<int>, A, C<bool>
   classMembers:
   classSetters:
   interfaceMembers:
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 4a7f3b8..ff98073 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -193,7 +193,7 @@
       // the bound because it's not yet available, it will be set to null.  In
       // that case, put it to the list to be updated later, when the bound is
       // available.
-      if (type.declaredNullability == null) {
+      if (type.typeParameterTypeNullability == null) {
         environment.pendingNullabilities.add(type);
       }
       return type;
@@ -355,7 +355,7 @@
     }
 
     for (TypeParameterType type in nestedEnvironment.pendingNullabilities) {
-      type.declaredNullability =
+      type.typeParameterTypeNullability =
           TypeParameterType.computeNullabilityFromBound(type.parameter);
     }
     nestedEnvironment.pendingNullabilities.clear();
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/not_promoted.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/not_promoted.dart
new file mode 100644
index 0000000..ecca539
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/type_promotion/data/not_promoted.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  this_access() {
+    if (this is D) {
+      this;
+    }
+  }
+
+  Object x = 'foo';
+
+  field_by_scope() {
+    if (x is String) {
+      x;
+    }
+  }
+
+  Object get y => 'foo';
+
+  getter_by_scope() {
+    if (y is String) {
+      y;
+    }
+  }
+}
+
+class D extends C {}
+
+field_by_access(C c) {
+  if (c.x is String) {
+    c.x;
+  }
+}
+
+getter_by_access(C c) {
+  if (c.y is String) {
+    c.y;
+  }
+}
+
+Object f() => 'foo';
+
+top_level_function() {
+  if (f is int Function()) {
+    f;
+  }
+}
+
+local_function() {
+  Object g() => 'foo';
+  if (g is int Function()) {
+    g;
+  }
+}
+
+Object a = 'foo';
+
+top_level_variable() {
+  if (a is String) {
+    a;
+  }
+}
+
+Object get b => 'foo';
+
+top_level_getter() {
+  if (b is String) {
+    b;
+  }
+}
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 dd6bf04..9013baa 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -43,7 +43,8 @@
         Name,
         Procedure;
 
-import 'package:kernel/target/targets.dart' show TargetFlags;
+import 'package:kernel/target/targets.dart'
+    show NoneTarget, Target, TargetFlags;
 
 import 'package:kernel/text/ast_to_text.dart' show componentToString;
 
@@ -115,8 +116,11 @@
 
   Future<Result<TestData>> run(TestData data, Context context) async {
     YamlMap map = data.map;
+    Set<String> keys = new Set<String>.from(map.keys.cast<String>());
+    keys.remove("type");
     switch (map["type"]) {
       case "basic":
+        keys.removeAll(["sources", "entry", "invalidate"]);
         await basicTest(
           map["sources"],
           map["entry"],
@@ -125,15 +129,19 @@
         );
         break;
       case "newworld":
+        keys.removeAll(["worlds", "modules", "omitPlatform", "target"]);
         await newWorldTest(
           map["worlds"],
           map["modules"],
           map["omitPlatform"],
+          map["target"],
         );
         break;
       default:
         throw "Unexpected type: ${map['type']}";
     }
+
+    if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys";
     return pass(data);
   }
 }
@@ -198,7 +206,7 @@
 }
 
 Future<Map<String, List<int>>> createModules(
-    Map module, final List<int> sdkSummaryData) async {
+    Map module, final List<int> sdkSummaryData, String targetName) async {
   final Uri base = Uri.parse("org-dartlang-test:///");
   final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
 
@@ -230,7 +238,7 @@
         moduleSources.add(uri);
       }
     }
-    CompilerOptions options = getOptions();
+    CompilerOptions options = getOptions(targetName: targetName);
     options.fileSystem = fs;
     options.sdkRoot = null;
     options.sdkSummary = sdkSummary;
@@ -264,7 +272,8 @@
   return moduleResult;
 }
 
-Future<Null> newWorldTest(List worlds, Map modules, bool omitPlatform) async {
+Future<Null> newWorldTest(
+    List worlds, Map modules, bool omitPlatform, String targetName) async {
   final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
   final Uri base = Uri.parse("org-dartlang-test:///");
   final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
@@ -284,7 +293,7 @@
   Map<String, Component> moduleComponents;
   Component sdk;
   if (modules != null) {
-    moduleData = await createModules(modules, sdkSummaryData);
+    moduleData = await createModules(modules, sdkSummaryData, targetName);
     sdk = newestWholeComponent = new Component();
     new BinaryBuilder(sdkSummaryData, filename: null, disableLazyReading: false)
         .readComponent(newestWholeComponent);
@@ -370,7 +379,7 @@
     }
 
     if (brandNewWorld) {
-      options = getOptions();
+      options = getOptions(targetName: targetName);
       options.fileSystem = fs;
       options.sdkRoot = null;
       options.sdkSummary = sdkSummary;
@@ -800,11 +809,21 @@
   Expect.equals(a.length, b.length);
 }
 
-CompilerOptions getOptions() {
+CompilerOptions getOptions({String targetName}) {
   final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+  Target target = new VmTarget(new TargetFlags());
+  if (targetName != null) {
+    if (targetName == "None") {
+      target = new NoneTarget(new TargetFlags());
+    } else if (targetName == "VM") {
+      // default.
+    } else {
+      throw "Unknown target name '$targetName'";
+    }
+  }
   CompilerOptions options = new CompilerOptions()
     ..sdkRoot = sdkRoot
-    ..target = new VmTarget(new TargetFlags())
+    ..target = target
     ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
     ..omitPlatform = true
     ..onDiagnostic = (DiagnosticMessage message) {
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index 8f9700e..bb052b5 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -545,13 +545,7 @@
   }
 
   void test_keyword_inout() {
-    _assertKeywordToken("inout",
-        configuration: ScannerConfiguration(enableVariance: true));
-  }
-
-  void test_keyword_inout_old() {
-    _assertNotKeywordToken("inout",
-        configuration: ScannerConfiguration(enableVariance: false));
+    _assertKeywordToken("inout");
   }
 
   void test_keyword_is() {
@@ -601,13 +595,7 @@
   }
 
   void test_keyword_out() {
-    _assertKeywordToken("out",
-        configuration: ScannerConfiguration(enableVariance: true));
-  }
-
-  void test_keyword_out_old() {
-    _assertNotKeywordToken("out",
-        configuration: ScannerConfiguration(enableVariance: false));
+    _assertKeywordToken("out");
   }
 
   void test_keyword_part() {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 893e05d..351b53d 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -14,6 +14,8 @@
 accounts
 accumulated
 accumulating
+acon
+acov
 across
 affecting
 afterwards
@@ -21,6 +23,7 @@
 ahe
 ai
 aiki
+ainv
 aka
 alexmarkov
 aligned
@@ -299,6 +302,8 @@
 fasta
 favoring
 fc
+fcon
+fcov
 fe
 feff
 ff
@@ -309,6 +314,7 @@
 ffi
 file's
 filenames
+finv
 firsts
 fishy
 fishythefish
@@ -331,6 +337,7 @@
 frontend
 frontends
 fs
+fsource
 function's
 fuse
 futured
@@ -377,6 +384,7 @@
 human
 i
 i'll
+i2b
 id
 identifies
 identifying
@@ -438,13 +446,14 @@
 juxtaposition
 juxtapositions
 k
-k’s
+kallentu
 kernel's
 kernel2kernel
 klass
 kmillikin
 kustermann
 kv
+k’s
 l
 lacks
 lang
@@ -621,13 +630,13 @@
 quick
 quoted
 r
+r'$creation
 r'\f
 r'\r
 r'\s
 r'\t
 r'\u
 r'\v
-r'$creation
 radix
 raises
 ran
@@ -1003,6 +1012,7 @@
 xxxxxx
 xxxxxxx
 y
+y`s
 yaml
 yet
 yielding
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 00968fa..40d83cd 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -97,8 +97,8 @@
 also
 alternating
 alternative
-alternatives
 alternatively
+alternatives
 although
 always
 ambiguous
@@ -251,6 +251,7 @@
 bets
 better
 between
+beyond
 big
 bigint
 binaries
@@ -278,6 +279,7 @@
 bound
 boundary
 bounded
+boundedness
 boundless
 bounds
 box
@@ -319,6 +321,7 @@
 calculated
 calculates
 calculation
+calculator
 call
 callback
 called
@@ -740,6 +743,7 @@
 development
 devices
 devise
+dfs
 diagnostic
 diagnostics
 did
@@ -812,6 +816,7 @@
 drive
 driver
 drop
+dropped
 dropping
 due
 dump
@@ -1628,6 +1633,7 @@
 matcher
 matches
 matching
+material
 math
 mathematical
 matter
@@ -1725,6 +1731,7 @@
 mutate
 mutated
 mutates
+mutating
 mutation
 mutations
 mutual
@@ -1958,10 +1965,10 @@
 piping
 pivot
 place
-places
 placed
 placeholder
 placeholders
+places
 plain
 plan
 platform
@@ -2292,6 +2299,7 @@
 restores
 restrict
 restricted
+restrictive
 result
 resulting
 results
@@ -2592,6 +2600,7 @@
 substring
 substrings
 substructures
+subterm
 subterms
 subtly
 subtract
@@ -2922,6 +2931,7 @@
 var
 variable
 variables
+variance
 various
 verbose
 verification
@@ -2939,6 +2949,7 @@
 very
 via
 view
+viewed
 violate
 violates
 violation
diff --git a/pkg/front_end/testcases/all_variances.dart b/pkg/front_end/testcases/all_variances.dart
new file mode 100644
index 0000000..3f1a118
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The test checks how type parameters of different variances are serialized.
+
+typedef F<W, X, Y, Z> = X Function(Y, Z Function(Z));
+
+main() {}
diff --git a/pkg/front_end/testcases/all_variances.dart.legacy.expect b/pkg/front_end/testcases/all_variances.dart.legacy.expect
new file mode 100644
index 0000000..add5d55
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart.legacy.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated W extends core::Object = dynamic, X extends core::Object = dynamic, contravariant Y extends core::Object = dynamic, invariant Z extends core::Object = dynamic> = (Y, (Z) → Z) → X;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/all_variances.dart.legacy.transformed.expect b/pkg/front_end/testcases/all_variances.dart.legacy.transformed.expect
new file mode 100644
index 0000000..add5d55
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart.legacy.transformed.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated W extends core::Object = dynamic, X extends core::Object = dynamic, contravariant Y extends core::Object = dynamic, invariant Z extends core::Object = dynamic> = (Y, (Z) → Z) → X;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/all_variances.dart.outline.expect b/pkg/front_end/testcases/all_variances.dart.outline.expect
new file mode 100644
index 0000000..23f7ffa
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated W extends core::Object* = dynamic, X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> = (Y*, (Z*) →* Z*) →* X*;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/all_variances.dart.strong.expect b/pkg/front_end/testcases/all_variances.dart.strong.expect
new file mode 100644
index 0000000..f7afd1b
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart.strong.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated W extends core::Object* = dynamic, X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> = (Y*, (Z*) →* Z*) →* X*;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/all_variances.dart.strong.transformed.expect b/pkg/front_end/testcases/all_variances.dart.strong.transformed.expect
new file mode 100644
index 0000000..f7afd1b
--- /dev/null
+++ b/pkg/front_end/testcases/all_variances.dart.strong.transformed.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated W extends core::Object* = dynamic, X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> = (Y*, (Z*) →* Z*) →* X*;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/expression/lib_nonshown_ctor.expression.yaml.expect b/pkg/front_end/testcases/expression/lib_nonshown_ctor.expression.yaml.expect
index b7af5e3..e7333cd 100644
--- a/pkg/front_end/testcases/expression/lib_nonshown_ctor.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/lib_nonshown_ctor.expression.yaml.expect
@@ -2,10 +2,6 @@
   org-dartlang-debug:synthetic_debug_expression:1:5: Error: Method not found: 'Directory'.
   new Directory("test")
       ^^^^^^^^^
-  org-dartlang-debug:synthetic_debug_expression:1:14: Error: Too many positional arguments: 0 allowed, but 1 found.
-  Try removing the extra positional arguments.
-  new Directory("test")
-               ^
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
   return invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:5: Error: Method not found: 'Directory'.\nnew Directory(\"test\")\n    ^^^^^^^^^";
diff --git a/pkg/front_end/testcases/extensions/annotations.dart b/pkg/front_end/testcases/extensions/annotations.dart
new file mode 100644
index 0000000..0e0b623
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  @pragma('dart2js:noInline')
+  instanceMethod() {}
+
+  @pragma('dart2js:noInline')
+  static staticMethod() {}
+}
+
+extension Extension on Class {
+  @pragma('dart2js:noInline')
+  extensionInstanceMethod() {}
+
+  @pragma('dart2js:noInline')
+  static extensionStaticMethod() {}
+}
+
+@pragma('dart2js:noInline')
+topLevelMethod() {}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.outline.expect b/pkg/front_end/testcases/extensions/annotations.dart.outline.expect
new file mode 100644
index 0000000..1c72331
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart.outline.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  @core::pragma::_("dart2js:noInline")
+  method instanceMethod() → dynamic
+    ;
+  @core::pragma::_("dart2js:noInline")
+  static method staticMethod() → dynamic
+    ;
+}
+extension Extension on self::Class* {
+  method extensionInstanceMethod = self::Extension|extensionInstanceMethod;
+  tearoff extensionInstanceMethod = self::Extension|get#extensionInstanceMethod;
+  static method extensionStaticMethod = self::Extension|extensionStaticMethod;
+}
+@core::pragma::_("dart2js:noInline")
+static method Extension|extensionInstanceMethod(final self::Class* #this) → dynamic
+  ;
+static method Extension|get#extensionInstanceMethod(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|extensionInstanceMethod(#this);
+@core::pragma::_("dart2js:noInline")
+static method Extension|extensionStaticMethod() → dynamic
+  ;
+@core::pragma::_("dart2js:noInline")
+static method topLevelMethod() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.strong.expect b/pkg/front_end/testcases/extensions/annotations.dart.strong.expect
new file mode 100644
index 0000000..73aac11
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart.strong.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  @#C3
+  method instanceMethod() → dynamic {}
+  @#C3
+  static method staticMethod() → dynamic {}
+}
+extension Extension on self::Class* {
+  method extensionInstanceMethod = self::Extension|extensionInstanceMethod;
+  tearoff extensionInstanceMethod = self::Extension|get#extensionInstanceMethod;
+  static method extensionStaticMethod = self::Extension|extensionStaticMethod;
+}
+@#C3
+static method Extension|extensionInstanceMethod(final self::Class* #this) → dynamic {}
+static method Extension|get#extensionInstanceMethod(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|extensionInstanceMethod(#this);
+@#C3
+static method Extension|extensionStaticMethod() → dynamic {}
+@#C3
+static method topLevelMethod() → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "dart2js:noInline"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect
new file mode 100644
index 0000000..73aac11
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  @#C3
+  method instanceMethod() → dynamic {}
+  @#C3
+  static method staticMethod() → dynamic {}
+}
+extension Extension on self::Class* {
+  method extensionInstanceMethod = self::Extension|extensionInstanceMethod;
+  tearoff extensionInstanceMethod = self::Extension|get#extensionInstanceMethod;
+  static method extensionStaticMethod = self::Extension|extensionStaticMethod;
+}
+@#C3
+static method Extension|extensionInstanceMethod(final self::Class* #this) → dynamic {}
+static method Extension|get#extensionInstanceMethod(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|extensionInstanceMethod(#this);
+@#C3
+static method Extension|extensionStaticMethod() → dynamic {}
+@#C3
+static method topLevelMethod() → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "dart2js:noInline"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart b/pkg/front_end/testcases/extensions/compounds.dart
index 1664612..812e0c9 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart
+++ b/pkg/front_end/testcases/extensions/compounds.dart
@@ -46,11 +46,53 @@
   void set property(Number value) {
     field = value;
   }
+
+  testImplicitProperties() {
+    Number n0 = new Number(0);
+    Number n1 = new Number(1);
+    Number n2 = new Number(2);
+
+    expect(n0, property);
+    expect(n1, property += n1);
+    expect(n2, property += n1);
+    expect(n0, property -= n2);
+    expect(n1, property += n1);
+    expect(n0, property -= n1);
+    expect(n1, ++property);
+    expect(n0, --property);
+    expect(n0, property++);
+    expect(n1, property--);
+    expect(n0, property);
+
+    expect(n0, property);
+    property += n1;
+    expect(n1, property);
+    property += n1;
+    expect(n2, property);
+    property -= n2;
+    expect(n0, property);
+    property += n1;
+    expect(n1, property);
+    property -= n1;
+    expect(n0, property);
+    ++property;
+    expect(n1, property);
+    --property;
+    expect(n0, property);
+    property++;
+    expect(n1, property);
+    property--;
+    expect(n0, property);
+  }
 }
 
 main() {
   testLocals();
   testProperties();
+  testExplicitProperties();
+  testExplicitNullAwareProperties(null);
+  testExplicitNullAwareProperties(new Class(new Number(0)));
+  new Class(new Number(0)).testImplicitProperties();
 }
 
 testLocals() {
@@ -69,6 +111,26 @@
   expect(n0, v++);
   expect(n1, v--);
   expect(n0, v);
+
+  expect(n0, v);
+  v += n1;
+  expect(n1, v);
+  v += n1;
+  expect(n2, v);
+  v -= n2;
+  expect(n0, v);
+  v += n1;
+  expect(n1, v);
+  v -= n1;
+  expect(n0, v);
+  ++v;
+  expect(n1, v);
+  --v;
+  expect(n0, v);
+  v++;
+  expect(n1, v);
+  v--;
+  expect(n0, v);
 }
 
 testProperties() {
@@ -88,6 +150,26 @@
   expect(n1, v.field--);
   expect(n0, v.field);
 
+  expect(n0, v.field);
+  v.field += n1;
+  expect(n1, v.field);
+  v.field += n1;
+  expect(n2, v.field);
+  v.field -= n2;
+  expect(n0, v.field);
+  v.field += n1;
+  expect(n1, v.field);
+  v.field -= n1;
+  expect(n0, v.field);
+  ++v.field;
+  expect(n1, v.field);
+  --v.field;
+  expect(n0, v.field);
+  v.field++;
+  expect(n1, v.field);
+  v.field--;
+  expect(n0, v.field);
+
   expect(n0, v.property);
   expect(n1, v.property += n1);
   expect(n2, v.property += n1);
@@ -99,9 +181,109 @@
   expect(n0, v.property++);
   expect(n1, v.property--);
   expect(n0, v.property);
+
+  expect(n0, v.property);
+  v.property += n1;
+  expect(n1, v.property);
+  v.property += n1;
+  expect(n2, v.property);
+  v.property -= n2;
+  expect(n0, v.property);
+  v.property += n1;
+  expect(n1, v.property);
+  v.property -= n1;
+  expect(n0, v.property);
+  ++v.property;
+  expect(n1, v.property);
+  --v.property;
+  expect(n0, v.property);
+  v.property++;
+  expect(n1, v.property);
+  v.property--;
+  expect(n0, v.property);
 }
 
-expect(expected, actual) {
+testExplicitProperties() {
+  Number n0 = new Number(0);
+  Number n1 = new Number(1);
+  Number n2 = new Number(2);
+  Class v = new Class(n0);
+
+  expect(n0, ClassExtension(v).property);
+  expect(n1, ClassExtension(v).property += n1);
+  expect(n2, ClassExtension(v).property += n1);
+  expect(n0, ClassExtension(v).property -= n2);
+  expect(n1, ClassExtension(v).property += n1);
+  expect(n0, ClassExtension(v).property -= n1);
+  expect(n1, ++ClassExtension(v).property);
+  expect(n0, --ClassExtension(v).property);
+  expect(n0, ClassExtension(v).property++);
+  expect(n1, ClassExtension(v).property--);
+  expect(n0, ClassExtension(v).property);
+
+  expect(n0, ClassExtension(v).property);
+  ClassExtension(v).property += n1;
+  expect(n1, ClassExtension(v).property);
+  ClassExtension(v).property += n1;
+  expect(n2, ClassExtension(v).property);
+  ClassExtension(v).property -= n2;
+  expect(n0, ClassExtension(v).property);
+  ClassExtension(v).property += n1;
+  expect(n1, ClassExtension(v).property);
+  ClassExtension(v).property -= n1;
+  expect(n0, ClassExtension(v).property);
+  ++ClassExtension(v).property;
+  expect(n1, ClassExtension(v).property);
+  --ClassExtension(v).property;
+  expect(n0, ClassExtension(v).property);
+  ClassExtension(v).property++;
+  expect(n1, ClassExtension(v).property);
+  ClassExtension(v).property--;
+  expect(n0, ClassExtension(v).property);
+}
+
+testExplicitNullAwareProperties(Class v) {
+  Number n0 = new Number(0);
+  Number n1 = new Number(1);
+  Number n2 = new Number(2);
+
+  expect(n0, ClassExtension(v)?.property, v == null);
+  expect(n1, ClassExtension(v)?.property += n1, v == null);
+  expect(n2, ClassExtension(v)?.property += n1, v == null);
+  expect(n0, ClassExtension(v)?.property -= n2, v == null);
+  expect(n1, ClassExtension(v)?.property += n1, v == null);
+  expect(n0, ClassExtension(v)?.property -= n1, v == null);
+  expect(n1, ++ClassExtension(v)?.property, v == null);
+  expect(n0, --ClassExtension(v)?.property, v == null);
+  expect(n0, ClassExtension(v)?.property++, v == null);
+  expect(n1, ClassExtension(v)?.property--, v == null);
+  expect(n0, ClassExtension(v)?.property, v == null);
+
+  expect(n0, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property += n1;
+  expect(n1, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property += n1;
+  expect(n2, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property -= n2;
+  expect(n0, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property += n1;
+  expect(n1, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property -= n1;
+  expect(n0, ClassExtension(v)?.property, v == null);
+  ++ClassExtension(v)?.property;
+  expect(n1, ClassExtension(v)?.property, v == null);
+  --ClassExtension(v)?.property;
+  expect(n0, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property++;
+  expect(n1, ClassExtension(v)?.property, v == null);
+  ClassExtension(v)?.property--;
+  expect(n0, ClassExtension(v)?.property, v == null);
+}
+
+expect(expected, actual, [expectNull = false]) {
+  if (expectNull) {
+    expected = null;
+  }
   if (expected != actual) {
     throw 'Mismatch: expected=$expected, actual=$actual';
   }
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.outline.expect b/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
index 10363aa..42ab3e2 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
@@ -24,6 +24,8 @@
 }
 extension ClassExtension on self::Class* {
   get property = self::ClassExtension|get#property;
+  method testImplicitProperties = self::ClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number*
@@ -34,11 +36,19 @@
   ;
 static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → void
   ;
+static method ClassExtension|testImplicitProperties(final self::Class* #this) → dynamic
+  ;
+static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
 static method main() → dynamic
   ;
 static method testLocals() → dynamic
   ;
 static method testProperties() → dynamic
   ;
-static method expect(dynamic expected, dynamic actual) → dynamic
+static method testExplicitProperties() → dynamic
+  ;
+static method testExplicitNullAwareProperties(self::Class* v) → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual, [dynamic expectNull]) → dynamic
   ;
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
index 1360e1d..e0e9cdf 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
@@ -26,6 +26,8 @@
 }
 extension ClassExtension on self::Class* {
   get property = self::ClassExtension|get#property;
+  method testImplicitProperties = self::ClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number* {
@@ -54,14 +56,53 @@
 }
 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;
+static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → void {
   #this.{self::Class::field} = value;
-  return #t1;
 }
+static method ClassExtension|testImplicitProperties(final self::Class* #this) → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::expect(n1, let final self::Number* #t1 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t2 = self::ClassExtension|set#property(#this, #t1) in #t1);
+  self::expect(n2, let final self::Number* #t3 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t4 = self::ClassExtension|set#property(#this, #t3) in #t3);
+  self::expect(n0, let final self::Number* #t5 = self::NumberExtension|-(self::ClassExtension|get#property(#this), n2) in let final void #t6 = self::ClassExtension|set#property(#this, #t5) in #t5);
+  self::expect(n1, let final self::Number* #t7 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t8 = self::ClassExtension|set#property(#this, #t7) in #t7);
+  self::expect(n0, let final self::Number* #t9 = self::NumberExtension|-(self::ClassExtension|get#property(#this), n1) in let final void #t10 = self::ClassExtension|set#property(#this, #t9) in #t9);
+  self::expect(n1, let final self::Number* #t11 = self::NumberExtension|+(self::ClassExtension|get#property(#this), 1) in let final void #t12 = self::ClassExtension|set#property(#this, #t11) in #t11);
+  self::expect(n0, let final self::Number* #t13 = self::NumberExtension|-(self::ClassExtension|get#property(#this), 1) in let final void #t14 = self::ClassExtension|set#property(#this, #t13) in #t13);
+  self::expect(n0, let final self::Number* #t15 = self::ClassExtension|get#property(#this) in let final self::Number* #t16 = self::ClassExtension|set#property(#this, self::NumberExtension|+(#t15, 1)) in #t15);
+  self::expect(n1, let final self::Number* #t17 = self::ClassExtension|get#property(#this) in let final self::Number* #t18 = self::ClassExtension|set#property(#this, self::NumberExtension|-(#t17, 1)) in #t17);
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n2, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), n2));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), n1));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  let final self::Number* #t19 = self::NumberExtension|+(self::ClassExtension|get#property(#this), 1) in let final void #t20 = self::ClassExtension|set#property(#this, #t19) in #t19;
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  let final self::Number* #t21 = self::NumberExtension|-(self::ClassExtension|get#property(#this), 1) in let final void #t22 = self::ClassExtension|set#property(#this, #t21) in #t21;
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), 1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), 1));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+}
+static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
 static method main() → dynamic {
   self::testLocals();
   self::testProperties();
+  self::testExplicitProperties();
+  self::testExplicitNullAwareProperties(null);
+  self::testExplicitNullAwareProperties(new self::Class::•(new self::Number::•(0)));
+  self::ClassExtension|testImplicitProperties(new self::Class::•(new self::Number::•(0)));
 }
 static method testLocals() → dynamic {
   self::Number* n0 = new self::Number::•(0);
@@ -76,8 +117,27 @@
   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, let final self::Number* #t23 = v in let final self::Number* #t24 = v = self::NumberExtension|+(#t23, 1) in #t23);
+  self::expect(n1, let final self::Number* #t25 = v in let final self::Number* #t26 = v = self::NumberExtension|-(#t25, 1) in #t25);
+  self::expect(n0, v);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n1, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n2, v);
+  v = self::NumberExtension|-(v, n2);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, n1);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, 1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, 1);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, 1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, 1);
   self::expect(n0, v);
 }
 static method testProperties() → dynamic {
@@ -86,30 +146,146 @@
   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(n1, let final self::Class* #t27 = v in #t27.{self::Class::field} = self::NumberExtension|+(#t27.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t28 = v in #t28.{self::Class::field} = self::NumberExtension|+(#t28.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t29 = v in #t29.{self::Class::field} = self::NumberExtension|-(#t29.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t30 = v in #t30.{self::Class::field} = self::NumberExtension|+(#t30.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t31 = v in #t31.{self::Class::field} = self::NumberExtension|-(#t31.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t32 = v in #t32.{self::Class::field} = self::NumberExtension|+(#t32.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t33 = v in #t33.{self::Class::field} = self::NumberExtension|-(#t33.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t34 = v in let final self::Number* #t35 = #t34.{self::Class::field} in let final self::Number* #t36 = #t34.{self::Class::field} = self::NumberExtension|+(#t35, 1) in #t35);
+  self::expect(n1, let final self::Class* #t37 = v in let final self::Number* #t38 = #t37.{self::Class::field} in let final self::Number* #t39 = #t37.{self::Class::field} = self::NumberExtension|-(#t38, 1) in #t38);
+  self::expect(n0, v.{self::Class::field});
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t40 = v in #t40.{self::Class::field} = self::NumberExtension|+(#t40.{self::Class::field}, n1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t41 = v in #t41.{self::Class::field} = self::NumberExtension|+(#t41.{self::Class::field}, n1);
+  self::expect(n2, v.{self::Class::field});
+  let final self::Class* #t42 = v in #t42.{self::Class::field} = self::NumberExtension|-(#t42.{self::Class::field}, n2);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t43 = v in #t43.{self::Class::field} = self::NumberExtension|+(#t43.{self::Class::field}, n1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t44 = v in #t44.{self::Class::field} = self::NumberExtension|-(#t44.{self::Class::field}, n1);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t45 = v in #t45.{self::Class::field} = self::NumberExtension|+(#t45.{self::Class::field}, 1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t46 = v in #t46.{self::Class::field} = self::NumberExtension|-(#t46.{self::Class::field}, 1);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t47 = v in #t47.{self::Class::field} = self::NumberExtension|+(#t47.{self::Class::field}, 1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t48 = v in #t48.{self::Class::field} = self::NumberExtension|-(#t48.{self::Class::field}, 1);
   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(n1, let final self::Class* #t49 = v in let final self::Class* #t50 = #t49 in let final self::Number* #t51 = self::NumberExtension|+(self::ClassExtension|get#property(#t49), n1) in let final void #t52 = self::ClassExtension|set#property(#t50, #t51) in #t51);
+  self::expect(n2, let final self::Class* #t53 = v in let final self::Class* #t54 = #t53 in let final self::Number* #t55 = self::NumberExtension|+(self::ClassExtension|get#property(#t53), n1) in let final void #t56 = self::ClassExtension|set#property(#t54, #t55) in #t55);
+  self::expect(n0, let final self::Class* #t57 = v in let final self::Class* #t58 = #t57 in let final self::Number* #t59 = self::NumberExtension|-(self::ClassExtension|get#property(#t57), n2) in let final void #t60 = self::ClassExtension|set#property(#t58, #t59) in #t59);
+  self::expect(n1, let final self::Class* #t61 = v in let final self::Class* #t62 = #t61 in let final self::Number* #t63 = self::NumberExtension|+(self::ClassExtension|get#property(#t61), n1) in let final void #t64 = self::ClassExtension|set#property(#t62, #t63) in #t63);
+  self::expect(n0, let final self::Class* #t65 = v in let final self::Class* #t66 = #t65 in let final self::Number* #t67 = self::NumberExtension|-(self::ClassExtension|get#property(#t65), n1) in let final void #t68 = self::ClassExtension|set#property(#t66, #t67) in #t67);
+  self::expect(n1, let final self::Class* #t69 = v in let final self::Class* #t70 = #t69 in let final self::Number* #t71 = self::NumberExtension|+(self::ClassExtension|get#property(#t69), 1) in let final void #t72 = self::ClassExtension|set#property(#t70, #t71) in #t71);
+  self::expect(n0, let final self::Class* #t73 = v in let final self::Class* #t74 = #t73 in let final self::Number* #t75 = self::NumberExtension|-(self::ClassExtension|get#property(#t73), 1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
+  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::ClassExtension|get#property(#t77) in let final self::Number* #t79 = self::ClassExtension|set#property(#t77, self::NumberExtension|+(#t78, 1)) in #t78);
+  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::ClassExtension|get#property(#t80) in let final self::Number* #t82 = self::ClassExtension|set#property(#t80, self::NumberExtension|-(#t81, 1)) in #t81);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t83 = v in self::ClassExtension|set#property(#t83, self::NumberExtension|+(self::ClassExtension|get#property(#t83), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t84 = v in self::ClassExtension|set#property(#t84, self::NumberExtension|+(self::ClassExtension|get#property(#t84), n1));
+  self::expect(n2, self::ClassExtension|get#property(v));
+  let final self::Class* #t85 = v in self::ClassExtension|set#property(#t85, self::NumberExtension|-(self::ClassExtension|get#property(#t85), n2));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t86 = v in self::ClassExtension|set#property(#t86, self::NumberExtension|+(self::ClassExtension|get#property(#t86), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t87 = v in self::ClassExtension|set#property(#t87, self::NumberExtension|-(self::ClassExtension|get#property(#t87), n1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t88 = v in let final self::Class* #t89 = #t88 in let final self::Number* #t90 = self::NumberExtension|+(self::ClassExtension|get#property(#t88), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90;
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t92 = v in let final self::Class* #t93 = #t92 in let final self::Number* #t94 = self::NumberExtension|-(self::ClassExtension|get#property(#t92), 1) in let final void #t95 = self::ClassExtension|set#property(#t93, #t94) in #t94;
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t96 = v in self::ClassExtension|set#property(#t96, self::NumberExtension|+(self::ClassExtension|get#property(#t96), 1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t97 = v in self::ClassExtension|set#property(#t97, self::NumberExtension|-(self::ClassExtension|get#property(#t97), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
-static method expect(dynamic expected, dynamic actual) → dynamic {
+static method testExplicitProperties() → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::Class* v = new self::Class::•(n0);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n1, let final self::Class* #t98 = v in let final self::Number* #t99 = self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1) in let final void #t100 = self::ClassExtension|set#property(#t98, #t99) in #t99);
+  self::expect(n2, let final self::Class* #t101 = v in let final self::Number* #t102 = self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1) in let final void #t103 = self::ClassExtension|set#property(#t101, #t102) in #t102);
+  self::expect(n0, let final self::Class* #t104 = v in let final self::Number* #t105 = self::NumberExtension|-(self::ClassExtension|get#property(#t104), n2) in let final void #t106 = self::ClassExtension|set#property(#t104, #t105) in #t105);
+  self::expect(n1, let final self::Class* #t107 = v in let final self::Number* #t108 = self::NumberExtension|+(self::ClassExtension|get#property(#t107), n1) in let final void #t109 = self::ClassExtension|set#property(#t107, #t108) in #t108);
+  self::expect(n0, let final self::Class* #t110 = v in let final self::Number* #t111 = self::NumberExtension|-(self::ClassExtension|get#property(#t110), n1) in let final void #t112 = self::ClassExtension|set#property(#t110, #t111) in #t111);
+  self::expect(n1, let final self::Class* #t113 = v in let final self::Number* #t114 = self::NumberExtension|+(self::ClassExtension|get#property(#t113), 1) in let final void #t115 = self::ClassExtension|set#property(#t113, #t114) in #t114);
+  self::expect(n0, let final self::Class* #t116 = v in let final self::Number* #t117 = self::NumberExtension|-(self::ClassExtension|get#property(#t116), 1) in let final void #t118 = self::ClassExtension|set#property(#t116, #t117) in #t117);
+  self::expect(n0, let final self::Class* #t119 = v in let final self::Number* #t120 = self::ClassExtension|get#property(#t119) in let final self::Number* #t121 = let final self::Number* #t122 = self::NumberExtension|+(#t120, 1) in let final void #t123 = self::ClassExtension|set#property(#t119, #t122) in #t122 in #t120);
+  self::expect(n1, let final self::Class* #t124 = v in let final self::Number* #t125 = self::ClassExtension|get#property(#t124) in let final self::Number* #t126 = let final self::Number* #t127 = self::NumberExtension|-(#t125, 1) in let final void #t128 = self::ClassExtension|set#property(#t124, #t127) in #t127 in #t125);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t129 = v in self::ClassExtension|set#property(#t129, self::NumberExtension|+(self::ClassExtension|get#property(#t129), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t130 = v in self::ClassExtension|set#property(#t130, self::NumberExtension|+(self::ClassExtension|get#property(#t130), n1));
+  self::expect(n2, self::ClassExtension|get#property(v));
+  let final self::Class* #t131 = v in self::ClassExtension|set#property(#t131, self::NumberExtension|-(self::ClassExtension|get#property(#t131), n2));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t132 = v in self::ClassExtension|set#property(#t132, self::NumberExtension|+(self::ClassExtension|get#property(#t132), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t133 = v in self::ClassExtension|set#property(#t133, self::NumberExtension|-(self::ClassExtension|get#property(#t133), n1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t134 = v in let final self::Number* #t135 = self::NumberExtension|+(self::ClassExtension|get#property(#t134), 1) in let final void #t136 = self::ClassExtension|set#property(#t134, #t135) in #t135;
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t137 = v in let final self::Number* #t138 = self::NumberExtension|-(self::ClassExtension|get#property(#t137), 1) in let final void #t139 = self::ClassExtension|set#property(#t137, #t138) in #t138;
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t140 = v in self::ClassExtension|set#property(#t140, self::NumberExtension|+(self::ClassExtension|get#property(#t140), 1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t141 = v in self::ClassExtension|set#property(#t141, self::NumberExtension|-(self::ClassExtension|get#property(#t141), 1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+}
+static method testExplicitNullAwareProperties(self::Class* v) → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::expect(n0, let final self::Class* #t142 = v in #t142.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t142), v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t143 = v in #t143.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t144 = self::NumberExtension|+(self::ClassExtension|get#property(#t143), n1) in let final void #t145 = self::ClassExtension|set#property(#t143, #t144) in #t144, v.{core::Object::==}(null));
+  self::expect(n2, let final self::Class* #t146 = v in #t146.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t147 = self::NumberExtension|+(self::ClassExtension|get#property(#t146), n1) in let final void #t148 = self::ClassExtension|set#property(#t146, #t147) in #t147, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t149 = v in #t149.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t150 = self::NumberExtension|-(self::ClassExtension|get#property(#t149), n2) in let final void #t151 = self::ClassExtension|set#property(#t149, #t150) in #t150, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t152 = v in #t152.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t153 = self::NumberExtension|+(self::ClassExtension|get#property(#t152), n1) in let final void #t154 = self::ClassExtension|set#property(#t152, #t153) in #t153, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t155 = v in #t155.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t156 = self::NumberExtension|-(self::ClassExtension|get#property(#t155), n1) in let final void #t157 = self::ClassExtension|set#property(#t155, #t156) in #t156, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t158 = v in #t158.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t159 = self::NumberExtension|+(self::ClassExtension|get#property(#t158), 1) in let final void #t160 = self::ClassExtension|set#property(#t158, #t159) in #t159, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t161 = v in #t161.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t162 = self::NumberExtension|-(self::ClassExtension|get#property(#t161), 1) in let final void #t163 = self::ClassExtension|set#property(#t161, #t162) in #t162, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t164 = v in #t164.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t165 = self::ClassExtension|get#property(#t164) in let final self::Number* #t166 = let final self::Number* #t167 = self::NumberExtension|+(#t165, 1) in let final void #t168 = self::ClassExtension|set#property(#t164, #t167) in #t167 in #t165, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t169 = v in #t169.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t170 = self::ClassExtension|get#property(#t169) in let final self::Number* #t171 = let final self::Number* #t172 = self::NumberExtension|-(#t170, 1) in let final void #t173 = self::ClassExtension|set#property(#t169, #t172) in #t172 in #t170, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t174 = v in #t174.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t174), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t175 = v in #t175.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t175), v.{core::Object::==}(null));
+  let final self::Class* #t176 = v in #t176.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t176, self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1));
+  self::expect(n1, let final self::Class* #t177 = v in #t177.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t177), v.{core::Object::==}(null));
+  let final self::Class* #t178 = v in #t178.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t178, self::NumberExtension|+(self::ClassExtension|get#property(#t178), n1));
+  self::expect(n2, let final self::Class* #t179 = v in #t179.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t179), v.{core::Object::==}(null));
+  let final self::Class* #t180 = v in #t180.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t180, self::NumberExtension|-(self::ClassExtension|get#property(#t180), n2));
+  self::expect(n0, let final self::Class* #t181 = v in #t181.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t181), v.{core::Object::==}(null));
+  let final self::Class* #t182 = v in #t182.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t182, self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1));
+  self::expect(n1, let final self::Class* #t183 = v in #t183.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t183), v.{core::Object::==}(null));
+  let final self::Class* #t184 = v in #t184.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t184, self::NumberExtension|-(self::ClassExtension|get#property(#t184), n1));
+  self::expect(n0, let final self::Class* #t185 = v in #t185.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t185), v.{core::Object::==}(null));
+  let final self::Class* #t186 = v in #t186.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t187 = self::NumberExtension|+(self::ClassExtension|get#property(#t186), 1) in let final void #t188 = self::ClassExtension|set#property(#t186, #t187) in #t187;
+  self::expect(n1, let final self::Class* #t189 = v in #t189.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t189), v.{core::Object::==}(null));
+  let final self::Class* #t190 = v in #t190.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t191 = self::NumberExtension|-(self::ClassExtension|get#property(#t190), 1) in let final void #t192 = self::ClassExtension|set#property(#t190, #t191) in #t191;
+  self::expect(n0, let final self::Class* #t193 = v in #t193.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t193), v.{core::Object::==}(null));
+  let final self::Class* #t194 = v in #t194.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t194, self::NumberExtension|+(self::ClassExtension|get#property(#t194), 1));
+  self::expect(n1, let final self::Class* #t195 = v in #t195.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t195), v.{core::Object::==}(null));
+  let final self::Class* #t196 = v in #t196.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t196, self::NumberExtension|-(self::ClassExtension|get#property(#t196), 1));
+  self::expect(n0, let final self::Class* #t197 = v in #t197.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t197), v.{core::Object::==}(null));
+}
+static method expect(dynamic expected, dynamic actual, [dynamic expectNull = #C1]) → dynamic {
+  if(expectNull as{TypeError} core::bool*) {
+    expected = null;
+  }
   if(!expected.{core::Object::==}(actual)) {
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+constants  {
+  #C1 = false
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
index 1360e1d..e0e9cdf 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
@@ -26,6 +26,8 @@
 }
 extension ClassExtension on self::Class* {
   get property = self::ClassExtension|get#property;
+  method testImplicitProperties = self::ClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number* {
@@ -54,14 +56,53 @@
 }
 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;
+static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → void {
   #this.{self::Class::field} = value;
-  return #t1;
 }
+static method ClassExtension|testImplicitProperties(final self::Class* #this) → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::expect(n1, let final self::Number* #t1 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t2 = self::ClassExtension|set#property(#this, #t1) in #t1);
+  self::expect(n2, let final self::Number* #t3 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t4 = self::ClassExtension|set#property(#this, #t3) in #t3);
+  self::expect(n0, let final self::Number* #t5 = self::NumberExtension|-(self::ClassExtension|get#property(#this), n2) in let final void #t6 = self::ClassExtension|set#property(#this, #t5) in #t5);
+  self::expect(n1, let final self::Number* #t7 = self::NumberExtension|+(self::ClassExtension|get#property(#this), n1) in let final void #t8 = self::ClassExtension|set#property(#this, #t7) in #t7);
+  self::expect(n0, let final self::Number* #t9 = self::NumberExtension|-(self::ClassExtension|get#property(#this), n1) in let final void #t10 = self::ClassExtension|set#property(#this, #t9) in #t9);
+  self::expect(n1, let final self::Number* #t11 = self::NumberExtension|+(self::ClassExtension|get#property(#this), 1) in let final void #t12 = self::ClassExtension|set#property(#this, #t11) in #t11);
+  self::expect(n0, let final self::Number* #t13 = self::NumberExtension|-(self::ClassExtension|get#property(#this), 1) in let final void #t14 = self::ClassExtension|set#property(#this, #t13) in #t13);
+  self::expect(n0, let final self::Number* #t15 = self::ClassExtension|get#property(#this) in let final self::Number* #t16 = self::ClassExtension|set#property(#this, self::NumberExtension|+(#t15, 1)) in #t15);
+  self::expect(n1, let final self::Number* #t17 = self::ClassExtension|get#property(#this) in let final self::Number* #t18 = self::ClassExtension|set#property(#this, self::NumberExtension|-(#t17, 1)) in #t17);
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n2, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), n2));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), n1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), n1));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  let final self::Number* #t19 = self::NumberExtension|+(self::ClassExtension|get#property(#this), 1) in let final void #t20 = self::ClassExtension|set#property(#this, #t19) in #t19;
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  let final self::Number* #t21 = self::NumberExtension|-(self::ClassExtension|get#property(#this), 1) in let final void #t22 = self::ClassExtension|set#property(#this, #t21) in #t21;
+  self::expect(n0, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|+(self::ClassExtension|get#property(#this), 1));
+  self::expect(n1, self::ClassExtension|get#property(#this));
+  self::ClassExtension|set#property(#this, self::NumberExtension|-(self::ClassExtension|get#property(#this), 1));
+  self::expect(n0, self::ClassExtension|get#property(#this));
+}
+static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
 static method main() → dynamic {
   self::testLocals();
   self::testProperties();
+  self::testExplicitProperties();
+  self::testExplicitNullAwareProperties(null);
+  self::testExplicitNullAwareProperties(new self::Class::•(new self::Number::•(0)));
+  self::ClassExtension|testImplicitProperties(new self::Class::•(new self::Number::•(0)));
 }
 static method testLocals() → dynamic {
   self::Number* n0 = new self::Number::•(0);
@@ -76,8 +117,27 @@
   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, let final self::Number* #t23 = v in let final self::Number* #t24 = v = self::NumberExtension|+(#t23, 1) in #t23);
+  self::expect(n1, let final self::Number* #t25 = v in let final self::Number* #t26 = v = self::NumberExtension|-(#t25, 1) in #t25);
+  self::expect(n0, v);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n1, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n2, v);
+  v = self::NumberExtension|-(v, n2);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, n1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, n1);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, 1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, 1);
+  self::expect(n0, v);
+  v = self::NumberExtension|+(v, 1);
+  self::expect(n1, v);
+  v = self::NumberExtension|-(v, 1);
   self::expect(n0, v);
 }
 static method testProperties() → dynamic {
@@ -86,30 +146,146 @@
   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(n1, let final self::Class* #t27 = v in #t27.{self::Class::field} = self::NumberExtension|+(#t27.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t28 = v in #t28.{self::Class::field} = self::NumberExtension|+(#t28.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t29 = v in #t29.{self::Class::field} = self::NumberExtension|-(#t29.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t30 = v in #t30.{self::Class::field} = self::NumberExtension|+(#t30.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t31 = v in #t31.{self::Class::field} = self::NumberExtension|-(#t31.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t32 = v in #t32.{self::Class::field} = self::NumberExtension|+(#t32.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t33 = v in #t33.{self::Class::field} = self::NumberExtension|-(#t33.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t34 = v in let final self::Number* #t35 = #t34.{self::Class::field} in let final self::Number* #t36 = #t34.{self::Class::field} = self::NumberExtension|+(#t35, 1) in #t35);
+  self::expect(n1, let final self::Class* #t37 = v in let final self::Number* #t38 = #t37.{self::Class::field} in let final self::Number* #t39 = #t37.{self::Class::field} = self::NumberExtension|-(#t38, 1) in #t38);
+  self::expect(n0, v.{self::Class::field});
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t40 = v in #t40.{self::Class::field} = self::NumberExtension|+(#t40.{self::Class::field}, n1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t41 = v in #t41.{self::Class::field} = self::NumberExtension|+(#t41.{self::Class::field}, n1);
+  self::expect(n2, v.{self::Class::field});
+  let final self::Class* #t42 = v in #t42.{self::Class::field} = self::NumberExtension|-(#t42.{self::Class::field}, n2);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t43 = v in #t43.{self::Class::field} = self::NumberExtension|+(#t43.{self::Class::field}, n1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t44 = v in #t44.{self::Class::field} = self::NumberExtension|-(#t44.{self::Class::field}, n1);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t45 = v in #t45.{self::Class::field} = self::NumberExtension|+(#t45.{self::Class::field}, 1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t46 = v in #t46.{self::Class::field} = self::NumberExtension|-(#t46.{self::Class::field}, 1);
+  self::expect(n0, v.{self::Class::field});
+  let final self::Class* #t47 = v in #t47.{self::Class::field} = self::NumberExtension|+(#t47.{self::Class::field}, 1);
+  self::expect(n1, v.{self::Class::field});
+  let final self::Class* #t48 = v in #t48.{self::Class::field} = self::NumberExtension|-(#t48.{self::Class::field}, 1);
   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(n1, let final self::Class* #t49 = v in let final self::Class* #t50 = #t49 in let final self::Number* #t51 = self::NumberExtension|+(self::ClassExtension|get#property(#t49), n1) in let final void #t52 = self::ClassExtension|set#property(#t50, #t51) in #t51);
+  self::expect(n2, let final self::Class* #t53 = v in let final self::Class* #t54 = #t53 in let final self::Number* #t55 = self::NumberExtension|+(self::ClassExtension|get#property(#t53), n1) in let final void #t56 = self::ClassExtension|set#property(#t54, #t55) in #t55);
+  self::expect(n0, let final self::Class* #t57 = v in let final self::Class* #t58 = #t57 in let final self::Number* #t59 = self::NumberExtension|-(self::ClassExtension|get#property(#t57), n2) in let final void #t60 = self::ClassExtension|set#property(#t58, #t59) in #t59);
+  self::expect(n1, let final self::Class* #t61 = v in let final self::Class* #t62 = #t61 in let final self::Number* #t63 = self::NumberExtension|+(self::ClassExtension|get#property(#t61), n1) in let final void #t64 = self::ClassExtension|set#property(#t62, #t63) in #t63);
+  self::expect(n0, let final self::Class* #t65 = v in let final self::Class* #t66 = #t65 in let final self::Number* #t67 = self::NumberExtension|-(self::ClassExtension|get#property(#t65), n1) in let final void #t68 = self::ClassExtension|set#property(#t66, #t67) in #t67);
+  self::expect(n1, let final self::Class* #t69 = v in let final self::Class* #t70 = #t69 in let final self::Number* #t71 = self::NumberExtension|+(self::ClassExtension|get#property(#t69), 1) in let final void #t72 = self::ClassExtension|set#property(#t70, #t71) in #t71);
+  self::expect(n0, let final self::Class* #t73 = v in let final self::Class* #t74 = #t73 in let final self::Number* #t75 = self::NumberExtension|-(self::ClassExtension|get#property(#t73), 1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
+  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::ClassExtension|get#property(#t77) in let final self::Number* #t79 = self::ClassExtension|set#property(#t77, self::NumberExtension|+(#t78, 1)) in #t78);
+  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::ClassExtension|get#property(#t80) in let final self::Number* #t82 = self::ClassExtension|set#property(#t80, self::NumberExtension|-(#t81, 1)) in #t81);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t83 = v in self::ClassExtension|set#property(#t83, self::NumberExtension|+(self::ClassExtension|get#property(#t83), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t84 = v in self::ClassExtension|set#property(#t84, self::NumberExtension|+(self::ClassExtension|get#property(#t84), n1));
+  self::expect(n2, self::ClassExtension|get#property(v));
+  let final self::Class* #t85 = v in self::ClassExtension|set#property(#t85, self::NumberExtension|-(self::ClassExtension|get#property(#t85), n2));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t86 = v in self::ClassExtension|set#property(#t86, self::NumberExtension|+(self::ClassExtension|get#property(#t86), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t87 = v in self::ClassExtension|set#property(#t87, self::NumberExtension|-(self::ClassExtension|get#property(#t87), n1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t88 = v in let final self::Class* #t89 = #t88 in let final self::Number* #t90 = self::NumberExtension|+(self::ClassExtension|get#property(#t88), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90;
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t92 = v in let final self::Class* #t93 = #t92 in let final self::Number* #t94 = self::NumberExtension|-(self::ClassExtension|get#property(#t92), 1) in let final void #t95 = self::ClassExtension|set#property(#t93, #t94) in #t94;
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t96 = v in self::ClassExtension|set#property(#t96, self::NumberExtension|+(self::ClassExtension|get#property(#t96), 1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t97 = v in self::ClassExtension|set#property(#t97, self::NumberExtension|-(self::ClassExtension|get#property(#t97), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
-static method expect(dynamic expected, dynamic actual) → dynamic {
+static method testExplicitProperties() → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::Class* v = new self::Class::•(n0);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n1, let final self::Class* #t98 = v in let final self::Number* #t99 = self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1) in let final void #t100 = self::ClassExtension|set#property(#t98, #t99) in #t99);
+  self::expect(n2, let final self::Class* #t101 = v in let final self::Number* #t102 = self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1) in let final void #t103 = self::ClassExtension|set#property(#t101, #t102) in #t102);
+  self::expect(n0, let final self::Class* #t104 = v in let final self::Number* #t105 = self::NumberExtension|-(self::ClassExtension|get#property(#t104), n2) in let final void #t106 = self::ClassExtension|set#property(#t104, #t105) in #t105);
+  self::expect(n1, let final self::Class* #t107 = v in let final self::Number* #t108 = self::NumberExtension|+(self::ClassExtension|get#property(#t107), n1) in let final void #t109 = self::ClassExtension|set#property(#t107, #t108) in #t108);
+  self::expect(n0, let final self::Class* #t110 = v in let final self::Number* #t111 = self::NumberExtension|-(self::ClassExtension|get#property(#t110), n1) in let final void #t112 = self::ClassExtension|set#property(#t110, #t111) in #t111);
+  self::expect(n1, let final self::Class* #t113 = v in let final self::Number* #t114 = self::NumberExtension|+(self::ClassExtension|get#property(#t113), 1) in let final void #t115 = self::ClassExtension|set#property(#t113, #t114) in #t114);
+  self::expect(n0, let final self::Class* #t116 = v in let final self::Number* #t117 = self::NumberExtension|-(self::ClassExtension|get#property(#t116), 1) in let final void #t118 = self::ClassExtension|set#property(#t116, #t117) in #t117);
+  self::expect(n0, let final self::Class* #t119 = v in let final self::Number* #t120 = self::ClassExtension|get#property(#t119) in let final self::Number* #t121 = let final self::Number* #t122 = self::NumberExtension|+(#t120, 1) in let final void #t123 = self::ClassExtension|set#property(#t119, #t122) in #t122 in #t120);
+  self::expect(n1, let final self::Class* #t124 = v in let final self::Number* #t125 = self::ClassExtension|get#property(#t124) in let final self::Number* #t126 = let final self::Number* #t127 = self::NumberExtension|-(#t125, 1) in let final void #t128 = self::ClassExtension|set#property(#t124, #t127) in #t127 in #t125);
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t129 = v in self::ClassExtension|set#property(#t129, self::NumberExtension|+(self::ClassExtension|get#property(#t129), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t130 = v in self::ClassExtension|set#property(#t130, self::NumberExtension|+(self::ClassExtension|get#property(#t130), n1));
+  self::expect(n2, self::ClassExtension|get#property(v));
+  let final self::Class* #t131 = v in self::ClassExtension|set#property(#t131, self::NumberExtension|-(self::ClassExtension|get#property(#t131), n2));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t132 = v in self::ClassExtension|set#property(#t132, self::NumberExtension|+(self::ClassExtension|get#property(#t132), n1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t133 = v in self::ClassExtension|set#property(#t133, self::NumberExtension|-(self::ClassExtension|get#property(#t133), n1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t134 = v in let final self::Number* #t135 = self::NumberExtension|+(self::ClassExtension|get#property(#t134), 1) in let final void #t136 = self::ClassExtension|set#property(#t134, #t135) in #t135;
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t137 = v in let final self::Number* #t138 = self::NumberExtension|-(self::ClassExtension|get#property(#t137), 1) in let final void #t139 = self::ClassExtension|set#property(#t137, #t138) in #t138;
+  self::expect(n0, self::ClassExtension|get#property(v));
+  let final self::Class* #t140 = v in self::ClassExtension|set#property(#t140, self::NumberExtension|+(self::ClassExtension|get#property(#t140), 1));
+  self::expect(n1, self::ClassExtension|get#property(v));
+  let final self::Class* #t141 = v in self::ClassExtension|set#property(#t141, self::NumberExtension|-(self::ClassExtension|get#property(#t141), 1));
+  self::expect(n0, self::ClassExtension|get#property(v));
+}
+static method testExplicitNullAwareProperties(self::Class* v) → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::expect(n0, let final self::Class* #t142 = v in #t142.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t142), v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t143 = v in #t143.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t144 = self::NumberExtension|+(self::ClassExtension|get#property(#t143), n1) in let final void #t145 = self::ClassExtension|set#property(#t143, #t144) in #t144, v.{core::Object::==}(null));
+  self::expect(n2, let final self::Class* #t146 = v in #t146.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t147 = self::NumberExtension|+(self::ClassExtension|get#property(#t146), n1) in let final void #t148 = self::ClassExtension|set#property(#t146, #t147) in #t147, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t149 = v in #t149.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t150 = self::NumberExtension|-(self::ClassExtension|get#property(#t149), n2) in let final void #t151 = self::ClassExtension|set#property(#t149, #t150) in #t150, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t152 = v in #t152.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t153 = self::NumberExtension|+(self::ClassExtension|get#property(#t152), n1) in let final void #t154 = self::ClassExtension|set#property(#t152, #t153) in #t153, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t155 = v in #t155.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t156 = self::NumberExtension|-(self::ClassExtension|get#property(#t155), n1) in let final void #t157 = self::ClassExtension|set#property(#t155, #t156) in #t156, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t158 = v in #t158.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t159 = self::NumberExtension|+(self::ClassExtension|get#property(#t158), 1) in let final void #t160 = self::ClassExtension|set#property(#t158, #t159) in #t159, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t161 = v in #t161.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t162 = self::NumberExtension|-(self::ClassExtension|get#property(#t161), 1) in let final void #t163 = self::ClassExtension|set#property(#t161, #t162) in #t162, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t164 = v in #t164.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t165 = self::ClassExtension|get#property(#t164) in let final self::Number* #t166 = let final self::Number* #t167 = self::NumberExtension|+(#t165, 1) in let final void #t168 = self::ClassExtension|set#property(#t164, #t167) in #t167 in #t165, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t169 = v in #t169.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t170 = self::ClassExtension|get#property(#t169) in let final self::Number* #t171 = let final self::Number* #t172 = self::NumberExtension|-(#t170, 1) in let final void #t173 = self::ClassExtension|set#property(#t169, #t172) in #t172 in #t170, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t174 = v in #t174.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t174), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t175 = v in #t175.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t175), v.{core::Object::==}(null));
+  let final self::Class* #t176 = v in #t176.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t176, self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1));
+  self::expect(n1, let final self::Class* #t177 = v in #t177.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t177), v.{core::Object::==}(null));
+  let final self::Class* #t178 = v in #t178.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t178, self::NumberExtension|+(self::ClassExtension|get#property(#t178), n1));
+  self::expect(n2, let final self::Class* #t179 = v in #t179.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t179), v.{core::Object::==}(null));
+  let final self::Class* #t180 = v in #t180.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t180, self::NumberExtension|-(self::ClassExtension|get#property(#t180), n2));
+  self::expect(n0, let final self::Class* #t181 = v in #t181.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t181), v.{core::Object::==}(null));
+  let final self::Class* #t182 = v in #t182.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t182, self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1));
+  self::expect(n1, let final self::Class* #t183 = v in #t183.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t183), v.{core::Object::==}(null));
+  let final self::Class* #t184 = v in #t184.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t184, self::NumberExtension|-(self::ClassExtension|get#property(#t184), n1));
+  self::expect(n0, let final self::Class* #t185 = v in #t185.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t185), v.{core::Object::==}(null));
+  let final self::Class* #t186 = v in #t186.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t187 = self::NumberExtension|+(self::ClassExtension|get#property(#t186), 1) in let final void #t188 = self::ClassExtension|set#property(#t186, #t187) in #t187;
+  self::expect(n1, let final self::Class* #t189 = v in #t189.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t189), v.{core::Object::==}(null));
+  let final self::Class* #t190 = v in #t190.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t191 = self::NumberExtension|-(self::ClassExtension|get#property(#t190), 1) in let final void #t192 = self::ClassExtension|set#property(#t190, #t191) in #t191;
+  self::expect(n0, let final self::Class* #t193 = v in #t193.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t193), v.{core::Object::==}(null));
+  let final self::Class* #t194 = v in #t194.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t194, self::NumberExtension|+(self::ClassExtension|get#property(#t194), 1));
+  self::expect(n1, let final self::Class* #t195 = v in #t195.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t195), v.{core::Object::==}(null));
+  let final self::Class* #t196 = v in #t196.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t196, self::NumberExtension|-(self::ClassExtension|get#property(#t196), 1));
+  self::expect(n0, let final self::Class* #t197 = v in #t197.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t197), v.{core::Object::==}(null));
+}
+static method expect(dynamic expected, dynamic actual, [dynamic expectNull = #C1]) → dynamic {
+  if(expectNull as{TypeError} core::bool*) {
+    expected = null;
+  }
   if(!expected.{core::Object::==}(actual)) {
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+constants  {
+  #C1 = false
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
index 28a5f00..ffaf9b8 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
@@ -13,30 +13,60 @@
 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
+pkg/front_end/testcases/extensions/compounds.dart:104:16: Context: Write to v@2369
   expect(n1, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:63:16: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:105:16: Context: Write to v@2369
   expect(n2, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:64:16: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:106:16: Context: Write to v@2369
   expect(n0, v -= n2);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:65:16: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:107:16: Context: Write to v@2369
   expect(n1, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:66:16: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:108:16: Context: Write to v@2369
   expect(n0, v -= n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:67:14: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:109:14: Context: Write to v@2369
   expect(n1, ++v);
              ^^
-pkg/front_end/testcases/extensions/compounds.dart:68:14: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:110:14: Context: Write to v@2369
   expect(n0, --v);
              ^^
-pkg/front_end/testcases/extensions/compounds.dart:69:15: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:111:15: Context: Write to v@2369
   expect(n0, v++);
               ^^
-pkg/front_end/testcases/extensions/compounds.dart:70:15: Context: Write to v@1309
+pkg/front_end/testcases/extensions/compounds.dart:112:15: Context: Write to v@2369
   expect(n1, v--);
               ^^
+pkg/front_end/testcases/extensions/compounds.dart:116:5: Context: Write to v@2369
+  v += n1;
+    ^^
+pkg/front_end/testcases/extensions/compounds.dart:118:5: Context: Write to v@2369
+  v += n1;
+    ^^
+pkg/front_end/testcases/extensions/compounds.dart:120:5: Context: Write to v@2369
+  v -= n2;
+    ^^
+pkg/front_end/testcases/extensions/compounds.dart:122:5: Context: Write to v@2369
+  v += n1;
+    ^^
+pkg/front_end/testcases/extensions/compounds.dart:124:5: Context: Write to v@2369
+  v -= n1;
+    ^^
+pkg/front_end/testcases/extensions/compounds.dart:126:3: Context: Write to v@2369
+  ++v;
+  ^^
+pkg/front_end/testcases/extensions/compounds.dart:128:3: Context: Write to v@2369
+  --v;
+  ^^
+pkg/front_end/testcases/extensions/compounds.dart:130:4: Context: Write to v@2369
+  v++;
+   ^^
+pkg/front_end/testcases/extensions/compounds.dart:132:4: Context: Write to v@2369
+  v--;
+   ^^
+pkg/front_end/testcases/extensions/compounds.dart:285:14: Context: Write to expected@7409
+    expected = null;
+             ^
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart b/pkg/front_end/testcases/extensions/conflicts.dart
new file mode 100644
index 0000000..b05aa28
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class1 {
+}
+class Class2 {}
+
+extension DuplicateExtensionName on Class1 {
+  uniqueMethod1() {}
+  duplicateMethodName2() => 1;
+}
+
+extension DuplicateExtensionName on Class2 {
+  uniqueMethod2() {}
+  duplicateMethodName2() => 2;
+}
+
+extension UniqueExtensionName on Class1 {
+  duplicateMethodName1() => 1;
+  duplicateMethodName1() => 2;
+}
+
+main() {
+  var c1 = new Class1();
+  c1.uniqueMethod1();
+}
+
+errors() {
+  var c2 = new Class2();
+  c2.uniqueMethod2();
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.outline.expect b/pkg/front_end/testcases/extensions/conflicts.dart.outline.expect
new file mode 100644
index 0000000..268695d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.outline.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:14:11: Error: 'DuplicateExtensionName' is already declared in this scope.
+// extension DuplicateExtensionName on Class2 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:9:11: Context: Previous declaration of 'DuplicateExtensionName'.
+// extension DuplicateExtensionName on Class1 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:21:3: Error: 'duplicateMethodName1' is already declared in this scope.
+//   duplicateMethodName1() => 2;
+//   ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:20:3: Context: Previous declaration of 'duplicateMethodName1'.
+//   duplicateMethodName1() => 1;
+//   ^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1*
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    ;
+}
+extension DuplicateExtensionName on self::Class1* {
+  method uniqueMethod1 = self::DuplicateExtensionName|uniqueMethod1;
+  tearoff uniqueMethod1 = self::DuplicateExtensionName|get#uniqueMethod1;
+  method duplicateMethodName2 = self::DuplicateExtensionName|duplicateMethodName2;
+  tearoff duplicateMethodName2 = self::DuplicateExtensionName|get#duplicateMethodName2;
+}
+extension UniqueExtensionName on self::Class1* {
+  method duplicateMethodName1 = self::UniqueExtensionName|duplicateMethodName1;
+  tearoff duplicateMethodName1 = self::UniqueExtensionName|get#duplicateMethodName1;
+}
+static method DuplicateExtensionName|uniqueMethod1(final self::Class1* #this) → dynamic
+  ;
+static method DuplicateExtensionName|get#uniqueMethod1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|uniqueMethod1(#this);
+static method DuplicateExtensionName|duplicateMethodName2(final self::Class1* #this) → dynamic
+  ;
+static method DuplicateExtensionName|get#duplicateMethodName2(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|duplicateMethodName2(#this);
+static method UniqueExtensionName|duplicateMethodName1(final self::Class1* #this) → dynamic
+  ;
+static method UniqueExtensionName|get#duplicateMethodName1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::UniqueExtensionName|duplicateMethodName1(#this);
+static method main() → dynamic
+  ;
+static method errors() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.strong.expect b/pkg/front_end/testcases/extensions/conflicts.dart.strong.expect
new file mode 100644
index 0000000..5481d64
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.strong.expect
@@ -0,0 +1,70 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:14:11: Error: 'DuplicateExtensionName' is already declared in this scope.
+// extension DuplicateExtensionName on Class2 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:9:11: Context: Previous declaration of 'DuplicateExtensionName'.
+// extension DuplicateExtensionName on Class1 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:21:3: Error: 'duplicateMethodName1' is already declared in this scope.
+//   duplicateMethodName1() => 2;
+//   ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:20:3: Context: Previous declaration of 'duplicateMethodName1'.
+//   duplicateMethodName1() => 1;
+//   ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:31:6: Error: The method 'uniqueMethod2' isn't defined for the class 'Class2'.
+//  - 'Class2' is from 'pkg/front_end/testcases/extensions/conflicts.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'uniqueMethod2'.
+//   c2.uniqueMethod2();
+//      ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1*
+    : super core::Object::•()
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+}
+extension DuplicateExtensionName on self::Class1* {
+  method uniqueMethod1 = self::DuplicateExtensionName|uniqueMethod1;
+  tearoff uniqueMethod1 = self::DuplicateExtensionName|get#uniqueMethod1;
+  method duplicateMethodName2 = self::DuplicateExtensionName|duplicateMethodName2;
+  tearoff duplicateMethodName2 = self::DuplicateExtensionName|get#duplicateMethodName2;
+}
+extension UniqueExtensionName on self::Class1* {
+  method duplicateMethodName1 = self::UniqueExtensionName|duplicateMethodName1;
+  tearoff duplicateMethodName1 = self::UniqueExtensionName|get#duplicateMethodName1;
+}
+static method DuplicateExtensionName|uniqueMethod1(final self::Class1* #this) → dynamic {}
+static method DuplicateExtensionName|get#uniqueMethod1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|uniqueMethod1(#this);
+static method DuplicateExtensionName|duplicateMethodName2(final self::Class1* #this) → dynamic
+  return 1;
+static method DuplicateExtensionName|get#duplicateMethodName2(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|duplicateMethodName2(#this);
+static method UniqueExtensionName|duplicateMethodName1(final self::Class1* #this) → dynamic
+  return 1;
+static method UniqueExtensionName|get#duplicateMethodName1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::UniqueExtensionName|duplicateMethodName1(#this);
+static method main() → dynamic {
+  self::Class1* c1 = new self::Class1::•();
+  self::DuplicateExtensionName|uniqueMethod1(c1);
+}
+static method errors() → dynamic {
+  self::Class2* c2 = new self::Class2::•();
+  invalid-expression "pkg/front_end/testcases/extensions/conflicts.dart:31:6: Error: The method 'uniqueMethod2' isn't defined for the class 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/extensions/conflicts.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'uniqueMethod2'.
+  c2.uniqueMethod2();
+     ^^^^^^^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/conflicts.dart.strong.transformed.expect
new file mode 100644
index 0000000..5481d64
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.strong.transformed.expect
@@ -0,0 +1,70 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:14:11: Error: 'DuplicateExtensionName' is already declared in this scope.
+// extension DuplicateExtensionName on Class2 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:9:11: Context: Previous declaration of 'DuplicateExtensionName'.
+// extension DuplicateExtensionName on Class1 {
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:21:3: Error: 'duplicateMethodName1' is already declared in this scope.
+//   duplicateMethodName1() => 2;
+//   ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/conflicts.dart:20:3: Context: Previous declaration of 'duplicateMethodName1'.
+//   duplicateMethodName1() => 1;
+//   ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/conflicts.dart:31:6: Error: The method 'uniqueMethod2' isn't defined for the class 'Class2'.
+//  - 'Class2' is from 'pkg/front_end/testcases/extensions/conflicts.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'uniqueMethod2'.
+//   c2.uniqueMethod2();
+//      ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1*
+    : super core::Object::•()
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+}
+extension DuplicateExtensionName on self::Class1* {
+  method uniqueMethod1 = self::DuplicateExtensionName|uniqueMethod1;
+  tearoff uniqueMethod1 = self::DuplicateExtensionName|get#uniqueMethod1;
+  method duplicateMethodName2 = self::DuplicateExtensionName|duplicateMethodName2;
+  tearoff duplicateMethodName2 = self::DuplicateExtensionName|get#duplicateMethodName2;
+}
+extension UniqueExtensionName on self::Class1* {
+  method duplicateMethodName1 = self::UniqueExtensionName|duplicateMethodName1;
+  tearoff duplicateMethodName1 = self::UniqueExtensionName|get#duplicateMethodName1;
+}
+static method DuplicateExtensionName|uniqueMethod1(final self::Class1* #this) → dynamic {}
+static method DuplicateExtensionName|get#uniqueMethod1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|uniqueMethod1(#this);
+static method DuplicateExtensionName|duplicateMethodName2(final self::Class1* #this) → dynamic
+  return 1;
+static method DuplicateExtensionName|get#duplicateMethodName2(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::DuplicateExtensionName|duplicateMethodName2(#this);
+static method UniqueExtensionName|duplicateMethodName1(final self::Class1* #this) → dynamic
+  return 1;
+static method UniqueExtensionName|get#duplicateMethodName1(final self::Class1* #this) → () →* dynamic
+  return () → dynamic => self::UniqueExtensionName|duplicateMethodName1(#this);
+static method main() → dynamic {
+  self::Class1* c1 = new self::Class1::•();
+  self::DuplicateExtensionName|uniqueMethod1(c1);
+}
+static method errors() → dynamic {
+  self::Class2* c2 = new self::Class2::•();
+  invalid-expression "pkg/front_end/testcases/extensions/conflicts.dart:31:6: Error: The method 'uniqueMethod2' isn't defined for the class 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/extensions/conflicts.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'uniqueMethod2'.
+  c2.uniqueMethod2();
+     ^^^^^^^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart b/pkg/front_end/testcases/extensions/default_values.dart
new file mode 100644
index 0000000..0b08f6d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.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.
+
+class Class {}
+
+extension Extension on Class {
+  method0([a]) => a;
+  method1([a = 42]) => a;
+  method2({b = 87}) => b;
+  method3({c = staticMethod}) => c();
+  static staticMethod() => 123;
+}
+
+main() {
+  Class c = new Class();
+  var tearOff0 = c.method0;
+  expect(0, tearOff0(0));
+  expect(null, tearOff0());
+  var tearOff1 = c.method1;
+  expect(0, tearOff1(0));
+  expect(42, tearOff1());
+  var tearOff2 = c.method2;
+  expect(0, tearOff2(b: 0));
+  expect(87, tearOff2());
+  var tearOff3 = c.method3;
+  expect(0, tearOff3(c: () => 0));
+  expect(123, tearOff3());
+}
+
+
+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/default_values.dart.outline.expect b/pkg/front_end/testcases/extensions/default_values.dart.outline.expect
new file mode 100644
index 0000000..77ed4f4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.dart.outline.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class* {
+  method method0 = self::Extension|method0;
+  tearoff method0 = self::Extension|get#method0;
+  method method1 = self::Extension|method1;
+  tearoff method1 = self::Extension|get#method1;
+  method method2 = self::Extension|method2;
+  tearoff method2 = self::Extension|get#method2;
+  method method3 = self::Extension|method3;
+  tearoff method3 = self::Extension|get#method3;
+  static method staticMethod = self::Extension|staticMethod;
+}
+static method Extension|method0(final self::Class* #this, [dynamic a]) → dynamic
+  ;
+static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a]) → dynamic => self::Extension|method0(#this, a);
+static method Extension|method1(final self::Class* #this, [dynamic a]) → dynamic
+  ;
+static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a]) → dynamic => self::Extension|method1(#this, a);
+static method Extension|method2(final self::Class* #this, {dynamic b}) → dynamic
+  ;
+static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
+  return ({dynamic b}) → dynamic => self::Extension|method2(#this, b: b);
+static method Extension|method3(final self::Class* #this, {dynamic c}) → dynamic
+  ;
+static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
+  return ({dynamic c}) → dynamic => self::Extension|method3(#this, c: c);
+static method Extension|staticMethod() → dynamic
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.strong.expect b/pkg/front_end/testcases/extensions/default_values.dart.strong.expect
new file mode 100644
index 0000000..e6b8869
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.dart.strong.expect
@@ -0,0 +1,65 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  method method0 = self::Extension|method0;
+  tearoff method0 = self::Extension|get#method0;
+  method method1 = self::Extension|method1;
+  tearoff method1 = self::Extension|get#method1;
+  method method2 = self::Extension|method2;
+  tearoff method2 = self::Extension|get#method2;
+  method method3 = self::Extension|method3;
+  tearoff method3 = self::Extension|get#method3;
+  static method staticMethod = self::Extension|staticMethod;
+}
+static method Extension|method0(final self::Class* #this, [dynamic a = #C1]) → dynamic
+  return a;
+static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a = #C1]) → dynamic => self::Extension|method0(#this, a);
+static method Extension|method1(final self::Class* #this, [dynamic a = #C2]) → dynamic
+  return a;
+static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a = #C2]) → dynamic => self::Extension|method1(#this, a);
+static method Extension|method2(final self::Class* #this, {dynamic b = #C3}) → dynamic
+  return b;
+static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
+  return ({dynamic b = #C3}) → dynamic => self::Extension|method2(#this, b: b);
+static method Extension|method3(final self::Class* #this, {dynamic c = #C4}) → dynamic
+  return c.call();
+static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
+  return ({dynamic c = #C4}) → dynamic => self::Extension|method3(#this, c: c);
+static method Extension|staticMethod() → dynamic
+  return 123;
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  ([dynamic]) →* dynamic tearOff0 = self::Extension|get#method0(c);
+  self::expect(0, tearOff0.call(0));
+  self::expect(null, tearOff0.call());
+  ([dynamic]) →* dynamic tearOff1 = self::Extension|get#method1(c);
+  self::expect(0, tearOff1.call(0));
+  self::expect(42, tearOff1.call());
+  ({b: dynamic}) →* dynamic tearOff2 = self::Extension|get#method2(c);
+  self::expect(0, tearOff2.call(b: 0));
+  self::expect(87, tearOff2.call());
+  ({c: dynamic}) →* dynamic tearOff3 = self::Extension|get#method3(c);
+  self::expect(0, tearOff3.call(c: () → core::int* => 0));
+  self::expect(123, tearOff3.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
+
+constants  {
+  #C1 = null
+  #C2 = 42
+  #C3 = 87
+  #C4 = tearoff self::Extension|staticMethod
+}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..e6b8869
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect
@@ -0,0 +1,65 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  method method0 = self::Extension|method0;
+  tearoff method0 = self::Extension|get#method0;
+  method method1 = self::Extension|method1;
+  tearoff method1 = self::Extension|get#method1;
+  method method2 = self::Extension|method2;
+  tearoff method2 = self::Extension|get#method2;
+  method method3 = self::Extension|method3;
+  tearoff method3 = self::Extension|get#method3;
+  static method staticMethod = self::Extension|staticMethod;
+}
+static method Extension|method0(final self::Class* #this, [dynamic a = #C1]) → dynamic
+  return a;
+static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a = #C1]) → dynamic => self::Extension|method0(#this, a);
+static method Extension|method1(final self::Class* #this, [dynamic a = #C2]) → dynamic
+  return a;
+static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
+  return ([dynamic a = #C2]) → dynamic => self::Extension|method1(#this, a);
+static method Extension|method2(final self::Class* #this, {dynamic b = #C3}) → dynamic
+  return b;
+static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
+  return ({dynamic b = #C3}) → dynamic => self::Extension|method2(#this, b: b);
+static method Extension|method3(final self::Class* #this, {dynamic c = #C4}) → dynamic
+  return c.call();
+static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
+  return ({dynamic c = #C4}) → dynamic => self::Extension|method3(#this, c: c);
+static method Extension|staticMethod() → dynamic
+  return 123;
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  ([dynamic]) →* dynamic tearOff0 = self::Extension|get#method0(c);
+  self::expect(0, tearOff0.call(0));
+  self::expect(null, tearOff0.call());
+  ([dynamic]) →* dynamic tearOff1 = self::Extension|get#method1(c);
+  self::expect(0, tearOff1.call(0));
+  self::expect(42, tearOff1.call());
+  ({b: dynamic}) →* dynamic tearOff2 = self::Extension|get#method2(c);
+  self::expect(0, tearOff2.call(b: 0));
+  self::expect(87, tearOff2.call());
+  ({c: dynamic}) →* dynamic tearOff3 = self::Extension|get#method3(c);
+  self::expect(0, tearOff3.call(c: () → core::int* => 0));
+  self::expect(123, tearOff3.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
+
+constants  {
+  #C1 = null
+  #C2 = 42
+  #C3 = 87
+  #C4 = tearoff self::Extension|staticMethod
+}
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart b/pkg/front_end/testcases/extensions/direct_instance_access.dart
index 32094b5..9ccfeda 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart
@@ -120,10 +120,7 @@
     writeSetterOptional(value);
     writeSetterNamed();
     writeSetterNamed(value: value);
-    // TODO(johnniwinther): Handle direct calls to generic methods. This
-    // requires inference to special-case the extension type parameters and
-    // perform a two-step type argument inference.
-    /*genericWriteSetterRequired(value);
+    genericWriteSetterRequired(value);
     genericWriteSetterRequired<T>(value);
     genericWriteSetterRequired<S>(value);
     genericWriteSetterOptional();
@@ -137,7 +134,7 @@
     genericWriteSetterNamed<S>();
     genericWriteSetterNamed(value: value);
     genericWriteSetterNamed<T>(value: value);
-    genericWriteSetterNamed<S>(value: value);*/
+    genericWriteSetterNamed<S>(value: value);
   }
 
   tearOffs<S extends T>(S value) {
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect
index 86ff6e6..f38f7f8c 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect
@@ -76,11 +76,11 @@
 static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value]) → dynamic
   ;
 static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
-  return ([dynamic value = null]) → dynamic => self::Extension|writeSetterOptional(#this, value);
+  return ([dynamic value]) → dynamic => self::Extension|writeSetterOptional(#this, value);
 static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value}) → dynamic
   ;
 static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
-  return ({dynamic value = null}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
+  return ({dynamic value}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
 static method Extension|get#tearOffGetterNoArgs(final self::Class* #this) → dynamic
   ;
 static method Extension|get#tearOffGetterRequired(final self::Class* #this) → dynamic
@@ -116,11 +116,11 @@
 static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value]) → dynamic
   ;
 static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
-  return ([self::GenericExtension|get#writeSetterOptional::T* value = null]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
+  return ([self::GenericExtension|get#writeSetterOptional::T* value]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
 static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value}) → dynamic
   ;
 static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
-  return ({self::GenericExtension|get#writeSetterNamed::T* value = null}) → dynamic => self::GenericExtension|writeSetterNamed<self::GenericExtension|get#writeSetterNamed::T*>(#this, value: value);
+  return ({self::GenericExtension|get#writeSetterNamed::T* value}) → dynamic => self::GenericExtension|writeSetterNamed<self::GenericExtension|get#writeSetterNamed::T*>(#this, value: value);
 static method GenericExtension|genericWriteSetterRequired<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterRequired::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterRequired::T*>* #this, self::GenericExtension|genericWriteSetterRequired::S* value) → dynamic
   ;
 static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
@@ -128,9 +128,9 @@
 static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value]) → dynamic
   ;
 static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
-  return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = null]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
+  return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
 static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
-  return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = null}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
+  return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
 static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value}) → dynamic
   ;
 static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect
index a652a17..ee8966f 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect
@@ -77,12 +77,12 @@
 }
 static method Extension|get#writeSetterRequired(final self::Class* #this) → (dynamic) →* dynamic
   return (dynamic value) → dynamic => self::Extension|writeSetterRequired(#this, value);
-static method Extension|writeSetterOptional(final self::Class* #this = #C1, [dynamic value = #C1]) → dynamic {
+static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value = #C1]) → dynamic {
   self::Extension|set#property(#this, value);
 }
 static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
   return ([dynamic value = #C1]) → dynamic => self::Extension|writeSetterOptional(#this, value);
-static method Extension|writeSetterNamed(final self::Class* #this = #C1, {dynamic value = #C1}) → dynamic {
+static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value = #C1}) → dynamic {
   self::Extension|set#property(#this, value);
 }
 static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
@@ -97,10 +97,8 @@
   return self::Extension|get#writeSetterNamed(#this);
 static method Extension|get#property(final self::Class* #this) → dynamic
   return #this.{self::Class::field};
-static method Extension|set#property(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
+static method Extension|set#property(final self::Class* #this, dynamic value) → void {
   #this.{self::Class::field} = value;
-  return #t1;
 }
 static method Extension|invocations(final self::Class* #this, dynamic value) → dynamic {
   self::Extension|readGetter(#this);
@@ -146,12 +144,12 @@
 }
 static method GenericExtension|get#writeSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterRequired::T*>* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic
   return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired<self::GenericExtension|get#writeSetterRequired::T*>(#this, value);
-static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
+static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|writeSetterOptional::T*>(#this, value);
 }
 static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
   return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
-static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
+static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|writeSetterNamed::T*>(#this, value);
 }
 static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
@@ -161,22 +159,20 @@
 }
 static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|get#genericWriteSetterRequired::T*, S*>(#this, value);
-static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
+static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterOptional::T*>(#this, value);
 }
 static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
 static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
-static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
+static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterNamed::T*>(#this, value);
 }
 static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
   return #this.{self::GenericClass::field};
-static method GenericExtension|set#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::T*>* #this, self::GenericExtension|set#property::T* value) → self::GenericExtension|set#property::T* {
-  final self::GenericExtension|set#property::T* #t2 = value;
+static method GenericExtension|set#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::T*>* #this, self::GenericExtension|set#property::T* value) → void {
   #this.{self::GenericClass::field} = value;
-  return #t2;
 }
 static method GenericExtension|get#tearOffGetterNoArgs<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#tearOffGetterNoArgs::T*>* #this) → dynamic
   return self::GenericExtension|get#readGetter<self::GenericExtension|get#tearOffGetterNoArgs::T*>(#this);
@@ -199,6 +195,21 @@
   self::GenericExtension|writeSetterOptional<self::GenericExtension|invocations::T*>(#this, value);
   self::GenericExtension|writeSetterNamed<self::GenericExtension|invocations::T*>(#this);
   self::GenericExtension|writeSetterNamed<self::GenericExtension|invocations::T*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value: value);
 }
 static method GenericExtension|get#invocations<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#invocations::T*>* #this) → <S extends self::GenericExtension|get#invocations::T* = dynamic>(S*) →* dynamic
   return <S extends self::GenericExtension|get#invocations::T* = dynamic>(S* value) → dynamic => self::GenericExtension|invocations<self::GenericExtension|get#invocations::T*, S*>(#this, value);
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect
index a652a17..ee8966f 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect
@@ -77,12 +77,12 @@
 }
 static method Extension|get#writeSetterRequired(final self::Class* #this) → (dynamic) →* dynamic
   return (dynamic value) → dynamic => self::Extension|writeSetterRequired(#this, value);
-static method Extension|writeSetterOptional(final self::Class* #this = #C1, [dynamic value = #C1]) → dynamic {
+static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value = #C1]) → dynamic {
   self::Extension|set#property(#this, value);
 }
 static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
   return ([dynamic value = #C1]) → dynamic => self::Extension|writeSetterOptional(#this, value);
-static method Extension|writeSetterNamed(final self::Class* #this = #C1, {dynamic value = #C1}) → dynamic {
+static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value = #C1}) → dynamic {
   self::Extension|set#property(#this, value);
 }
 static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
@@ -97,10 +97,8 @@
   return self::Extension|get#writeSetterNamed(#this);
 static method Extension|get#property(final self::Class* #this) → dynamic
   return #this.{self::Class::field};
-static method Extension|set#property(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
+static method Extension|set#property(final self::Class* #this, dynamic value) → void {
   #this.{self::Class::field} = value;
-  return #t1;
 }
 static method Extension|invocations(final self::Class* #this, dynamic value) → dynamic {
   self::Extension|readGetter(#this);
@@ -146,12 +144,12 @@
 }
 static method GenericExtension|get#writeSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterRequired::T*>* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic
   return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired<self::GenericExtension|get#writeSetterRequired::T*>(#this, value);
-static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
+static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|writeSetterOptional::T*>(#this, value);
 }
 static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
   return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
-static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
+static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|writeSetterNamed::T*>(#this, value);
 }
 static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
@@ -161,22 +159,20 @@
 }
 static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|get#genericWriteSetterRequired::T*, S*>(#this, value);
-static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
+static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterOptional::T*>(#this, value);
 }
 static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
 static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
   return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
-static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
+static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
   self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterNamed::T*>(#this, value);
 }
 static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
   return #this.{self::GenericClass::field};
-static method GenericExtension|set#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::T*>* #this, self::GenericExtension|set#property::T* value) → self::GenericExtension|set#property::T* {
-  final self::GenericExtension|set#property::T* #t2 = value;
+static method GenericExtension|set#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::T*>* #this, self::GenericExtension|set#property::T* value) → void {
   #this.{self::GenericClass::field} = value;
-  return #t2;
 }
 static method GenericExtension|get#tearOffGetterNoArgs<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#tearOffGetterNoArgs::T*>* #this) → dynamic
   return self::GenericExtension|get#readGetter<self::GenericExtension|get#tearOffGetterNoArgs::T*>(#this);
@@ -199,6 +195,21 @@
   self::GenericExtension|writeSetterOptional<self::GenericExtension|invocations::T*>(#this, value);
   self::GenericExtension|writeSetterNamed<self::GenericExtension|invocations::T*>(#this);
   self::GenericExtension|writeSetterNamed<self::GenericExtension|invocations::T*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value);
+  self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value);
+  self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::T*>(#this, value: value);
+  self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|invocations::T*, self::GenericExtension|invocations::S*>(#this, value: value);
 }
 static method GenericExtension|get#invocations<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#invocations::T*>* #this) → <S extends self::GenericExtension|get#invocations::T* = dynamic>(S*) →* dynamic
   return <S extends self::GenericExtension|get#invocations::T* = dynamic>(S* value) → dynamic => self::GenericExtension|invocations<self::GenericExtension|get#invocations::T*, S*>(#this, value);
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart b/pkg/front_end/testcases/extensions/dynamic_invoke.dart
new file mode 100644
index 0000000..bd327b7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  noSuchMethod(Invocation i) => 123;
+}
+
+extension ClassExtension on Class {
+  int method() => 42;
+}
+
+extension Extension on dynamic {
+  int method() => 87;
+}
+
+main() {
+  dynamic c0 = new Class();
+  Object c1 = new Class();
+  Class c2 = new Class();
+
+  expect(123, c0.method());
+  expect(87, c1.method());
+  expect(42, c2.method());
+}
+
+expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Mismatch: expected=$expected, actual=$actual';
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.outline.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.outline.expect
new file mode 100644
index 0000000..c8a99ef
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    ;
+}
+extension ClassExtension on self::Class* {
+  method method = self::ClassExtension|method;
+  tearoff method = self::ClassExtension|get#method;
+}
+extension Extension on dynamic {
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+}
+static method ClassExtension|method(final self::Class* #this) → core::int*
+  ;
+static method ClassExtension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::ClassExtension|method(#this);
+static method Extension|method(final dynamic #this) → core::int*
+  ;
+static method Extension|get#method(final dynamic #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/dynamic_invoke.dart.strong.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.strong.expect
new file mode 100644
index 0000000..95ddf7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.strong.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    return 123;
+}
+extension ClassExtension on self::Class* {
+  method method = self::ClassExtension|method;
+  tearoff method = self::ClassExtension|get#method;
+}
+extension Extension on dynamic {
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+}
+static method ClassExtension|method(final self::Class* #this) → core::int*
+  return 42;
+static method ClassExtension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::ClassExtension|method(#this);
+static method Extension|method(final dynamic #this) → core::int*
+  return 87;
+static method Extension|get#method(final dynamic #this) → () →* core::int*
+  return () → core::int* => self::Extension|method(#this);
+static method main() → dynamic {
+  dynamic c0 = new self::Class::•();
+  core::Object* c1 = new self::Class::•();
+  self::Class* c2 = new self::Class::•();
+  self::expect(123, c0.method());
+  self::expect(87, self::Extension|method(c1));
+  self::expect(42, self::ClassExtension|method(c2));
+}
+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/dynamic_invoke.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.strong.transformed.expect
new file mode 100644
index 0000000..95ddf7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    return 123;
+}
+extension ClassExtension on self::Class* {
+  method method = self::ClassExtension|method;
+  tearoff method = self::ClassExtension|get#method;
+}
+extension Extension on dynamic {
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+}
+static method ClassExtension|method(final self::Class* #this) → core::int*
+  return 42;
+static method ClassExtension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::ClassExtension|method(#this);
+static method Extension|method(final dynamic #this) → core::int*
+  return 87;
+static method Extension|get#method(final dynamic #this) → () →* core::int*
+  return () → core::int* => self::Extension|method(#this);
+static method main() → dynamic {
+  dynamic c0 = new self::Class::•();
+  core::Object* c1 = new self::Class::•();
+  self::Class* c2 = new self::Class::•();
+  self::expect(123, c0.method());
+  self::expect(87, self::Extension|method(c1));
+  self::expect(42, self::ClassExtension|method(c2));
+}
+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/explicit_extension_access.dart.strong.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
index 70f01be..4f30c9d 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
@@ -27,10 +27,8 @@
 }
 static method Extension1|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field1};
-static method Extension1|set#field(final self::Class* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method Extension1|set#field(final self::Class* #this, core::int* value) → void {
   #this.{self::Class::field1} = value;
-  return #t1;
 }
 static method Extension1|method(final self::Class* #this) → core::int*
   return #this.{self::Class::field1};
@@ -42,10 +40,8 @@
   return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
-static method Extension2|set#field(final self::Class* #this, core::int* value) → core::int* {
-  final core::int* #t2 = value;
+static method Extension2|set#field(final self::Class* #this, core::int* value) → void {
   #this.{self::Class::field2} = value;
-  return #t2;
 }
 static method Extension2|method(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
@@ -75,8 +71,8 @@
   self::expect(97, genericTearOff2.call<core::int*>(10));
   self::expect(52, genericTearOff1.call<core::num*>(10));
   self::expect(97, genericTearOff2.call<core::num*>(10));
-  self::expect(23, self::Extension1|set#field(c, 23));
-  self::expect(67, self::Extension2|set#field(c, 67));
+  self::expect(23, let final self::Class* #t1 = c in let final core::int* #t2 = 23 in let final void #t3 = self::Extension1|set#field(#t1, #t2) in #t2);
+  self::expect(67, let final self::Class* #t4 = c in let final core::int* #t5 = 67 in let final void #t6 = self::Extension2|set#field(#t4, #t5) in #t5);
   self::expect(23, self::Extension1|get#field(c));
   self::expect(67, self::Extension2|get#field(c));
 }
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
index 70f01be..4f30c9d 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
@@ -27,10 +27,8 @@
 }
 static method Extension1|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field1};
-static method Extension1|set#field(final self::Class* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method Extension1|set#field(final self::Class* #this, core::int* value) → void {
   #this.{self::Class::field1} = value;
-  return #t1;
 }
 static method Extension1|method(final self::Class* #this) → core::int*
   return #this.{self::Class::field1};
@@ -42,10 +40,8 @@
   return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
-static method Extension2|set#field(final self::Class* #this, core::int* value) → core::int* {
-  final core::int* #t2 = value;
+static method Extension2|set#field(final self::Class* #this, core::int* value) → void {
   #this.{self::Class::field2} = value;
-  return #t2;
 }
 static method Extension2|method(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
@@ -75,8 +71,8 @@
   self::expect(97, genericTearOff2.call<core::int*>(10));
   self::expect(52, genericTearOff1.call<core::num*>(10));
   self::expect(97, genericTearOff2.call<core::num*>(10));
-  self::expect(23, self::Extension1|set#field(c, 23));
-  self::expect(67, self::Extension2|set#field(c, 67));
+  self::expect(23, let final self::Class* #t1 = c in let final core::int* #t2 = 23 in let final void #t3 = self::Extension1|set#field(#t1, #t2) in #t2);
+  self::expect(67, let final self::Class* #t4 = c in let final core::int* #t5 = 67 in let final void #t6 = self::Extension2|set#field(#t4, #t5) in #t5);
   self::expect(23, self::Extension1|get#field(c));
   self::expect(67, self::Extension2|get#field(c));
 }
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
index e203cfb..accfea8 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
@@ -31,11 +31,9 @@
   self::Extension1|latestType = "${self::Extension1|get#field::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → self::Extension1|set#field::T* {
-  final self::Extension1|set#field::T* #t1 = value;
+static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
   self::Extension1|latestType = "${self::Extension1|set#field::T*}";
   #this.{self::Class::field1} = value;
-  return #t1;
 }
 static method Extension1|method<T extends core::num* = dynamic>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
   self::Extension1|latestType = "${self::Extension1|method::T*}";
@@ -51,10 +49,8 @@
   return <S extends core::num* = dynamic>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
 static method Extension2|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
   return #this.{self::Class::field2};
-static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → self::Extension2|set#field::T* {
-  final self::Extension2|set#field::T* #t2 = value;
+static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
   #this.{self::Class::field2} = value;
-  return #t2;
 }
 static method Extension2|method<T extends core::num* = dynamic>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
   return #this.{self::Class::field2};
@@ -113,11 +109,11 @@
   self::expect(52, genericTearOffInteger1.call<core::num*>(10));
   self::expect("int:num", self::Extension1|latestType);
   self::expect(97, genericTearOff2.call<core::num*>(10));
-  self::expect(23, self::Extension1|set#field<core::num*>(c, 23));
+  self::expect(23, let final self::Class<core::int*>* #t1 = c in let final core::int* #t2 = 23 in let final void #t3 = self::Extension1|set#field<core::num*>(#t1, #t2) in #t2);
   self::expect("num", self::Extension1|latestType);
-  self::expect(23, self::Extension1|set#field<core::int*>(c, 23));
+  self::expect(23, let final self::Class<core::int*>* #t4 = c in let final core::int* #t5 = 23 in let final void #t6 = self::Extension1|set#field<core::int*>(#t4, #t5) in #t5);
   self::expect("int", self::Extension1|latestType);
-  self::expect(67, self::Extension2|set#field<core::num*>(c, 67));
+  self::expect(67, let final self::Class<core::int*>* #t7 = c in let final core::int* #t8 = 67 in let final void #t9 = self::Extension2|set#field<core::num*>(#t7, #t8) in #t8);
   self::expect(23, self::Extension1|get#field<core::num*>(c));
   self::expect(67, self::Extension2|get#field<core::num*>(c));
 }
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
index e203cfb..accfea8 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
@@ -31,11 +31,9 @@
   self::Extension1|latestType = "${self::Extension1|get#field::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → self::Extension1|set#field::T* {
-  final self::Extension1|set#field::T* #t1 = value;
+static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
   self::Extension1|latestType = "${self::Extension1|set#field::T*}";
   #this.{self::Class::field1} = value;
-  return #t1;
 }
 static method Extension1|method<T extends core::num* = dynamic>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
   self::Extension1|latestType = "${self::Extension1|method::T*}";
@@ -51,10 +49,8 @@
   return <S extends core::num* = dynamic>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
 static method Extension2|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
   return #this.{self::Class::field2};
-static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → self::Extension2|set#field::T* {
-  final self::Extension2|set#field::T* #t2 = value;
+static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
   #this.{self::Class::field2} = value;
-  return #t2;
 }
 static method Extension2|method<T extends core::num* = dynamic>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
   return #this.{self::Class::field2};
@@ -113,11 +109,11 @@
   self::expect(52, genericTearOffInteger1.call<core::num*>(10));
   self::expect("int:num", self::Extension1|latestType);
   self::expect(97, genericTearOff2.call<core::num*>(10));
-  self::expect(23, self::Extension1|set#field<core::num*>(c, 23));
+  self::expect(23, let final self::Class<core::int*>* #t1 = c in let final core::int* #t2 = 23 in let final void #t3 = self::Extension1|set#field<core::num*>(#t1, #t2) in #t2);
   self::expect("num", self::Extension1|latestType);
-  self::expect(23, self::Extension1|set#field<core::int*>(c, 23));
+  self::expect(23, let final self::Class<core::int*>* #t4 = c in let final core::int* #t5 = 23 in let final void #t6 = self::Extension1|set#field<core::int*>(#t4, #t5) in #t5);
   self::expect("int", self::Extension1|latestType);
-  self::expect(67, self::Extension2|set#field<core::num*>(c, 67));
+  self::expect(67, let final self::Class<core::int*>* #t7 = c in let final core::int* #t8 = 67 in let final void #t9 = self::Extension2|set#field<core::num*>(#t7, #t8) in #t8);
   self::expect(23, self::Extension1|get#field<core::num*>(c));
   self::expect(67, self::Extension2|get#field<core::num*>(c));
 }
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart
new file mode 100644
index 0000000..fc8cd69
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.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.
+
+class Class {}
+
+extension Extension on Class {}
+
+errors(Class c) {
+  Extension(c);
+  Extension(c) = 42;
+  Extension(c) += 42;
+  Extension(c)++;
+  ++Extension(c);
+}
+
+main() {
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.outline.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.outline.expect
new file mode 100644
index 0000000..d4546e9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class* {
+}
+static method errors(self::Class* c) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.expect
new file mode 100644
index 0000000..a751f73
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c);
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
+//   Extension(c) = 42;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c) += 42;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c)++;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
+//   ++Extension(c);
+//     ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+}
+static method errors(self::Class* c) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c);
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
+  Extension(c) = 42;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c) += 42;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c)++;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
+  ++Extension(c);
+    ^^^^^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.transformed.expect
new file mode 100644
index 0000000..a751f73
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.strong.transformed.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c);
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
+//   Extension(c) = 42;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c) += 42;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
+//   Extension(c)++;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
+//   ++Extension(c);
+//     ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+}
+static method errors(self::Class* c) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c);
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
+  Extension(c) = 42;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c) += 42;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
+  Extension(c)++;
+  ^^^^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
+  ++Extension(c);
+    ^^^^^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart b/pkg/front_end/testcases/extensions/extension_setter.dart
new file mode 100644
index 0000000..de0ed9e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart
@@ -0,0 +1,201 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  int field;
+}
+
+extension Extension on Class {
+  int get simpleSetter => field;
+
+  set simpleSetter(int value) {
+    field = value;
+  }
+
+  int get mutatingSetter => field;
+
+  set mutatingSetter(int value) {
+    value = value + 1;
+    field = value;
+  }
+
+  int get setterWithReturn => field;
+
+  set setterWithReturn(int value) {
+    if (value < 0) {
+      field = -value;
+      return;
+    }
+    field = value;
+  }
+
+  int get setterWithClosure => field;
+
+  set setterWithClosure(int value) {
+    abs(value) {
+      return value < 0 ? -value : value;
+    }
+    field = abs(value);
+  }
+  
+  testInternal() {
+    expect(null, field);
+
+    simpleSetter = 0;
+    expect(0, field);
+    expect(1, simpleSetter = 1);
+
+    mutatingSetter = 0;
+    expect(1, field);
+    expect(2, mutatingSetter = 2);
+    expect(3, field);
+
+    setterWithReturn = 1;
+    expect(1, field);
+    setterWithReturn = -2;
+    expect(2, field);
+    expect(3, setterWithReturn = 3);
+    expect(3, field);
+    expect(-4, setterWithReturn = -4);
+    expect(4, field);
+
+    setterWithClosure = 1;
+    expect(1, field);
+    setterWithClosure = -2;
+    expect(2, field);
+    expect(3, setterWithClosure = 3);
+    expect(3, field);
+    expect(-4, setterWithClosure = -4);
+    expect(4, field);
+  }
+}
+
+main() {
+  var c = new Class();
+  expect(null, c.field);
+
+  c.simpleSetter = 0;
+  expect(0, c.field);
+  expect(1, c.simpleSetter = 1);
+  Extension(c).simpleSetter = 2;
+  expect(2, c.field);
+  expect(3, Extension(c).simpleSetter = 3);
+
+  c.mutatingSetter = 0;
+  expect(1, c.field);
+  expect(2, c.mutatingSetter = 2);
+  expect(3, c.field);
+  Extension(c).mutatingSetter = 4;
+  expect(5, c.field);
+  expect(6, Extension(c).mutatingSetter = 6);
+  expect(7, c.field);
+
+  c.setterWithReturn = 1;
+  expect(1, c.field);
+  c.setterWithReturn = -2;
+  expect(2, c.field);
+  expect(3, c.setterWithReturn = 3);
+  expect(3, c.field);
+  expect(-4, c.setterWithReturn = -4);
+  expect(4, c.field);
+  Extension(c).setterWithReturn = 5;
+  expect(5, c.field);
+  Extension(c).setterWithReturn = -6;
+  expect(6, c.field);
+  expect(7, Extension(c).setterWithReturn = 7);
+  expect(7, c.field);
+  expect(-8, Extension(c).setterWithReturn = -8);
+  expect(8, c.field);
+
+  c.setterWithClosure = 1;
+  expect(1, c.field);
+  c.setterWithClosure = -2;
+  expect(2, c.field);
+  expect(3, c.setterWithClosure = 3);
+  expect(3, c.field);
+  expect(-4, c.setterWithClosure = -4);
+  expect(4, c.field);
+  Extension(c).setterWithClosure = 5;
+  expect(5, c.field);
+  Extension(c).setterWithClosure = -6;
+  expect(6, c.field);
+  expect(7, Extension(c).setterWithClosure = 7);
+  expect(7, c.field);
+  expect(-8, Extension(c).setterWithClosure = -8);
+  expect(8, c.field);
+
+  c.simpleSetter = 0;
+  expect(0, c?.field);
+  expect(1, c?.simpleSetter = 1);
+  Extension(c).simpleSetter = 2;
+  expect(2, c?.field);
+  expect(3, Extension(c).simpleSetter = 3);
+
+  c.mutatingSetter = 0;
+  expect(1, c?.field);
+  expect(2, c?.mutatingSetter = 2);
+  expect(3, c?.field);
+  Extension(c).mutatingSetter = 4;
+  expect(5, c?.field);
+  expect(6, Extension(c).mutatingSetter = 6);
+  expect(7, c?.field);
+
+  c?.setterWithReturn = 1;
+  expect(1, c?.field);
+  c?.setterWithReturn = -2;
+  expect(2, c?.field);
+  expect(3, c?.setterWithReturn = 3);
+  expect(3, c?.field);
+  expect(-4, c?.setterWithReturn = -4);
+  expect(4, c?.field);
+  Extension(c).setterWithReturn = 5;
+  expect(5, c?.field);
+  Extension(c).setterWithReturn = -6;
+  expect(6, c?.field);
+  expect(7, Extension(c).setterWithReturn = 7);
+  expect(7, c?.field);
+  expect(-8, Extension(c).setterWithReturn = -8);
+  expect(8, c?.field);
+
+  c?.setterWithClosure = 1;
+  expect(1, c?.field);
+  c?.setterWithClosure = -2;
+  expect(2, c?.field);
+  expect(3, c?.setterWithClosure = 3);
+  expect(3, c?.field);
+  expect(-4, c?.setterWithClosure = -4);
+  expect(4, c?.field);
+  Extension(c).setterWithClosure = 5;
+  expect(5, c?.field);
+  Extension(c).setterWithClosure = -6;
+  expect(6, c?.field);
+  expect(7, Extension(c).setterWithClosure = 7);
+  expect(7, c?.field);
+  expect(-8, Extension(c).setterWithClosure = -8);
+  expect(8, c?.field);
+
+  c.field = null;
+  c.simpleSetter ??= 1;
+  expect(1, c.field);
+  expect(1, c.simpleSetter ??= 2);
+  c.field = null;
+  expect(2, c.simpleSetter ??= 2);
+
+  c?.field = null;
+  c?.simpleSetter ??= 1;
+  expect(1, c?.field);
+  expect(1, c?.simpleSetter ??= 2);
+  c?.field = null;
+  expect(2, c?.simpleSetter ??= 2);
+
+  new Class().testInternal();
+
+}
+
+
+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/extension_setter.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect
new file mode 100644
index 0000000..15b272e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect
@@ -0,0 +1,45 @@
+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 simpleSetter = self::Extension|get#simpleSetter;
+  get mutatingSetter = self::Extension|get#mutatingSetter;
+  get setterWithReturn = self::Extension|get#setterWithReturn;
+  get setterWithClosure = self::Extension|get#setterWithClosure;
+  method testInternal = self::Extension|testInternal;
+  tearoff testInternal = self::Extension|get#testInternal;
+  set simpleSetter = self::Extension|set#simpleSetter;
+  set mutatingSetter = self::Extension|set#mutatingSetter;
+  set setterWithReturn = self::Extension|set#setterWithReturn;
+  set setterWithClosure = self::Extension|set#setterWithClosure;
+}
+static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
+  ;
+static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void
+  ;
+static method Extension|get#mutatingSetter(final self::Class* #this) → core::int*
+  ;
+static method Extension|set#mutatingSetter(final self::Class* #this, core::int* value) → void
+  ;
+static method Extension|get#setterWithReturn(final self::Class* #this) → core::int*
+  ;
+static method Extension|set#setterWithReturn(final self::Class* #this, core::int* value) → void
+  ;
+static method Extension|get#setterWithClosure(final self::Class* #this) → core::int*
+  ;
+static method Extension|set#setterWithClosure(final self::Class* #this, core::int* value) → void
+  ;
+static method Extension|testInternal(final self::Class* #this) → dynamic
+  ;
+static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testInternal(#this);
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
new file mode 100644
index 0000000..f487199
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
@@ -0,0 +1,192 @@
+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 simpleSetter = self::Extension|get#simpleSetter;
+  get mutatingSetter = self::Extension|get#mutatingSetter;
+  get setterWithReturn = self::Extension|get#setterWithReturn;
+  get setterWithClosure = self::Extension|get#setterWithClosure;
+  method testInternal = self::Extension|testInternal;
+  tearoff testInternal = self::Extension|get#testInternal;
+  set simpleSetter = self::Extension|set#simpleSetter;
+  set mutatingSetter = self::Extension|set#mutatingSetter;
+  set setterWithReturn = self::Extension|set#setterWithReturn;
+  set setterWithClosure = self::Extension|set#setterWithClosure;
+}
+static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void {
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#mutatingSetter(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#mutatingSetter(final self::Class* #this, core::int* value) → void {
+  value = value.{core::num::+}(1);
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#setterWithReturn(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#setterWithReturn(final self::Class* #this, core::int* value) → void {
+  if(value.{core::num::<}(0)) {
+    #this.{self::Class::field} = value.{core::int::unary-}();
+    return;
+  }
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#setterWithClosure(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#setterWithClosure(final self::Class* #this, core::int* value) → void {
+  function abs(dynamic value) → dynamic {
+    return value.<(0) as{TypeError} core::bool* ?{dynamic} value.unary-() : value;
+  }
+  #this.{self::Class::field} = abs.call(value) as{TypeError} core::int*;
+}
+static method Extension|testInternal(final self::Class* #this) → dynamic {
+  self::expect(null, #this.{self::Class::field});
+  self::Extension|set#simpleSetter(#this, 0);
+  self::expect(0, #this.{self::Class::field});
+  self::expect(1, let final core::int* #t1 = 1 in let final void #t2 = self::Extension|set#simpleSetter(#this, #t1) in #t1);
+  self::Extension|set#mutatingSetter(#this, 0);
+  self::expect(1, #this.{self::Class::field});
+  self::expect(2, let final core::int* #t3 = 2 in let final void #t4 = self::Extension|set#mutatingSetter(#this, #t3) in #t3);
+  self::expect(3, #this.{self::Class::field});
+  self::Extension|set#setterWithReturn(#this, 1);
+  self::expect(1, #this.{self::Class::field});
+  self::Extension|set#setterWithReturn(#this, 2.{core::int::unary-}());
+  self::expect(2, #this.{self::Class::field});
+  self::expect(3, let final core::int* #t5 = 3 in let final void #t6 = self::Extension|set#setterWithReturn(#this, #t5) in #t5);
+  self::expect(3, #this.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final core::int* #t7 = 4.{core::int::unary-}() in let final void #t8 = self::Extension|set#setterWithReturn(#this, #t7) in #t7);
+  self::expect(4, #this.{self::Class::field});
+  self::Extension|set#setterWithClosure(#this, 1);
+  self::expect(1, #this.{self::Class::field});
+  self::Extension|set#setterWithClosure(#this, 2.{core::int::unary-}());
+  self::expect(2, #this.{self::Class::field});
+  self::expect(3, let final core::int* #t9 = 3 in let final void #t10 = self::Extension|set#setterWithClosure(#this, #t9) in #t9);
+  self::expect(3, #this.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final core::int* #t11 = 4.{core::int::unary-}() in let final void #t12 = self::Extension|set#setterWithClosure(#this, #t11) in #t11);
+  self::expect(4, #this.{self::Class::field});
+}
+static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testInternal(#this);
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(null, c.{self::Class::field});
+  self::Extension|set#simpleSetter(c, 0);
+  self::expect(0, c.{self::Class::field});
+  self::expect(1, let final self::Class* #t13 = c in let final core::int* #t14 = 1 in let final void #t15 = self::Extension|set#simpleSetter(#t13, #t14) in #t14);
+  self::Extension|set#simpleSetter(c, 2);
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t16 = c in let final core::int* #t17 = 3 in let final void #t18 = self::Extension|set#simpleSetter(#t16, #t17) in #t17);
+  self::Extension|set#mutatingSetter(c, 0);
+  self::expect(1, c.{self::Class::field});
+  self::expect(2, let final self::Class* #t19 = c in let final core::int* #t20 = 2 in let final void #t21 = self::Extension|set#mutatingSetter(#t19, #t20) in #t20);
+  self::expect(3, c.{self::Class::field});
+  self::Extension|set#mutatingSetter(c, 4);
+  self::expect(5, c.{self::Class::field});
+  self::expect(6, let final self::Class* #t22 = c in let final core::int* #t23 = 6 in let final void #t24 = self::Extension|set#mutatingSetter(#t22, #t23) in #t23);
+  self::expect(7, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 1);
+  self::expect(1, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 2.{core::int::unary-}());
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t25 = c in let final core::int* #t26 = 3 in let final void #t27 = self::Extension|set#setterWithReturn(#t25, #t26) in #t26);
+  self::expect(3, c.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = 4.{core::int::unary-}() in let final void #t30 = self::Extension|set#setterWithReturn(#t28, #t29) in #t29);
+  self::expect(4, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 5);
+  self::expect(5, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
+  self::expect(6, c.{self::Class::field});
+  self::expect(7, let final self::Class* #t31 = c in let final core::int* #t32 = 7 in let final void #t33 = self::Extension|set#setterWithReturn(#t31, #t32) in #t32);
+  self::expect(7, c.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t34 = c in let final core::int* #t35 = 8.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithReturn(#t34, #t35) in #t35);
+  self::expect(8, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 1);
+  self::expect(1, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 2.{core::int::unary-}());
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t37 = c in let final core::int* #t38 = 3 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
+  self::expect(3, c.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 4.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
+  self::expect(4, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 5);
+  self::expect(5, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
+  self::expect(6, c.{self::Class::field});
+  self::expect(7, let final self::Class* #t43 = c in let final core::int* #t44 = 7 in let final void #t45 = self::Extension|set#setterWithClosure(#t43, #t44) in #t44);
+  self::expect(7, c.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t46 = c in let final core::int* #t47 = 8.{core::int::unary-}() in let final void #t48 = self::Extension|set#setterWithClosure(#t46, #t47) in #t47);
+  self::expect(8, c.{self::Class::field});
+  self::Extension|set#simpleSetter(c, 0);
+  self::expect(0, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : #t49.{self::Class::field});
+  self::expect(1, let final self::Class* #t50 = c in #t50.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t51 = 1 in let final void #t52 = self::Extension|set#simpleSetter(#t50, #t51) in #t51);
+  self::Extension|set#simpleSetter(c, 2);
+  self::expect(2, let final self::Class* #t53 = c in #t53.{core::Object::==}(null) ?{core::int*} null : #t53.{self::Class::field});
+  self::expect(3, let final self::Class* #t54 = c in let final core::int* #t55 = 3 in let final void #t56 = self::Extension|set#simpleSetter(#t54, #t55) in #t55);
+  self::Extension|set#mutatingSetter(c, 0);
+  self::expect(1, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : #t57.{self::Class::field});
+  self::expect(2, let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t59 = 2 in let final void #t60 = self::Extension|set#mutatingSetter(#t58, #t59) in #t59);
+  self::expect(3, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : #t61.{self::Class::field});
+  self::Extension|set#mutatingSetter(c, 4);
+  self::expect(5, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
+  self::expect(6, let final self::Class* #t63 = c in let final core::int* #t64 = 6 in let final void #t65 = self::Extension|set#mutatingSetter(#t63, #t64) in #t64);
+  self::expect(7, let final self::Class* #t66 = c in #t66.{core::Object::==}(null) ?{core::int*} null : #t66.{self::Class::field});
+  let final self::Class* #t67 = c in #t67.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t67, 1);
+  self::expect(1, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
+  let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t69, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t70 = c in #t70.{core::Object::==}(null) ?{core::int*} null : #t70.{self::Class::field});
+  self::expect(3, let final self::Class* #t71 = c in #t71.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t72 = 3 in let final void #t73 = self::Extension|set#setterWithReturn(#t71, #t72) in #t72);
+  self::expect(3, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t75 = c in #t75.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t76 = 4.{core::int::unary-}() in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
+  self::expect(4, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 5);
+  self::expect(5, let final self::Class* #t79 = c in #t79.{core::Object::==}(null) ?{core::int*} null : #t79.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
+  self::expect(6, let final self::Class* #t80 = c in #t80.{core::Object::==}(null) ?{core::int*} null : #t80.{self::Class::field});
+  self::expect(7, let final self::Class* #t81 = c in let final core::int* #t82 = 7 in let final void #t83 = self::Extension|set#setterWithReturn(#t81, #t82) in #t82);
+  self::expect(7, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t85 = c in let final core::int* #t86 = 8.{core::int::unary-}() in let final void #t87 = self::Extension|set#setterWithReturn(#t85, #t86) in #t86);
+  self::expect(8, let final self::Class* #t88 = c in #t88.{core::Object::==}(null) ?{core::int*} null : #t88.{self::Class::field});
+  let final self::Class* #t89 = c in #t89.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t89, 1);
+  self::expect(1, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
+  let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t91, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t92 = c in #t92.{core::Object::==}(null) ?{core::int*} null : #t92.{self::Class::field});
+  self::expect(3, let final self::Class* #t93 = c in #t93.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t94 = 3 in let final void #t95 = self::Extension|set#setterWithClosure(#t93, #t94) in #t94);
+  self::expect(3, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t97 = c in #t97.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t98 = 4.{core::int::unary-}() in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
+  self::expect(4, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 5);
+  self::expect(5, let final self::Class* #t101 = c in #t101.{core::Object::==}(null) ?{core::int*} null : #t101.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
+  self::expect(6, let final self::Class* #t102 = c in #t102.{core::Object::==}(null) ?{core::int*} null : #t102.{self::Class::field});
+  self::expect(7, let final self::Class* #t103 = c in let final core::int* #t104 = 7 in let final void #t105 = self::Extension|set#setterWithClosure(#t103, #t104) in #t104);
+  self::expect(7, let final self::Class* #t106 = c in #t106.{core::Object::==}(null) ?{core::int*} null : #t106.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t107 = c in let final core::int* #t108 = 8.{core::int::unary-}() in let final void #t109 = self::Extension|set#setterWithClosure(#t107, #t108) in #t108);
+  self::expect(8, let final self::Class* #t110 = c in #t110.{core::Object::==}(null) ?{core::int*} null : #t110.{self::Class::field});
+  c.{self::Class::field} = null;
+  let final self::Class* #t111 = c in self::Extension|get#simpleSetter(#t111).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t111, 1) : null;
+  self::expect(1, c.{self::Class::field});
+  self::expect(1, let final self::Class* #t112 = c in let final core::int* #t113 = self::Extension|get#simpleSetter(#t112) in #t113.{core::num::==}(null) ?{core::int*} let final self::Class* #t114 = #t112 in let final core::int* #t115 = 2 in let final void #t116 = self::Extension|set#simpleSetter(#t114, #t115) in #t115 : #t113);
+  c.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t117 = c in let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final self::Class* #t119 = #t117 in let final core::int* #t120 = 2 in let final void #t121 = self::Extension|set#simpleSetter(#t119, #t120) in #t120 : #t118);
+  let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::Null?} null : #t122.{self::Class::field} = null;
+  let final self::Class* #t123 = c in #t123.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t123).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t123, 1) : null;
+  self::expect(1, let final self::Class* #t124 = c in #t124.{core::Object::==}(null) ?{core::int*} null : #t124.{self::Class::field});
+  self::expect(1, let final self::Class* #t125 = c in #t125.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t126 = self::Extension|get#simpleSetter(#t125) in #t126.{core::num::==}(null) ?{core::int*} let final core::int* #t127 = 2 in let final void #t128 = self::Extension|set#simpleSetter(#t125, #t127) in #t127 : #t126);
+  let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
+  self::Extension|testInternal(new self::Class::•());
+}
+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/extension_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
new file mode 100644
index 0000000..f487199
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
@@ -0,0 +1,192 @@
+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 simpleSetter = self::Extension|get#simpleSetter;
+  get mutatingSetter = self::Extension|get#mutatingSetter;
+  get setterWithReturn = self::Extension|get#setterWithReturn;
+  get setterWithClosure = self::Extension|get#setterWithClosure;
+  method testInternal = self::Extension|testInternal;
+  tearoff testInternal = self::Extension|get#testInternal;
+  set simpleSetter = self::Extension|set#simpleSetter;
+  set mutatingSetter = self::Extension|set#mutatingSetter;
+  set setterWithReturn = self::Extension|set#setterWithReturn;
+  set setterWithClosure = self::Extension|set#setterWithClosure;
+}
+static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void {
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#mutatingSetter(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#mutatingSetter(final self::Class* #this, core::int* value) → void {
+  value = value.{core::num::+}(1);
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#setterWithReturn(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#setterWithReturn(final self::Class* #this, core::int* value) → void {
+  if(value.{core::num::<}(0)) {
+    #this.{self::Class::field} = value.{core::int::unary-}();
+    return;
+  }
+  #this.{self::Class::field} = value;
+}
+static method Extension|get#setterWithClosure(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#setterWithClosure(final self::Class* #this, core::int* value) → void {
+  function abs(dynamic value) → dynamic {
+    return value.<(0) as{TypeError} core::bool* ?{dynamic} value.unary-() : value;
+  }
+  #this.{self::Class::field} = abs.call(value) as{TypeError} core::int*;
+}
+static method Extension|testInternal(final self::Class* #this) → dynamic {
+  self::expect(null, #this.{self::Class::field});
+  self::Extension|set#simpleSetter(#this, 0);
+  self::expect(0, #this.{self::Class::field});
+  self::expect(1, let final core::int* #t1 = 1 in let final void #t2 = self::Extension|set#simpleSetter(#this, #t1) in #t1);
+  self::Extension|set#mutatingSetter(#this, 0);
+  self::expect(1, #this.{self::Class::field});
+  self::expect(2, let final core::int* #t3 = 2 in let final void #t4 = self::Extension|set#mutatingSetter(#this, #t3) in #t3);
+  self::expect(3, #this.{self::Class::field});
+  self::Extension|set#setterWithReturn(#this, 1);
+  self::expect(1, #this.{self::Class::field});
+  self::Extension|set#setterWithReturn(#this, 2.{core::int::unary-}());
+  self::expect(2, #this.{self::Class::field});
+  self::expect(3, let final core::int* #t5 = 3 in let final void #t6 = self::Extension|set#setterWithReturn(#this, #t5) in #t5);
+  self::expect(3, #this.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final core::int* #t7 = 4.{core::int::unary-}() in let final void #t8 = self::Extension|set#setterWithReturn(#this, #t7) in #t7);
+  self::expect(4, #this.{self::Class::field});
+  self::Extension|set#setterWithClosure(#this, 1);
+  self::expect(1, #this.{self::Class::field});
+  self::Extension|set#setterWithClosure(#this, 2.{core::int::unary-}());
+  self::expect(2, #this.{self::Class::field});
+  self::expect(3, let final core::int* #t9 = 3 in let final void #t10 = self::Extension|set#setterWithClosure(#this, #t9) in #t9);
+  self::expect(3, #this.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final core::int* #t11 = 4.{core::int::unary-}() in let final void #t12 = self::Extension|set#setterWithClosure(#this, #t11) in #t11);
+  self::expect(4, #this.{self::Class::field});
+}
+static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testInternal(#this);
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(null, c.{self::Class::field});
+  self::Extension|set#simpleSetter(c, 0);
+  self::expect(0, c.{self::Class::field});
+  self::expect(1, let final self::Class* #t13 = c in let final core::int* #t14 = 1 in let final void #t15 = self::Extension|set#simpleSetter(#t13, #t14) in #t14);
+  self::Extension|set#simpleSetter(c, 2);
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t16 = c in let final core::int* #t17 = 3 in let final void #t18 = self::Extension|set#simpleSetter(#t16, #t17) in #t17);
+  self::Extension|set#mutatingSetter(c, 0);
+  self::expect(1, c.{self::Class::field});
+  self::expect(2, let final self::Class* #t19 = c in let final core::int* #t20 = 2 in let final void #t21 = self::Extension|set#mutatingSetter(#t19, #t20) in #t20);
+  self::expect(3, c.{self::Class::field});
+  self::Extension|set#mutatingSetter(c, 4);
+  self::expect(5, c.{self::Class::field});
+  self::expect(6, let final self::Class* #t22 = c in let final core::int* #t23 = 6 in let final void #t24 = self::Extension|set#mutatingSetter(#t22, #t23) in #t23);
+  self::expect(7, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 1);
+  self::expect(1, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 2.{core::int::unary-}());
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t25 = c in let final core::int* #t26 = 3 in let final void #t27 = self::Extension|set#setterWithReturn(#t25, #t26) in #t26);
+  self::expect(3, c.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = 4.{core::int::unary-}() in let final void #t30 = self::Extension|set#setterWithReturn(#t28, #t29) in #t29);
+  self::expect(4, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 5);
+  self::expect(5, c.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
+  self::expect(6, c.{self::Class::field});
+  self::expect(7, let final self::Class* #t31 = c in let final core::int* #t32 = 7 in let final void #t33 = self::Extension|set#setterWithReturn(#t31, #t32) in #t32);
+  self::expect(7, c.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t34 = c in let final core::int* #t35 = 8.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithReturn(#t34, #t35) in #t35);
+  self::expect(8, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 1);
+  self::expect(1, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 2.{core::int::unary-}());
+  self::expect(2, c.{self::Class::field});
+  self::expect(3, let final self::Class* #t37 = c in let final core::int* #t38 = 3 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
+  self::expect(3, c.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 4.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
+  self::expect(4, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 5);
+  self::expect(5, c.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
+  self::expect(6, c.{self::Class::field});
+  self::expect(7, let final self::Class* #t43 = c in let final core::int* #t44 = 7 in let final void #t45 = self::Extension|set#setterWithClosure(#t43, #t44) in #t44);
+  self::expect(7, c.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t46 = c in let final core::int* #t47 = 8.{core::int::unary-}() in let final void #t48 = self::Extension|set#setterWithClosure(#t46, #t47) in #t47);
+  self::expect(8, c.{self::Class::field});
+  self::Extension|set#simpleSetter(c, 0);
+  self::expect(0, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : #t49.{self::Class::field});
+  self::expect(1, let final self::Class* #t50 = c in #t50.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t51 = 1 in let final void #t52 = self::Extension|set#simpleSetter(#t50, #t51) in #t51);
+  self::Extension|set#simpleSetter(c, 2);
+  self::expect(2, let final self::Class* #t53 = c in #t53.{core::Object::==}(null) ?{core::int*} null : #t53.{self::Class::field});
+  self::expect(3, let final self::Class* #t54 = c in let final core::int* #t55 = 3 in let final void #t56 = self::Extension|set#simpleSetter(#t54, #t55) in #t55);
+  self::Extension|set#mutatingSetter(c, 0);
+  self::expect(1, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : #t57.{self::Class::field});
+  self::expect(2, let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t59 = 2 in let final void #t60 = self::Extension|set#mutatingSetter(#t58, #t59) in #t59);
+  self::expect(3, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : #t61.{self::Class::field});
+  self::Extension|set#mutatingSetter(c, 4);
+  self::expect(5, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
+  self::expect(6, let final self::Class* #t63 = c in let final core::int* #t64 = 6 in let final void #t65 = self::Extension|set#mutatingSetter(#t63, #t64) in #t64);
+  self::expect(7, let final self::Class* #t66 = c in #t66.{core::Object::==}(null) ?{core::int*} null : #t66.{self::Class::field});
+  let final self::Class* #t67 = c in #t67.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t67, 1);
+  self::expect(1, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
+  let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t69, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t70 = c in #t70.{core::Object::==}(null) ?{core::int*} null : #t70.{self::Class::field});
+  self::expect(3, let final self::Class* #t71 = c in #t71.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t72 = 3 in let final void #t73 = self::Extension|set#setterWithReturn(#t71, #t72) in #t72);
+  self::expect(3, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t75 = c in #t75.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t76 = 4.{core::int::unary-}() in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
+  self::expect(4, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 5);
+  self::expect(5, let final self::Class* #t79 = c in #t79.{core::Object::==}(null) ?{core::int*} null : #t79.{self::Class::field});
+  self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
+  self::expect(6, let final self::Class* #t80 = c in #t80.{core::Object::==}(null) ?{core::int*} null : #t80.{self::Class::field});
+  self::expect(7, let final self::Class* #t81 = c in let final core::int* #t82 = 7 in let final void #t83 = self::Extension|set#setterWithReturn(#t81, #t82) in #t82);
+  self::expect(7, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t85 = c in let final core::int* #t86 = 8.{core::int::unary-}() in let final void #t87 = self::Extension|set#setterWithReturn(#t85, #t86) in #t86);
+  self::expect(8, let final self::Class* #t88 = c in #t88.{core::Object::==}(null) ?{core::int*} null : #t88.{self::Class::field});
+  let final self::Class* #t89 = c in #t89.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t89, 1);
+  self::expect(1, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
+  let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t91, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t92 = c in #t92.{core::Object::==}(null) ?{core::int*} null : #t92.{self::Class::field});
+  self::expect(3, let final self::Class* #t93 = c in #t93.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t94 = 3 in let final void #t95 = self::Extension|set#setterWithClosure(#t93, #t94) in #t94);
+  self::expect(3, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t97 = c in #t97.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t98 = 4.{core::int::unary-}() in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
+  self::expect(4, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 5);
+  self::expect(5, let final self::Class* #t101 = c in #t101.{core::Object::==}(null) ?{core::int*} null : #t101.{self::Class::field});
+  self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
+  self::expect(6, let final self::Class* #t102 = c in #t102.{core::Object::==}(null) ?{core::int*} null : #t102.{self::Class::field});
+  self::expect(7, let final self::Class* #t103 = c in let final core::int* #t104 = 7 in let final void #t105 = self::Extension|set#setterWithClosure(#t103, #t104) in #t104);
+  self::expect(7, let final self::Class* #t106 = c in #t106.{core::Object::==}(null) ?{core::int*} null : #t106.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t107 = c in let final core::int* #t108 = 8.{core::int::unary-}() in let final void #t109 = self::Extension|set#setterWithClosure(#t107, #t108) in #t108);
+  self::expect(8, let final self::Class* #t110 = c in #t110.{core::Object::==}(null) ?{core::int*} null : #t110.{self::Class::field});
+  c.{self::Class::field} = null;
+  let final self::Class* #t111 = c in self::Extension|get#simpleSetter(#t111).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t111, 1) : null;
+  self::expect(1, c.{self::Class::field});
+  self::expect(1, let final self::Class* #t112 = c in let final core::int* #t113 = self::Extension|get#simpleSetter(#t112) in #t113.{core::num::==}(null) ?{core::int*} let final self::Class* #t114 = #t112 in let final core::int* #t115 = 2 in let final void #t116 = self::Extension|set#simpleSetter(#t114, #t115) in #t115 : #t113);
+  c.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t117 = c in let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final self::Class* #t119 = #t117 in let final core::int* #t120 = 2 in let final void #t121 = self::Extension|set#simpleSetter(#t119, #t120) in #t120 : #t118);
+  let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::Null?} null : #t122.{self::Class::field} = null;
+  let final self::Class* #t123 = c in #t123.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t123).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t123, 1) : null;
+  self::expect(1, let final self::Class* #t124 = c in #t124.{core::Object::==}(null) ?{core::int*} null : #t124.{self::Class::field});
+  self::expect(1, let final self::Class* #t125 = c in #t125.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t126 = self::Extension|get#simpleSetter(#t125) in #t126.{core::num::==}(null) ?{core::int*} let final core::int* #t127 = 2 in let final void #t128 = self::Extension|set#simpleSetter(#t125, #t127) in #t127 : #t126);
+  let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
+  self::Extension|testInternal(new self::Class::•());
+}
+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/extension_setter.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.type_promotion.expect
new file mode 100644
index 0000000..759a79d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/extensions/extension_setter.dart:19:11: Context: Write to value@335
+    value = value + 1;
+          ^
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart
new file mode 100644
index 0000000..eb42294
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 get m1 => 0;
+  void set m2(int x) {}
+}
+
+extension Extension0 on Class {
+  void set m1(int x) {}
+  int get m2 => 0;
+  void set m3(int x) {}
+  int get m4 => 0;
+}
+
+extension Extension1 on Class {
+  int get m3 => 0;
+  void set m4(int x) {}
+}
+
+main() {
+  var c = new Class();
+  expect(0, c.m1);
+  c.m2 = 2;
+}
+
+errors() {
+  var c = new Class();
+  expect(0, c.m2);
+  c.m1 = 2;
+  c.m3;
+  c.m3 = 2;
+  c.m4;
+  c.m4 = 2;
+}
+
+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/getter_setter_conflict.dart.outline.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.outline.expect
new file mode 100644
index 0000000..ed922f8
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.outline.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  get m1() → core::int*
+    ;
+  set m2(core::int* x) → void
+    ;
+}
+extension Extension0 on self::Class* {
+  get m2 = self::Extension0|get#m2;
+  get m4 = self::Extension0|get#m4;
+  set m1 = self::Extension0|set#m1;
+  set m3 = self::Extension0|set#m3;
+}
+extension Extension1 on self::Class* {
+  get m3 = self::Extension1|get#m3;
+  set m4 = self::Extension1|set#m4;
+}
+static method Extension0|set#m1(final self::Class* #this, core::int* x) → void
+  ;
+static method Extension0|get#m2(final self::Class* #this) → core::int*
+  ;
+static method Extension0|set#m3(final self::Class* #this, core::int* x) → void
+  ;
+static method Extension0|get#m4(final self::Class* #this) → core::int*
+  ;
+static method Extension1|get#m3(final self::Class* #this) → core::int*
+  ;
+static method Extension1|set#m4(final self::Class* #this, core::int* x) → void
+  ;
+static method main() → dynamic
+  ;
+static method errors() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.strong.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.strong.expect
new file mode 100644
index 0000000..f432ee9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.strong.expect
@@ -0,0 +1,113 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:30:15: Error: The getter 'm2' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm2'.
+//   expect(0, c.m2);
+//               ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:31:5: Error: The setter 'm1' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   c.m1 = 2;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:32:5: Error: The getter 'm3' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm3'.
+//   c.m3;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:33:5: Error: The setter 'm3' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm3'.
+//   c.m3 = 2;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:34:5: Error: The getter 'm4' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm4'.
+//   c.m4;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:35:5: Error: The setter 'm4' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm4'.
+//   c.m4 = 2;
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  get m1() → core::int*
+    return 0;
+  set m2(core::int* x) → void {}
+}
+extension Extension0 on self::Class* {
+  get m2 = self::Extension0|get#m2;
+  get m4 = self::Extension0|get#m4;
+  set m1 = self::Extension0|set#m1;
+  set m3 = self::Extension0|set#m3;
+}
+extension Extension1 on self::Class* {
+  get m3 = self::Extension1|get#m3;
+  set m4 = self::Extension1|set#m4;
+}
+static method Extension0|set#m1(final self::Class* #this, core::int* x) → void {}
+static method Extension0|get#m2(final self::Class* #this) → core::int*
+  return 0;
+static method Extension0|set#m3(final self::Class* #this, core::int* x) → void {}
+static method Extension0|get#m4(final self::Class* #this) → core::int*
+  return 0;
+static method Extension1|get#m3(final self::Class* #this) → core::int*
+  return 0;
+static method Extension1|set#m4(final self::Class* #this, core::int* x) → void {}
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(0, c.{self::Class::m1});
+  c.{self::Class::m2} = 2;
+}
+static method errors() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(0, invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:30:15: Error: The getter 'm2' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm2'.
+  expect(0, c.m2);
+              ^^");
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:31:5: Error: The setter 'm1' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  c.m1 = 2;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:32:5: Error: The getter 'm3' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm3'.
+  c.m3;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:33:5: Error: The setter 'm3' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm3'.
+  c.m3 = 2;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:34:5: Error: The getter 'm4' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm4'.
+  c.m4;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:35:5: Error: The setter 'm4' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm4'.
+  c.m4 = 2;
+    ^^";
+}
+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/getter_setter_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.strong.transformed.expect
new file mode 100644
index 0000000..f432ee9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.strong.transformed.expect
@@ -0,0 +1,113 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:30:15: Error: The getter 'm2' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm2'.
+//   expect(0, c.m2);
+//               ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:31:5: Error: The setter 'm1' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   c.m1 = 2;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:32:5: Error: The getter 'm3' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm3'.
+//   c.m3;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:33:5: Error: The setter 'm3' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm3'.
+//   c.m3 = 2;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:34:5: Error: The getter 'm4' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'm4'.
+//   c.m4;
+//     ^^
+//
+// pkg/front_end/testcases/extensions/getter_setter_conflict.dart:35:5: Error: The setter 'm4' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm4'.
+//   c.m4 = 2;
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  get m1() → core::int*
+    return 0;
+  set m2(core::int* x) → void {}
+}
+extension Extension0 on self::Class* {
+  get m2 = self::Extension0|get#m2;
+  get m4 = self::Extension0|get#m4;
+  set m1 = self::Extension0|set#m1;
+  set m3 = self::Extension0|set#m3;
+}
+extension Extension1 on self::Class* {
+  get m3 = self::Extension1|get#m3;
+  set m4 = self::Extension1|set#m4;
+}
+static method Extension0|set#m1(final self::Class* #this, core::int* x) → void {}
+static method Extension0|get#m2(final self::Class* #this) → core::int*
+  return 0;
+static method Extension0|set#m3(final self::Class* #this, core::int* x) → void {}
+static method Extension0|get#m4(final self::Class* #this) → core::int*
+  return 0;
+static method Extension1|get#m3(final self::Class* #this) → core::int*
+  return 0;
+static method Extension1|set#m4(final self::Class* #this, core::int* x) → void {}
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(0, c.{self::Class::m1});
+  c.{self::Class::m2} = 2;
+}
+static method errors() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(0, invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:30:15: Error: The getter 'm2' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm2'.
+  expect(0, c.m2);
+              ^^");
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:31:5: Error: The setter 'm1' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  c.m1 = 2;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:32:5: Error: The getter 'm3' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm3'.
+  c.m3;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:33:5: Error: The setter 'm3' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm3'.
+  c.m3 = 2;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:34:5: Error: The getter 'm4' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'm4'.
+  c.m4;
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extensions/getter_setter_conflict.dart:35:5: Error: The setter 'm4' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/getter_setter_conflict.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm4'.
+  c.m4 = 2;
+    ^^";
+}
+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/if_null.dart b/pkg/front_end/testcases/extensions/if_null.dart
new file mode 100644
index 0000000..4dadffb
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.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 Class {
+  int field;
+}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {
+    field = value;
+  }
+  int method() => field;
+}
+
+main() {
+  Class c;
+  c?.property ?? 0;
+  Extension(c)?.property ?? 0;
+  c?.property = 42 ?? 0;
+  Extension(c)?.property = 42 ?? 0;
+  (c?.property = 42) ?? 0;
+  (Extension(c)?.property = 42) ?? 0;
+  c?.method() ?? 0;
+  Extension(c)?.method() ?? 0;
+  c = new Class();
+  c.property ?? 0;
+  Extension(c).property ?? 0;
+}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.outline.expect b/pkg/front_end/testcases/extensions/if_null.dart.outline.expect
new file mode 100644
index 0000000..17223f2
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.outline.expect
@@ -0,0 +1,25 @@
+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
+  ;
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.strong.expect b/pkg/front_end/testcases/extensions/if_null.dart.strong.expect
new file mode 100644
index 0000000..76f0f9b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.strong.expect
@@ -0,0 +1,39 @@
+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) → void {
+  #this.{self::Class::field} = value;
+}
+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;
+  let final core::int* #t1 = let final self::Class* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t2) in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+  let final core::int* #t3 = let final self::Class* #t4 = c in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t4) in #t3.{core::num::==}(null) ?{core::int*} 0 : #t3;
+  let final self::Class* #t5 = c in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t5, let final core::int* #t6 = 42 in #t6.{core::num::==}(null) ?{core::int*} 0 : #t6);
+  let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t7, let final core::int* #t8 = 42 in #t8.{core::num::==}(null) ?{core::int*} 0 : #t8);
+  let final core::int* #t9 = let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = 42 in let final void #t12 = self::Extension|set#property(#t10, #t11) in #t11 in #t9.{core::num::==}(null) ?{core::int*} 0 : #t9;
+  let final core::int* #t13 = let final self::Class* #t14 = c in #t14.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t15 = 42 in let final void #t16 = self::Extension|set#property(#t14, #t15) in #t15 in #t13.{core::num::==}(null) ?{core::int*} 0 : #t13;
+  let final core::int* #t17 = let final self::Class* #t18 = c in #t18.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t18) in #t17.{core::num::==}(null) ?{core::int*} 0 : #t17;
+  let final core::int* #t19 = let final self::Class* #t20 = c in #t20.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t20) in #t19.{core::num::==}(null) ?{core::int*} 0 : #t19;
+  c = new self::Class::•();
+  let final core::int* #t21 = self::Extension|get#property(c) in #t21.{core::num::==}(null) ?{core::int*} 0 : #t21;
+  let final core::int* #t22 = self::Extension|get#property(c) in #t22.{core::num::==}(null) ?{core::int*} 0 : #t22;
+}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect
new file mode 100644
index 0000000..76f0f9b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect
@@ -0,0 +1,39 @@
+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) → void {
+  #this.{self::Class::field} = value;
+}
+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;
+  let final core::int* #t1 = let final self::Class* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t2) in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+  let final core::int* #t3 = let final self::Class* #t4 = c in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t4) in #t3.{core::num::==}(null) ?{core::int*} 0 : #t3;
+  let final self::Class* #t5 = c in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t5, let final core::int* #t6 = 42 in #t6.{core::num::==}(null) ?{core::int*} 0 : #t6);
+  let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t7, let final core::int* #t8 = 42 in #t8.{core::num::==}(null) ?{core::int*} 0 : #t8);
+  let final core::int* #t9 = let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = 42 in let final void #t12 = self::Extension|set#property(#t10, #t11) in #t11 in #t9.{core::num::==}(null) ?{core::int*} 0 : #t9;
+  let final core::int* #t13 = let final self::Class* #t14 = c in #t14.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t15 = 42 in let final void #t16 = self::Extension|set#property(#t14, #t15) in #t15 in #t13.{core::num::==}(null) ?{core::int*} 0 : #t13;
+  let final core::int* #t17 = let final self::Class* #t18 = c in #t18.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t18) in #t17.{core::num::==}(null) ?{core::int*} 0 : #t17;
+  let final core::int* #t19 = let final self::Class* #t20 = c in #t20.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t20) in #t19.{core::num::==}(null) ?{core::int*} 0 : #t19;
+  c = new self::Class::•();
+  let final core::int* #t21 = self::Extension|get#property(c) in #t21.{core::num::==}(null) ?{core::int*} 0 : #t21;
+  let final core::int* #t22 = self::Extension|get#property(c) in #t22.{core::num::==}(null) ?{core::int*} 0 : #t22;
+}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect
new file mode 100644
index 0000000..8431aad
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/extensions/if_null.dart:27:5: Context: Write to c@408
+  c = new Class();
+    ^
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 9812038..895ddb7 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
@@ -50,12 +50,10 @@
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
 }
-static method Extension1|set#property(final self::Class1* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method Extension1|set#property(final self::Class1* #this, core::int* value) → void {
   #this.{self::Class1::field} = value;
   core::print("Extension1.property set(${value}) on ${#this}");
   value = value.{core::num::+}(1);
-  return #t1;
 }
 static method Extension2|method(final self::Class2* #this) → core::int* {
   core::print("Extension2.method on ${#this}");
@@ -73,12 +71,10 @@
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
 }
-static method Extension2|set#property(final self::Class2* #this, core::int* value) → core::int* {
-  final core::int* #t2 = value;
+static method Extension2|set#property(final self::Class2* #this, core::int* value) → void {
   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();
@@ -89,42 +85,42 @@
   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(1, let final self::Class1* #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int*} null : self::Extension1|method(#t1));
   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(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t2));
+  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::Extension1|set#property(#t3, #t4) in #t4);
   self::expect(1, self::Extension1|get#property(c1));
-  self::expect(87, self::Extension1|set#property(c0, 87));
-  self::expect(27, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 27)));
-  self::expect(37, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 37)));
-  self::expect(77, self::Extension1|set#property(c1, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 77))));
-  self::expect(67, self::Extension1|set#property(c0, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 67))));
+  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::Extension1|set#property(#t6, #t7) in #t7);
+  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::Extension1|set#property(#t11, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(#t9, #t10) in #t10);
+  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::Extension1|set#property(#t17, #t18) in #t18 in let final void #t20 = self::Extension1|set#property(#t15, #t16) in #t16);
+  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::Extension1|set#property(#t25, #t26) in #t26 in let final void #t28 = self::Extension1|set#property(#t23, #t24) in #t24 in let final void #t29 = self::Extension1|set#property(#t21, #t22) in #t22);
+  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::Extension1|set#property(#t34, #t35) in #t35 in let final void #t37 = self::Extension1|set#property(#t32, #t33) in #t33 in let final void #t38 = self::Extension1|set#property(#t30, #t31) in #t31);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::Extension2|method(c0));
-  self::expect(3, let final self::Class2* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t5));
+  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t39));
   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(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t40));
+  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::Extension2|set#property(#t41, #t42) in #t42);
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
-  self::expect(43, self::Extension2|set#property(c1, 43));
+  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::Extension2|set#property(#t44, #t45) in #t45);
   self::expect(49, self::Extension2|get#property(c1));
-  self::expect(49, self::Extension2|set#property(c0, self::Extension2|get#property(c1)));
-  self::expect(55, self::Extension2|set#property(c1, self::Extension2|get#property(c0)));
-  self::expect(61, self::Extension2|set#property(c1, self::Extension2|set#property(c0, self::Extension2|get#property(c1))));
-  self::expect(67, self::Extension2|set#property(c0, self::Extension2|set#property(c1, self::Extension2|get#property(c0))));
+  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::Extension2|get#property(c1) in let final void #t49 = self::Extension2|set#property(#t47, #t48) in #t48);
+  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::Extension2|get#property(c0) in let final void #t52 = self::Extension2|set#property(#t50, #t51) in #t51);
+  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::Extension2|get#property(c1) in let final void #t57 = self::Extension2|set#property(#t55, #t56) in #t56 in let final void #t58 = self::Extension2|set#property(#t53, #t54) in #t54);
+  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::Extension2|get#property(c0) in let final void #t63 = self::Extension2|set#property(#t61, #t62) in #t62 in let final void #t64 = self::Extension2|set#property(#t59, #t60) in #t60);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
index 9812038..895ddb7 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
@@ -50,12 +50,10 @@
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
 }
-static method Extension1|set#property(final self::Class1* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method Extension1|set#property(final self::Class1* #this, core::int* value) → void {
   #this.{self::Class1::field} = value;
   core::print("Extension1.property set(${value}) on ${#this}");
   value = value.{core::num::+}(1);
-  return #t1;
 }
 static method Extension2|method(final self::Class2* #this) → core::int* {
   core::print("Extension2.method on ${#this}");
@@ -73,12 +71,10 @@
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
 }
-static method Extension2|set#property(final self::Class2* #this, core::int* value) → core::int* {
-  final core::int* #t2 = value;
+static method Extension2|set#property(final self::Class2* #this, core::int* value) → void {
   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();
@@ -89,42 +85,42 @@
   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(1, let final self::Class1* #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int*} null : self::Extension1|method(#t1));
   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(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t2));
+  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::Extension1|set#property(#t3, #t4) in #t4);
   self::expect(1, self::Extension1|get#property(c1));
-  self::expect(87, self::Extension1|set#property(c0, 87));
-  self::expect(27, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 27)));
-  self::expect(37, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 37)));
-  self::expect(77, self::Extension1|set#property(c1, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 77))));
-  self::expect(67, self::Extension1|set#property(c0, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 67))));
+  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::Extension1|set#property(#t6, #t7) in #t7);
+  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::Extension1|set#property(#t11, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(#t9, #t10) in #t10);
+  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::Extension1|set#property(#t17, #t18) in #t18 in let final void #t20 = self::Extension1|set#property(#t15, #t16) in #t16);
+  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::Extension1|set#property(#t25, #t26) in #t26 in let final void #t28 = self::Extension1|set#property(#t23, #t24) in #t24 in let final void #t29 = self::Extension1|set#property(#t21, #t22) in #t22);
+  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::Extension1|set#property(#t34, #t35) in #t35 in let final void #t37 = self::Extension1|set#property(#t32, #t33) in #t33 in let final void #t38 = self::Extension1|set#property(#t30, #t31) in #t31);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::Extension2|method(c0));
-  self::expect(3, let final self::Class2* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t5));
+  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t39));
   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(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t40));
+  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::Extension2|set#property(#t41, #t42) in #t42);
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
-  self::expect(43, self::Extension2|set#property(c1, 43));
+  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::Extension2|set#property(#t44, #t45) in #t45);
   self::expect(49, self::Extension2|get#property(c1));
-  self::expect(49, self::Extension2|set#property(c0, self::Extension2|get#property(c1)));
-  self::expect(55, self::Extension2|set#property(c1, self::Extension2|get#property(c0)));
-  self::expect(61, self::Extension2|set#property(c1, self::Extension2|set#property(c0, self::Extension2|get#property(c1))));
-  self::expect(67, self::Extension2|set#property(c0, self::Extension2|set#property(c1, self::Extension2|get#property(c0))));
+  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::Extension2|get#property(c1) in let final void #t49 = self::Extension2|set#property(#t47, #t48) in #t48);
+  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::Extension2|get#property(c0) in let final void #t52 = self::Extension2|set#property(#t50, #t51) in #t51);
+  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::Extension2|get#property(c1) in let final void #t57 = self::Extension2|set#property(#t55, #t56) in #t56 in let final void #t58 = self::Extension2|set#property(#t53, #t54) in #t54);
+  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::Extension2|get#property(c0) in let final void #t63 = self::Extension2|set#property(#t61, #t62) in #t62 in let final void #t64 = self::Extension2|set#property(#t59, #t60) in #t60);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect b/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect
index 36c0330..09050c7 100644
--- a/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect
@@ -37,11 +37,11 @@
 static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o]) → self::A1*
   ;
 static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
-  return <T extends core::Object* = dynamic>([T* o = null]) → self::A1* => self::A2|method3<T*>(#this, o);
+  return <T extends core::Object* = dynamic>([T* o]) → self::A1* => self::A2|method3<T*>(#this, o);
 static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o}) → self::A1*
   ;
 static method A2|get#method4(final self::A1* #this) → <T extends core::Object* = dynamic>({o: T*}) →* self::A1*
-  return <T extends core::Object* = dynamic>({T* o = null}) → self::A1* => self::A2|method4<T*>(#this, o: o);
+  return <T extends core::Object* = dynamic>({T* o}) → self::A1* => self::A2|method4<T*>(#this, o: o);
 static method B2|method1<T extends core::Object* = dynamic>(final self::B1<self::B2|method1::T*>* #this) → self::B1<self::B2|method1::T*>*
   ;
 static method B2|get#method1<T extends core::Object* = dynamic>(final self::B1<self::B2|get#method1::T*>* #this) → () →* self::B1<self::B2|get#method1::T*>*
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect
index dfed3fb..5b79a6b 100644
--- a/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect
@@ -39,13 +39,13 @@
 }
 static method A2|get#method2(final self::A1* #this) → <T extends core::Object* = dynamic>(T*) →* self::A1*
   return <T extends core::Object* = dynamic>(T* o) → self::A1* => self::A2|method2<T*>(#this, o);
-static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* {
+static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o = #C1]) → self::A1* {
   core::print(o);
   return #this;
 }
 static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
   return <T extends core::Object* = dynamic>([T* o = #C1]) → self::A1* => self::A2|method3<T*>(#this, o);
-static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* {
+static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* {
   core::print(o);
   return #this;
 }
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect
index dfed3fb..5b79a6b 100644
--- a/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect
@@ -39,13 +39,13 @@
 }
 static method A2|get#method2(final self::A1* #this) → <T extends core::Object* = dynamic>(T*) →* self::A1*
   return <T extends core::Object* = dynamic>(T* o) → self::A1* => self::A2|method2<T*>(#this, o);
-static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* {
+static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o = #C1]) → self::A1* {
   core::print(o);
   return #this;
 }
 static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
   return <T extends core::Object* = dynamic>([T* o = #C1]) → self::A1* => self::A2|method3<T*>(#this, o);
-static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* {
+static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* {
   core::print(o);
   return #this;
 }
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart b/pkg/front_end/testcases/extensions/internal_resolution.dart
new file mode 100644
index 0000000..1494e16
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  int field;
+}
+
+extension on Class {
+  int get property1 => property2;
+  void set property1(int value) => field = value;
+}
+
+extension on Class {
+  int get property2 => field;
+  void set property2(int value) => property1 = value;
+}
+
+main() {
+  var c = new Class();
+  expect(null, c.property1);
+  expect(null, c.property2);
+  expect(42, c.property1 = 42);
+  expect(42, c.property2);
+  expect(87, c.property2 = 87);
+  expect(87, c.property1);
+}
+
+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/internal_resolution.dart.outline.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.outline.expect
new file mode 100644
index 0000000..5c9540a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.outline.expect
@@ -0,0 +1,29 @@
+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#0 on self::Class* {
+  get property1 = self::_extension#0|get#property1;
+  set property1 = self::_extension#0|set#property1;
+}
+extension _extension#1 on self::Class* {
+  get property2 = self::_extension#1|get#property2;
+  set property2 = self::_extension#1|set#property2;
+}
+static method _extension#0|get#property1(final self::Class* #this) → core::int*
+  ;
+static method _extension#0|set#property1(final self::Class* #this, core::int* value) → void
+  ;
+static method _extension#1|get#property2(final self::Class* #this) → core::int*
+  ;
+static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect
new file mode 100644
index 0000000..0225e55
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect
@@ -0,0 +1,40 @@
+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#0 on self::Class* {
+  get property1 = self::_extension#0|get#property1;
+  set property1 = self::_extension#0|set#property1;
+}
+extension _extension#1 on self::Class* {
+  get property2 = self::_extension#1|get#property2;
+  set property2 = self::_extension#1|set#property2;
+}
+static method _extension#0|get#property1(final self::Class* #this) → core::int*
+  return self::_extension#1|get#property2(#this);
+static method _extension#0|set#property1(final self::Class* #this, core::int* value) → void
+  return #this.{self::Class::field} = value;
+static method _extension#1|get#property2(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
+  return let final self::Class* #t1 = #this in let final core::int* #t2 = value in let final void #t3 = self::_extension#0|set#property1(#t1, #t2) in #t2;
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(null, self::_extension#0|get#property1(c));
+  self::expect(null, self::_extension#1|get#property2(c));
+  self::expect(42, let final self::Class* #t4 = c in let final core::int* #t5 = 42 in let final void #t6 = self::_extension#0|set#property1(#t4, #t5) in #t5);
+  self::expect(42, self::_extension#1|get#property2(c));
+  self::expect(87, let final self::Class* #t7 = c in let final core::int* #t8 = 87 in let final void #t9 = self::_extension#1|set#property2(#t7, #t8) in #t8);
+  self::expect(87, self::_extension#0|get#property1(c));
+}
+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/internal_resolution.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
new file mode 100644
index 0000000..0225e55
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+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#0 on self::Class* {
+  get property1 = self::_extension#0|get#property1;
+  set property1 = self::_extension#0|set#property1;
+}
+extension _extension#1 on self::Class* {
+  get property2 = self::_extension#1|get#property2;
+  set property2 = self::_extension#1|set#property2;
+}
+static method _extension#0|get#property1(final self::Class* #this) → core::int*
+  return self::_extension#1|get#property2(#this);
+static method _extension#0|set#property1(final self::Class* #this, core::int* value) → void
+  return #this.{self::Class::field} = value;
+static method _extension#1|get#property2(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
+  return let final self::Class* #t1 = #this in let final core::int* #t2 = value in let final void #t3 = self::_extension#0|set#property1(#t1, #t2) in #t2;
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect(null, self::_extension#0|get#property1(c));
+  self::expect(null, self::_extension#1|get#property2(c));
+  self::expect(42, let final self::Class* #t4 = c in let final core::int* #t5 = 42 in let final void #t6 = self::_extension#0|set#property1(#t4, #t5) in #t5);
+  self::expect(42, self::_extension#1|get#property2(c));
+  self::expect(87, let final self::Class* #t7 = c in let final core::int* #t8 = 87 in let final void #t9 = self::_extension#1|set#property2(#t7, #t8) in #t8);
+  self::expect(87, self::_extension#0|get#property1(c));
+}
+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 b/pkg/front_end/testcases/extensions/null_aware.dart
index d645b13..6b8d908 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart
+++ b/pkg/front_end/testcases/extensions/null_aware.dart
@@ -12,6 +12,12 @@
     field = value;
   }
   int method() => field;
+
+  testImplicitThis() {
+    expect(null, property);
+    expect(42, property ??= 42);
+    expect(42, property ??= 87);
+  }
 }
 
 main() {
@@ -20,6 +26,8 @@
   expect(null, c?.method);
   expect(null, c?.method());
   expect(null, c?.property = 42);
+  expect(null, Extension(c)?.property ??= 42);
+
   c = new Class();
   expect(null, c?.property);
   expect(null, c?.method());
@@ -27,9 +35,35 @@
   expect(null, tearOff());
   expect(42, c?.property = 42);
   expect(42, tearOff());
+
   expect(null, c?.property = null);
+  expect(42, c?.property = 42);
+
+  c?.property = null;
+  expect(null, c?.property);
   expect(42, c.property ??= 42);
   expect(42, c.property ??= 87);
+
+  expect(null, c?.property = null);
+  c.property ??= 42;
+  expect(42, c?.property);
+  c.property ??= 87;
+  expect(42, c?.property);
+
+  c?.property = null;
+  expect(null, c?.property);
+  expect(42, Extension(c).property ??= 42);
+  expect(42, Extension(c).property ??= 87);
+
+  c?.property = null;
+  expect(null, c?.property);
+  Extension(c).property ??= 42;
+  expect(42, c?.property);
+  Extension(c).property ??= 87;
+  expect(42, c?.property);
+
+  c?.property = null;
+  c.testImplicitThis();
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect b/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect
index 50dde61..3e892cf 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect
@@ -11,6 +11,8 @@
   get property = self::Extension|get#property;
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
+  method testImplicitThis = self::Extension|testImplicitThis;
+  tearoff testImplicitThis = self::Extension|get#testImplicitThis;
   set property = self::Extension|set#property;
 }
 static method Extension|get#property(final self::Class* #this) → core::int*
@@ -21,6 +23,10 @@
   ;
 static method Extension|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension|method(#this);
+static method Extension|testImplicitThis(final self::Class* #this) → dynamic
+  ;
+static method Extension|get#testImplicitThis(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testImplicitThis(#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
index 6b4ef8f..6d32899 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
@@ -12,35 +12,63 @@
   get property = self::Extension|get#property;
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
+  method testImplicitThis = self::Extension|testImplicitThis;
+  tearoff testImplicitThis = self::Extension|get#testImplicitThis;
   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;
+static method Extension|set#property(final self::Class* #this, core::int* value) → void {
   #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 Extension|testImplicitThis(final self::Class* #this) → dynamic {
+  self::expect(null, self::Extension|get#property(#this));
+  self::expect(42, let final core::int* #t1 = self::Extension|get#property(#this) in #t1.{core::num::==}(null) ?{core::int*} let final core::int* #t2 = 42 in let final void #t3 = self::Extension|set#property(#this, #t2) in #t2 : #t1);
+  self::expect(42, let final core::int* #t4 = self::Extension|get#property(#this) in #t4.{core::num::==}(null) ?{core::int*} let final core::int* #t5 = 87 in let final void #t6 = self::Extension|set#property(#this, #t5) in #t5 : #t4);
+}
+static method Extension|get#testImplicitThis(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testImplicitThis(#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));
+  self::expect(null, let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t7));
+  self::expect(null, let final self::Class* #t8 = c in #t8.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t8));
+  self::expect(null, let final self::Class* #t9 = c in #t9.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t9));
+  self::expect(null, let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = 42 in let final void #t12 = self::Extension|set#property(#t10, #t11) in #t11);
+  self::expect(null, let final self::Class* #t13 = c in #t13.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t14 = self::Extension|get#property(#t13) in #t14.{core::num::==}(null) ?{core::int*} let final core::int* #t15 = 42 in let final void #t16 = self::Extension|set#property(#t13, #t15) in #t15 : #t14);
   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, let final self::Class* #t17 = c in #t17.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t17));
+  self::expect(null, let final self::Class* #t18 = c in #t18.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t18));
+  () →* core::int* tearOff = let final self::Class* #t19 = c in #t19.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t19);
   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, let final self::Class* #t20 = c in #t20.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t21 = 42 in let final void #t22 = self::Extension|set#property(#t20, #t21) in #t21);
   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);
+  self::expect(null, let final self::Class* #t23 = c in #t23.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t24 = null in let final void #t25 = self::Extension|set#property(#t23, #t24) in #t24);
+  self::expect(42, let final self::Class* #t26 = c in #t26.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t27 = 42 in let final void #t28 = self::Extension|set#property(#t26, #t27) in #t27);
+  let final self::Class* #t29 = c in #t29.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t29, null);
+  self::expect(null, let final self::Class* #t30 = c in #t30.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t30));
+  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final self::Class* #t33 = #t31 in let final core::int* #t34 = 42 in let final void #t35 = self::Extension|set#property(#t33, #t34) in #t34 : #t32);
+  self::expect(42, let final self::Class* #t36 = c in let final core::int* #t37 = self::Extension|get#property(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final self::Class* #t38 = #t36 in let final core::int* #t39 = 87 in let final void #t40 = self::Extension|set#property(#t38, #t39) in #t39 : #t37);
+  self::expect(null, let final self::Class* #t41 = c in #t41.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t42 = null in let final void #t43 = self::Extension|set#property(#t41, #t42) in #t42);
+  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 42) : null;
+  self::expect(42, let final self::Class* #t45 = c in #t45.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t45));
+  let final self::Class* #t46 = c in self::Extension|get#property(#t46).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t46, 87) : null;
+  self::expect(42, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
+  let final self::Class* #t48 = c in #t48.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t48, null);
+  self::expect(null, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t49));
+  self::expect(42, let final self::Class* #t50 = c in let final core::int* #t51 = self::Extension|get#property(#t50) in #t51.{core::num::==}(null) ?{core::int*} let final core::int* #t52 = 42 in let final void #t53 = self::Extension|set#property(#t50, #t52) in #t52 : #t51);
+  self::expect(42, let final self::Class* #t54 = c in let final core::int* #t55 = self::Extension|get#property(#t54) in #t55.{core::num::==}(null) ?{core::int*} let final core::int* #t56 = 87 in let final void #t57 = self::Extension|set#property(#t54, #t56) in #t56 : #t55);
+  let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t58, null);
+  self::expect(null, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
+  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 42) : null;
+  self::expect(42, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t61));
+  let final self::Class* #t62 = c in self::Extension|get#property(#t62).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t62, 87) : null;
+  self::expect(42, let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t63));
+  let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t64, null);
+  self::Extension|testImplicitThis(c);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(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
index 6b4ef8f..6d32899 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
@@ -12,35 +12,63 @@
   get property = self::Extension|get#property;
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
+  method testImplicitThis = self::Extension|testImplicitThis;
+  tearoff testImplicitThis = self::Extension|get#testImplicitThis;
   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;
+static method Extension|set#property(final self::Class* #this, core::int* value) → void {
   #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 Extension|testImplicitThis(final self::Class* #this) → dynamic {
+  self::expect(null, self::Extension|get#property(#this));
+  self::expect(42, let final core::int* #t1 = self::Extension|get#property(#this) in #t1.{core::num::==}(null) ?{core::int*} let final core::int* #t2 = 42 in let final void #t3 = self::Extension|set#property(#this, #t2) in #t2 : #t1);
+  self::expect(42, let final core::int* #t4 = self::Extension|get#property(#this) in #t4.{core::num::==}(null) ?{core::int*} let final core::int* #t5 = 87 in let final void #t6 = self::Extension|set#property(#this, #t5) in #t5 : #t4);
+}
+static method Extension|get#testImplicitThis(final self::Class* #this) → () →* dynamic
+  return () → dynamic => self::Extension|testImplicitThis(#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));
+  self::expect(null, let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t7));
+  self::expect(null, let final self::Class* #t8 = c in #t8.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t8));
+  self::expect(null, let final self::Class* #t9 = c in #t9.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t9));
+  self::expect(null, let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = 42 in let final void #t12 = self::Extension|set#property(#t10, #t11) in #t11);
+  self::expect(null, let final self::Class* #t13 = c in #t13.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t14 = self::Extension|get#property(#t13) in #t14.{core::num::==}(null) ?{core::int*} let final core::int* #t15 = 42 in let final void #t16 = self::Extension|set#property(#t13, #t15) in #t15 : #t14);
   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, let final self::Class* #t17 = c in #t17.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t17));
+  self::expect(null, let final self::Class* #t18 = c in #t18.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t18));
+  () →* core::int* tearOff = let final self::Class* #t19 = c in #t19.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t19);
   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, let final self::Class* #t20 = c in #t20.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t21 = 42 in let final void #t22 = self::Extension|set#property(#t20, #t21) in #t21);
   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);
+  self::expect(null, let final self::Class* #t23 = c in #t23.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t24 = null in let final void #t25 = self::Extension|set#property(#t23, #t24) in #t24);
+  self::expect(42, let final self::Class* #t26 = c in #t26.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t27 = 42 in let final void #t28 = self::Extension|set#property(#t26, #t27) in #t27);
+  let final self::Class* #t29 = c in #t29.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t29, null);
+  self::expect(null, let final self::Class* #t30 = c in #t30.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t30));
+  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final self::Class* #t33 = #t31 in let final core::int* #t34 = 42 in let final void #t35 = self::Extension|set#property(#t33, #t34) in #t34 : #t32);
+  self::expect(42, let final self::Class* #t36 = c in let final core::int* #t37 = self::Extension|get#property(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final self::Class* #t38 = #t36 in let final core::int* #t39 = 87 in let final void #t40 = self::Extension|set#property(#t38, #t39) in #t39 : #t37);
+  self::expect(null, let final self::Class* #t41 = c in #t41.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t42 = null in let final void #t43 = self::Extension|set#property(#t41, #t42) in #t42);
+  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 42) : null;
+  self::expect(42, let final self::Class* #t45 = c in #t45.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t45));
+  let final self::Class* #t46 = c in self::Extension|get#property(#t46).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t46, 87) : null;
+  self::expect(42, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
+  let final self::Class* #t48 = c in #t48.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t48, null);
+  self::expect(null, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t49));
+  self::expect(42, let final self::Class* #t50 = c in let final core::int* #t51 = self::Extension|get#property(#t50) in #t51.{core::num::==}(null) ?{core::int*} let final core::int* #t52 = 42 in let final void #t53 = self::Extension|set#property(#t50, #t52) in #t52 : #t51);
+  self::expect(42, let final self::Class* #t54 = c in let final core::int* #t55 = self::Extension|get#property(#t54) in #t55.{core::num::==}(null) ?{core::int*} let final core::int* #t56 = 87 in let final void #t57 = self::Extension|set#property(#t54, #t56) in #t56 : #t55);
+  let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t58, null);
+  self::expect(null, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
+  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 42) : null;
+  self::expect(42, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t61));
+  let final self::Class* #t62 = c in self::Extension|get#property(#t62).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t62, 87) : null;
+  self::expect(42, let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t63));
+  let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t64, null);
+  self::Extension|testImplicitThis(c);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(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
index dee5817..5534d1b 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
@@ -1,3 +1,3 @@
-pkg/front_end/testcases/extensions/null_aware.dart:23:5: Context: Write to c@408
+pkg/front_end/testcases/extensions/null_aware.dart:31:5: Context: Write to c@530
   c = new Class();
     ^
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart b/pkg/front_end/testcases/extensions/on_function_type.dart
new file mode 100644
index 0000000..b3e30d2
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.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.
+
+extension<R, T> on R Function(T) {
+  Type get returnType => R;
+  Type get parameterType => T;
+}
+
+class Class<T extends Class<T>> {}
+
+class Subclass extends Class<Subclass> {}
+
+extension<T extends Class<T>> on dynamic Function<S extends T>(T, S) {
+  Type get parameterType => T;
+}
+
+main() {
+  int local1(int i) => i;
+
+  print(local1.returnType);
+  print(local1.parameterType);
+
+  Subclass local2<S extends Subclass>(Subclass a, S b) => a;
+
+  print(local2.parameterType);
+}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect
new file mode 100644
index 0000000..b83d5f5
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends self::Class<self::Class::T*>* = self::Class<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T*>*
+    ;
+}
+class Subclass extends self::Class<self::Subclass*> {
+  synthetic constructor •() → self::Subclass*
+    ;
+}
+extension _extension#0<R extends core::Object* = dynamic, T extends core::Object* = dynamic> on (T*) →* R* {
+  get returnType = self::_extension#0|get#returnType;
+  get parameterType = self::_extension#0|get#parameterType;
+}
+extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+  get parameterType = self::_extension#1|get#parameterType;
+}
+static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
+  ;
+static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
+  ;
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect
new file mode 100644
index 0000000..c4d4880
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends self::Class<self::Class::T*>* = self::Class<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T*>*
+    : super core::Object::•()
+    ;
+}
+class Subclass extends self::Class<self::Subclass*> {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+}
+extension _extension#0<R extends core::Object* = dynamic, T extends core::Object* = dynamic> on (T*) →* R* {
+  get returnType = self::_extension#0|get#returnType;
+  get parameterType = self::_extension#0|get#parameterType;
+}
+extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+  get parameterType = self::_extension#1|get#parameterType;
+}
+static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
+  return self::_extension#0|get#returnType::R*;
+static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
+  return self::_extension#0|get#parameterType::T*;
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+  return self::_extension#1|get#parameterType::T*;
+static method main() → dynamic {
+  function local1(core::int* i) → core::int*
+    return i;
+  core::print(self::_extension#0|get#returnType<core::int*, core::int*>(local1));
+  core::print(self::_extension#0|get#parameterType<core::int*, core::int*>(local1));
+  function local2<S extends self::Subclass* = self::Subclass*>(self::Subclass* a, S* b) → self::Subclass*
+    return a;
+  core::print(self::_extension#1|get#parameterType<self::Subclass*>(local2));
+}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..c4d4880
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends self::Class<self::Class::T*>* = self::Class<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T*>*
+    : super core::Object::•()
+    ;
+}
+class Subclass extends self::Class<self::Subclass*> {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+}
+extension _extension#0<R extends core::Object* = dynamic, T extends core::Object* = dynamic> on (T*) →* R* {
+  get returnType = self::_extension#0|get#returnType;
+  get parameterType = self::_extension#0|get#parameterType;
+}
+extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+  get parameterType = self::_extension#1|get#parameterType;
+}
+static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
+  return self::_extension#0|get#returnType::R*;
+static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
+  return self::_extension#0|get#parameterType::T*;
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+  return self::_extension#1|get#parameterType::T*;
+static method main() → dynamic {
+  function local1(core::int* i) → core::int*
+    return i;
+  core::print(self::_extension#0|get#returnType<core::int*, core::int*>(local1));
+  core::print(self::_extension#0|get#parameterType<core::int*, core::int*>(local1));
+  function local2<S extends self::Subclass* = self::Subclass*>(self::Subclass* a, S* b) → self::Subclass*
+    return a;
+  core::print(self::_extension#1|get#parameterType<self::Subclass*>(local2));
+}
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 f788aff..157b936 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
@@ -73,10 +73,7 @@
   return () → self::Extension|get#method::T* => self::Extension|method<self::Extension|get#method::T*>(#this);
 static method Extension|get#property<T extends self::Struct* = dynamic>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
   return #this;
-static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → self::Extension|set#property::T* {
-  final self::Extension|set#property::T* #t1 = value;
-  return #t1;
-}
+static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
 static method main() → dynamic {
   self::Struct* struct;
   self::StructA* structA;
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 f788aff..157b936 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
@@ -73,10 +73,7 @@
   return () → self::Extension|get#method::T* => self::Extension|method<self::Extension|get#method::T*>(#this);
 static method Extension|get#property<T extends self::Struct* = dynamic>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
   return #this;
-static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → self::Extension|set#property::T* {
-  final self::Extension|set#property::T* #t1 = value;
-  return #t1;
-}
+static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
 static method main() → dynamic {
   self::Struct* struct;
   self::StructA* structA;
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart b/pkg/front_end/testcases/extensions/other_kinds.dart
index 21e21b4..1958166 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart
@@ -22,12 +22,18 @@
     setInstanceField(value);
   }
 
-  // TODO(johnniwinther): Test operator -() and operator -(val).
-
   int operator +(int value) {
     return getInstanceField() + value;
   }
 
+  int operator -(int value) {
+    return getInstanceField() - value;
+  }
+
+  int operator -() {
+   return -getInstanceField();
+  }
+
   static int staticField = A1.getStaticField();
 
   static int get staticProperty => A1.getStaticField();
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.outline.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.outline.expect
index 48438c1..964d48f 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.outline.expect
@@ -19,6 +19,8 @@
 extension A2 on self::A1* {
   get instanceProperty = self::A2|get#instanceProperty;
   operator + = self::A2|+;
+  operator - = self::A2|-;
+  operator unary- = self::A2|unary-;
   static field staticField = self::A2|staticField;
   static get staticProperty = get self::A2|staticProperty;
   set instanceProperty = self::A2|set#instanceProperty;
@@ -31,6 +33,10 @@
   ;
 static method A2|+(final self::A1* #this, core::int* value) → core::int*
   ;
+static method A2|-(final self::A1* #this, core::int* value) → core::int*
+  ;
+static method A2|unary-(final self::A1* #this) → core::int*
+  ;
 static get A2|staticProperty() → core::int*
   ;
 static set A2|staticProperty(core::int* value) → void
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.strong.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.strong.expect
index 4c4e60c..b4b386a 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.strong.expect
@@ -22,6 +22,8 @@
 extension A2 on self::A1* {
   get instanceProperty = self::A2|get#instanceProperty;
   operator + = self::A2|+;
+  operator - = self::A2|-;
+  operator unary- = self::A2|unary-;
   static field staticField = self::A2|staticField;
   static get staticProperty = get self::A2|staticProperty;
   set instanceProperty = self::A2|set#instanceProperty;
@@ -30,14 +32,18 @@
 static field core::int* A2|staticField = self::A1::getStaticField();
 static method A2|get#instanceProperty(final self::A1* #this) → core::int*
   return #this.{self::A1::getInstanceField}();
-static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → void {
   #this.{self::A1::setInstanceField}(value);
-  return #t1;
 }
 static method A2|+(final self::A1* #this, core::int* value) → core::int* {
   return #this.{self::A1::getInstanceField}().{core::num::+}(value);
 }
+static method A2|-(final self::A1* #this, core::int* value) → core::int* {
+  return #this.{self::A1::getInstanceField}().{core::num::-}(value);
+}
+static method A2|unary-(final self::A1* #this) → core::int* {
+  return #this.{self::A1::getInstanceField}().{core::int::unary-}();
+}
 static get A2|staticProperty() → core::int*
   return self::A1::getStaticField();
 static set A2|staticProperty(core::int* value) → void {
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.strong.transformed.expect
index 4c4e60c..b4b386a 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.strong.transformed.expect
@@ -22,6 +22,8 @@
 extension A2 on self::A1* {
   get instanceProperty = self::A2|get#instanceProperty;
   operator + = self::A2|+;
+  operator - = self::A2|-;
+  operator unary- = self::A2|unary-;
   static field staticField = self::A2|staticField;
   static get staticProperty = get self::A2|staticProperty;
   set instanceProperty = self::A2|set#instanceProperty;
@@ -30,14 +32,18 @@
 static field core::int* A2|staticField = self::A1::getStaticField();
 static method A2|get#instanceProperty(final self::A1* #this) → core::int*
   return #this.{self::A1::getInstanceField}();
-static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → core::int* {
-  final core::int* #t1 = value;
+static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → void {
   #this.{self::A1::setInstanceField}(value);
-  return #t1;
 }
 static method A2|+(final self::A1* #this, core::int* value) → core::int* {
   return #this.{self::A1::getInstanceField}().{core::num::+}(value);
 }
+static method A2|-(final self::A1* #this, core::int* value) → core::int* {
+  return #this.{self::A1::getInstanceField}().{core::num::-}(value);
+}
+static method A2|unary-(final self::A1* #this) → core::int* {
+  return #this.{self::A1::getInstanceField}().{core::int::unary-}();
+}
 static get A2|staticProperty() → core::int*
   return self::A1::getStaticField();
 static set A2|staticProperty(core::int* value) → void {
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.strong.expect b/pkg/front_end/testcases/extensions/static_access.dart.strong.expect
index 9c616d4..b5659e5 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.strong.expect
@@ -29,10 +29,7 @@
   return () → dynamic => self::Extension|instanceMethod(#this);
 static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
   return 42;
-static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
-  return #t1;
-}
+static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void {}
 static method main() → dynamic {
   self::Extension|method();
   self::Extension|genericMethod<core::int*>(42);
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/static_access.dart.strong.transformed.expect
index 9c616d4..b5659e5 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.strong.transformed.expect
@@ -29,10 +29,7 @@
   return () → dynamic => self::Extension|instanceMethod(#this);
 static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
   return 42;
-static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
-  return #t1;
-}
+static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void {}
 static method main() → dynamic {
   self::Extension|method();
   self::Extension|genericMethod<core::int*>(42);
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.expect
index 10c2dbb..5ad2d40 100644
--- a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.expect
@@ -37,10 +37,7 @@
   return () → dynamic => self::Extension|instanceMethod(#this);
 static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
   return 42;
-static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
-  return #t1;
-}
+static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void {}
 static method main() → dynamic {
   invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
   Extension.instanceMethod();
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.transformed.expect
index 10c2dbb..5ad2d40 100644
--- a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.strong.transformed.expect
@@ -37,10 +37,7 @@
   return () → dynamic => self::Extension|instanceMethod(#this);
 static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
   return 42;
-static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
-  final dynamic #t1 = value;
-  return #t1;
-}
+static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void {}
 static method main() → dynamic {
   invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
   Extension.instanceMethod();
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
index ec79050..ee67c10 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
@@ -50,12 +50,10 @@
   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;
+static method _extension#0|set#property(final self::Class1* #this, core::int* value) → void {
   #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}");
@@ -73,12 +71,10 @@
   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;
+static method _extension#1|set#property(final self::Class2* #this, core::int* value) → void {
   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();
@@ -89,42 +85,42 @@
   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(1, let final self::Class1* #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|method(#t1));
   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(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t2));
+  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::_extension#0|set#property(#t3, #t4) in #t4);
   self::expect(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))));
+  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::_extension#0|set#property(#t6, #t7) in #t7);
+  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::_extension#0|set#property(#t11, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(#t9, #t10) in #t10);
+  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::_extension#0|set#property(#t17, #t18) in #t18 in let final void #t20 = self::_extension#0|set#property(#t15, #t16) in #t16);
+  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::_extension#0|set#property(#t25, #t26) in #t26 in let final void #t28 = self::_extension#0|set#property(#t23, #t24) in #t24 in let final void #t29 = self::_extension#0|set#property(#t21, #t22) in #t22);
+  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::_extension#0|set#property(#t34, #t35) in #t35 in let final void #t37 = self::_extension#0|set#property(#t32, #t33) in #t33 in let final void #t38 = self::_extension#0|set#property(#t30, #t31) in #t31);
 }
 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(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t39));
   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(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t40));
+  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::_extension#1|set#property(#t41, #t42) in #t42);
   self::expect(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(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::_extension#1|set#property(#t44, #t45) in #t45);
   self::expect(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))));
+  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::_extension#1|get#property(c1) in let final void #t49 = self::_extension#1|set#property(#t47, #t48) in #t48);
+  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::_extension#1|get#property(c0) in let final void #t52 = self::_extension#1|set#property(#t50, #t51) in #t51);
+  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::_extension#1|get#property(c1) in let final void #t57 = self::_extension#1|set#property(#t55, #t56) in #t56 in let final void #t58 = self::_extension#1|set#property(#t53, #t54) in #t54);
+  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::_extension#1|get#property(c0) in let final void #t63 = self::_extension#1|set#property(#t61, #t62) in #t62 in let final void #t64 = self::_extension#1|set#property(#t59, #t60) in #t60);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
index ec79050..ee67c10 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
@@ -50,12 +50,10 @@
   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;
+static method _extension#0|set#property(final self::Class1* #this, core::int* value) → void {
   #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}");
@@ -73,12 +71,10 @@
   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;
+static method _extension#1|set#property(final self::Class2* #this, core::int* value) → void {
   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();
@@ -89,42 +85,42 @@
   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(1, let final self::Class1* #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|method(#t1));
   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(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t2));
+  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::_extension#0|set#property(#t3, #t4) in #t4);
   self::expect(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))));
+  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::_extension#0|set#property(#t6, #t7) in #t7);
+  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::_extension#0|set#property(#t11, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(#t9, #t10) in #t10);
+  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::_extension#0|set#property(#t17, #t18) in #t18 in let final void #t20 = self::_extension#0|set#property(#t15, #t16) in #t16);
+  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::_extension#0|set#property(#t25, #t26) in #t26 in let final void #t28 = self::_extension#0|set#property(#t23, #t24) in #t24 in let final void #t29 = self::_extension#0|set#property(#t21, #t22) in #t22);
+  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::_extension#0|set#property(#t34, #t35) in #t35 in let final void #t37 = self::_extension#0|set#property(#t32, #t33) in #t33 in let final void #t38 = self::_extension#0|set#property(#t30, #t31) in #t31);
 }
 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(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t39));
   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(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t40));
+  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::_extension#1|set#property(#t41, #t42) in #t42);
   self::expect(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(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::_extension#1|set#property(#t44, #t45) in #t45);
   self::expect(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))));
+  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::_extension#1|get#property(c1) in let final void #t49 = self::_extension#1|set#property(#t47, #t48) in #t48);
+  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::_extension#1|get#property(c0) in let final void #t52 = self::_extension#1|set#property(#t50, #t51) in #t51);
+  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::_extension#1|get#property(c1) in let final void #t57 = self::_extension#1|set#property(#t55, #t56) in #t56 in let final void #t58 = self::_extension#1|set#property(#t53, #t54) in #t54);
+  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::_extension#1|get#property(c0) in let final void #t63 = self::_extension#1|set#property(#t61, #t62) in #t62 in let final void #t64 = self::_extension#1|set#property(#t59, #t60) in #t60);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/general/accessors.dart.strong.expect b/pkg/front_end/testcases/general/accessors.dart.strong.expect
index efe4a1c..1265410 100644
--- a/pkg/front_end/testcases/general/accessors.dart.strong.expect
+++ b/pkg/front_end/testcases/general/accessors.dart.strong.expect
@@ -2,20 +2,12 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
-//       print(onlySetter);
-//             ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
 //       print(onlySetter);
 //             ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
-//     print(onlySetter);
-//           ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
diff --git a/pkg/front_end/testcases/general/accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/general/accessors.dart.strong.transformed.expect
index efe4a1c..1265410 100644
--- a/pkg/front_end/testcases/general/accessors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/accessors.dart.strong.transformed.expect
@@ -2,20 +2,12 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
-//       print(onlySetter);
-//             ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
 //       print(onlySetter);
 //             ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
-//     print(onlySetter);
-//           ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
index 737b3a9..7949f03 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -113,8 +113,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef ContravariantUse<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef InvariantUse<T extends core::Object* = dynamic> = (T*) →* T*;
+typedef ContravariantUse<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef InvariantUse<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 class Empty extends core::Object {
   synthetic constructor •() → self::Empty*
     ;
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
index 133519d..efccee2 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -113,8 +113,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef ContravariantUse<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef InvariantUse<T extends core::Object* = dynamic> = (T*) →* T*;
+typedef ContravariantUse<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef InvariantUse<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 class Empty extends core::Object {
   synthetic constructor •() → self::Empty*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index cf5fe36..8a0566b 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -113,8 +113,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef ContravariantUse<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef InvariantUse<T extends core::Object* = dynamic> = (T*) →* T*;
+typedef ContravariantUse<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef InvariantUse<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 class Empty extends core::Object {
   synthetic constructor •() → self::Empty*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/bug32629.dart.outline.expect b/pkg/front_end/testcases/general/bug32629.dart.outline.expect
index 742088c..4c03145 100644
--- a/pkg/front_end/testcases/general/bug32629.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug32629.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Reducer<S extends core::Object* = dynamic> = (S*, dynamic) →* S*;
+typedef Reducer<invariant S extends core::Object* = dynamic> = (S*, dynamic) →* S*;
 class A extends core::Object {
   synthetic constructor •() → self::A*
     ;
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 a7c5eb0..c0c603a 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<dynamic, core::Null?>* map12 = <dynamic, 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<dynamic, core::Null?>* map13 = <dynamic, 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 5cc5798..27878cb 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<dynamic, core::Null?>* map12 = <dynamic, 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<dynamic, core::Null?>* map13 = <dynamic, 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.outline.expect b/pkg/front_end/testcases/general/covariant_generic.dart.outline.expect
index a516d86..830c5bd 100644
--- a/pkg/front_end/testcases/general/covariant_generic.dart.outline.expect
+++ b/pkg/front_end/testcases/general/covariant_generic.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Callback<T extends core::Object* = dynamic> = (T*) →* void;
+typedef Callback<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   final field self::Foo::T* finalField;
   final field (self::Foo::T*) →* void callbackField;
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 684ab99..d794499 100644
--- a/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Callback<T extends core::Object* = dynamic> = (T*) →* void;
+typedef Callback<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   final field self::Foo::T* finalField;
   final field (self::Foo::T*) →* void callbackField;
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 684ab99..d794499 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Callback<T extends core::Object* = dynamic> = (T*) →* void;
+typedef Callback<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   final field self::Foo::T* finalField;
   final field (self::Foo::T*) →* void callbackField;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart b/pkg/front_end/testcases/general/error_locations/error_location_05.dart
new file mode 100644
index 0000000..98a013d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library error_location_05;
+
+part 'error_location_05_lib1.dart';
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.outline.expect
new file mode 100644
index 0000000..ee7a72e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.outline.expect
@@ -0,0 +1,18 @@
+library error_location_05;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+import self as self;
+
+part error_location_05_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z, {dynamic z}) → dynamic
+  ;
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x2() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect
new file mode 100644
index 0000000..b4a23c0
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect
@@ -0,0 +1,30 @@
+library error_location_05;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:10:9: Error: 'z' is already declared in this scope.
+//   y(z, {z}) {}
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:10:5: Context: Previous declaration of 'z'.
+//   y(z, {z}) {}
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+part error_location_05_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x2() → dynamic {
+  function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect
new file mode 100644
index 0000000..b4a23c0
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library error_location_05;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:7:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:10:9: Error: 'z' is already declared in this scope.
+//   y(z, {z}) {}
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart:10:5: Context: Previous declaration of 'z'.
+//   y(z, {z}) {}
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+part error_location_05_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x2() → dynamic {
+  function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart b/pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart
new file mode 100644
index 0000000..f896142
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05_lib1.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of error_location_05;
+
+x1(z, {z}) {}
+
+x2() {
+  y(z, {z}) {}
+}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart b/pkg/front_end/testcases/general/error_locations/error_location_06.dart
new file mode 100644
index 0000000..b97ac23
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library error_location_06;
+
+part 'error_location_06_lib1.dart';
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.outline.expect
new file mode 100644
index 0000000..6f0dc86
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.outline.expect
@@ -0,0 +1,18 @@
+library error_location_06;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+import self as self;
+
+part error_location_06_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z, {dynamic z}) → dynamic
+  ;
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x2() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect
new file mode 100644
index 0000000..2d14468
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect
@@ -0,0 +1,30 @@
+library error_location_06;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:15:9: Error: 'z' is already declared in this scope.
+//   y(z, {z}) {}
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:15:5: Context: Previous declaration of 'z'.
+//   y(z, {z}) {}
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+part error_location_06_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x2() → dynamic {
+  function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect
new file mode 100644
index 0000000..2d14468
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library error_location_06;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:8: Error: Duplicated parameter name 'z'.
+// x1(z, {z}) {}
+//        ^
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:12:4: Context: Other parameter named 'z'.
+// x1(z, {z}) {}
+//    ^
+//
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:15:9: Error: 'z' is already declared in this scope.
+//   y(z, {z}) {}
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart:15:5: Context: Previous declaration of 'z'.
+//   y(z, {z}) {}
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+part error_location_06_lib1.dart;
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x2() → dynamic {
+  function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart b/pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart
new file mode 100644
index 0000000..47a8883
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06_lib1.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Lots of comment lines that pushes the length of this file beyond that of
+// error_location_06. This in turn causes the (first) 'z' in 'x2' to get an
+// offset that is larger than the largest valid offset in error_location_06.
+// This in turn can cause a crash, if the fileUri for that z is the wrong file.
+
+part of error_location_06;
+
+x1(z, {z}) {}
+
+x2() {
+  y(z, {z}) {}
+}
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
index 8e90b12..fe5752c 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
@@ -18,14 +18,6 @@
 //     for (c.untypedSuperInstanceField in []) {}
 //           ^
 //
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:37:10: Error: Setter not found: 'unresolved'.
-//     for (unresolved in []) {}
-//          ^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: Getter not found: 'unresolved'.
-//     for (unresolved.foo in []) {}
-//          ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:38:20: Error: Unexpected token '.'.
 //     for (unresolved.foo in []) {}
 //                    ^
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
index 8e90b12..fe5752c 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
@@ -18,14 +18,6 @@
 //     for (c.untypedSuperInstanceField in []) {}
 //           ^
 //
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:37:10: Error: Setter not found: 'unresolved'.
-//     for (unresolved in []) {}
-//          ^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: Getter not found: 'unresolved'.
-//     for (unresolved.foo in []) {}
-//          ^^^^^^^^^^
-//
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:38:20: Error: Unexpected token '.'.
 //     for (unresolved.foo in []) {}
 //                    ^
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
index 34b3c11..17ceeb6 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     ;
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
index ffb8e82..e612779 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
index ffb8e82..e612779 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
index 8432152..174bfb1 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     ;
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
index 7cca990..b21225c 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
index 7cca990..b21225c 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
index 2ddd767..61cb63d 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
@@ -21,7 +21,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     ;
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
index abbdcd7..3257f5f 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
@@ -21,7 +21,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
index abbdcd7..3257f5f 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
index c8bbb73..5454a33 100644
--- a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
@@ -2,125 +2,125 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
-//   foo() {}
-//   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
-//   foo([x]) {}
-//   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:21:7: Context: Override was introduced in the mixin application class 'A0'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:21:7: Error: The mixin application class 'A0' introduces an erroneous override of 'foo'.
 // class A0 = S with M;
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:22:7: Context: Override was introduced in the mixin application class 'A1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:22:7: Error: The mixin application class 'A1' introduces an erroneous override of 'foo'.
 // class A1 = S with M1, M;
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:23:7: Context: Override was introduced in the mixin application class 'A2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:23:7: Error: The mixin application class 'A2' introduces an erroneous override of 'foo'.
 // class A2 = S with M1, M2, M;
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:25:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:25:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class A0X = S with M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:26:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:26:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class A1X = S with M1, M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:27:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:27:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class A2X = S with M1, M2, M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:29:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:29:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class B0 extends S with M {}
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:31:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:31:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class B1 extends S with M1, M {}
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:33:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:33:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class B2 extends S with M1, M2, M {}
 //       ^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:35:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:35:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class B0X extends S with M, MX {}
 //       ^^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:37:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:37:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class B1X extends S with M1, M, MX {}
 //       ^^^
-//
-// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
 // pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/general/mixin_application_override.dart:39:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:39:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class B2X extends S with M1, M2, M, MX {}
 //       ^^^
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+//   foo() {}
+//   ^
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+//   foo([x]) {}
+//   ^
 //
 import self as self;
 import "dart:core" as core;
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 d13b4f3..d20dd45 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
@@ -120,9 +120,9 @@
         ^" in null;
   }
   {
-    dynamic x = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:41:15: Error: Can't declare 'T' because it was already used in this scope.
+    () →* core::Null? x = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:41:15: Error: Can't declare 'T' because it was already used in this scope.
     var x = T T() {};
-              ^" in let final () →* self::T* T = () → self::T* {} in T;
+              ^" in let final () →* core::Null? T = () → core::Null? {} in T;
   }
   {
     self::V* V = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:47:7: Error: Can't declare 'V' because it was already used in this scope.
@@ -130,9 +130,9 @@
       ^" as{TypeError} self::V*;
   }
   {
-    dynamic x = let final dynamic #t3 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
+    <T extends core::Object* = dynamic>() →* core::Null? x = let final dynamic #t3 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
     var x = T<T>() {};
-            ^" in let final <T extends core::Object* = dynamic>() →* dynamic T = <T extends core::Object* = dynamic>() → dynamic {} in T;
+            ^" in let final <T extends core::Object* = dynamic>() →* core::Null? T = <T extends core::Object* = dynamic>() → core::Null? {} in T;
   }
   {
     self::T* t;
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 d13b4f3..d20dd45 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
@@ -120,9 +120,9 @@
         ^" in null;
   }
   {
-    dynamic x = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:41:15: Error: Can't declare 'T' because it was already used in this scope.
+    () →* core::Null? x = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:41:15: Error: Can't declare 'T' because it was already used in this scope.
     var x = T T() {};
-              ^" in let final () →* self::T* T = () → self::T* {} in T;
+              ^" in let final () →* core::Null? T = () → core::Null? {} in T;
   }
   {
     self::V* V = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:47:7: Error: Can't declare 'V' because it was already used in this scope.
@@ -130,9 +130,9 @@
       ^" as{TypeError} self::V*;
   }
   {
-    dynamic x = let final dynamic #t3 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
+    <T extends core::Object* = dynamic>() →* core::Null? x = let final dynamic #t3 = invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
     var x = T<T>() {};
-            ^" in let final <T extends core::Object* = dynamic>() →* dynamic T = <T extends core::Object* = dynamic>() → dynamic {} in T;
+            ^" in let final <T extends core::Object* = dynamic>() →* core::Null? T = <T extends core::Object* = dynamic>() → core::Null? {} in T;
   }
   {
     self::T* t;
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 8410392..d2551c7 100644
--- a/pkg/front_end/testcases/general/null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/general/null_aware.dart.strong.expect
@@ -15,8 +15,8 @@
   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;
-  let final self::Foo* #t3 = foo in #t3.==(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
+  let final self::Foo* #t3 = foo in #t3.{core::Object::==}(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
   self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
-  core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int*} 6 : #t4;
-  core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num*} 4.5 : #t5;
+  core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.{core::num::==}(null) ?{core::int*} 6 : #t4;
+  core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.{core::num::==}(null) ?{core::num*} 4.5 : #t5;
 }
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 8410392..d2551c7 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
@@ -15,8 +15,8 @@
   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;
-  let final self::Foo* #t3 = foo in #t3.==(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
+  let final self::Foo* #t3 = foo in #t3.{core::Object::==}(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
   self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
-  core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int*} 6 : #t4;
-  core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num*} 4.5 : #t5;
+  core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.{core::num::==}(null) ?{core::int*} 6 : #t4;
+  core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.{core::num::==}(null) ?{core::num*} 4.5 : #t5;
 }
diff --git a/pkg/front_end/testcases/general/null_aware_postfix.dart b/pkg/front_end/testcases/general/null_aware_postfix.dart
new file mode 100644
index 0000000..e468e8f
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_postfix.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 {
+  B b;
+}
+
+class B {
+  C operator +(int i) => null;
+}
+
+class C extends B {}
+
+main() {
+  A a;
+  a?.b++;
+  C c = a?.b++;
+}
diff --git a/pkg/front_end/testcases/general/null_aware_postfix.dart.outline.expect b/pkg/front_end/testcases/general/null_aware_postfix.dart.outline.expect
new file mode 100644
index 0000000..89edf56
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_postfix.dart.outline.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B* b;
+  synthetic constructor •() → self::A*
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    ;
+  operator +(core::int* i) → self::C*
+    ;
+}
+class C extends self::B {
+  synthetic constructor •() → self::C*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.expect b/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.expect
new file mode 100644
index 0000000..594d81b
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B* b = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  operator +(core::int* i) → self::C*
+    return null;
+}
+class C extends self::B {
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {
+  self::A* a;
+  let final self::A* #t1 = a in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::A::b} = #t1.{self::A::b}.{self::B::+}(1);
+  self::C* c = (let final self::A* #t2 = a in #t2.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t3 = #t2.{self::A::b} in let final void #t4 = #t2.{self::A::b} = #t3.{self::B::+}(1) in #t3) as{TypeError} self::C*;
+}
diff --git a/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.transformed.expect
new file mode 100644
index 0000000..594d81b
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_postfix.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B* b = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  operator +(core::int* i) → self::C*
+    return null;
+}
+class C extends self::B {
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {
+  self::A* a;
+  let final self::A* #t1 = a in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::A::b} = #t1.{self::A::b}.{self::B::+}(1);
+  self::C* c = (let final self::A* #t2 = a in #t2.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t3 = #t2.{self::A::b} in let final void #t4 = #t2.{self::A::b} = #t3.{self::B::+}(1) in #t3) as{TypeError} self::C*;
+}
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
index abcb6aa..d8a8994 100644
--- 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
@@ -7,7 +7,6 @@
 # the same.
 
 type: newworld
-strong: true
 modules:
   module:
     module/a.dart: |
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
index a4a6cd9..c4dc3df 100644
--- 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
@@ -7,7 +7,6 @@
 # the same.
 
 type: newworld
-strong: true
 modules:
   module:
     module/a.dart: |
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
index 4f4762e..19a5268 100644
--- 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
@@ -6,7 +6,6 @@
 # which - if loaded - pulls in more of itself.
 
 type: newworld
-strong: true
 modules:
   module:
     module/a.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml
new file mode 100644
index 0000000..f7261a4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml
@@ -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.md file.
+
+# Reproduction fo https://github.com/flutter/flutter/issues/40966.
+
+type: newworld
+target: None
+modules:
+  module:
+    module/a.dart: |
+      class A { }
+      class B { }
+      class C { }
+      class AB = A with B;
+    module/.packages: |
+      module:.
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "package:module/a.dart";
+        class ABC = AB with C;
+      .packages: |
+        module:module
+    modules:
+      - module
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml
index 6869e85..d19784b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml
@@ -7,7 +7,6 @@
 # dill libraries.
 
 type: newworld
-strong: true
 modules:
   moduleB:
     moduleB/b.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml
index 449b319..02e89d3 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml
@@ -7,7 +7,6 @@
 # dill libraries.
 
 type: newworld
-strong: true
 modules:
   moduleB:
     moduleB/b.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml
index 89367ec..84cb4d7 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml
@@ -7,7 +7,6 @@
 # dill libraries.
 
 type: newworld
-strong: true
 modules:
   moduleB:
     moduleB/b.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml
index 3ad421d..07c9b1c 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml
@@ -7,7 +7,6 @@
 # dill libraries.
 
 type: newworld
-strong: true
 modules:
   module:
     module/lib1.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml
index dbe8c91..2e2d653 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml
@@ -7,7 +7,6 @@
 # dill libraries.
 
 type: newworld
-strong: true
 modules:
   module:
     module/lib1.dart: |
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
index 03cc5bd..2a4d912 100644
--- 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
@@ -7,7 +7,6 @@
 # the same.
 
 type: newworld
-strong: true
 modules:
   moduleA:
     moduleA/a.dart: |
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml
index 404e5a5..10b94fd 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml
@@ -5,7 +5,6 @@
 # This have crashed at one point (assertion error).
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml
index 0ecda031..3a869c5 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml
@@ -10,7 +10,6 @@
 # Fix both and the error should go away.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml
index 4c8455b..76e71de 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml
@@ -8,7 +8,6 @@
 # Fixing that should fix everything.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml
index 79727eb..309b436 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml
@@ -7,7 +7,6 @@
 # we keep getting errors. Once we fix it, we no longer get errors.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml
index 1b18f5c..20ae3a1 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml
@@ -7,7 +7,6 @@
 # we keep getting errors. Once we fix it, we no longer get errors.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml
index 9e1b824..3eb0124 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml
@@ -8,7 +8,6 @@
 # Remove said file again and the error should go away.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml
index c8ec3fa..308cc60 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml
@@ -9,7 +9,6 @@
 # Any references to the constant shouldn't matter in this regard.
 
 type: newworld
-strong: true
 worlds:
   - entry: main.dart
     sources:
diff --git a/pkg/front_end/testcases/inference/bug30624.dart b/pkg/front_end/testcases/inference/bug30624.dart
index 39f822e..58f7c33 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart
+++ b/pkg/front_end/testcases/inference/bug30624.dart
@@ -9,20 +9,21 @@
 
 class C<E> {
   void barA([int cmp(E a, E b)]) {
-    /*@ typeArgs=C::E* */ foo(this, cmp ?? _default);
+    /*@ typeArgs=C::E* */ foo(this, cmp /*@ target=Object::== */ ?? _default);
   }
 
   void barB([int cmp(E a, E b)]) {
-    /*@ typeArgs=C::E* */ foo(this, cmp ?? (_default as int Function(E, E)));
+    /*@ typeArgs=C::E* */ foo(
+        this, cmp /*@ target=Object::== */ ?? (_default as int Function(E, E)));
   }
 
   void barC([int cmp(E a, E b)]) {
     int Function(E, E) v = _default;
-    /*@ typeArgs=C::E* */ foo(this, cmp ?? v);
+    /*@ typeArgs=C::E* */ foo(this, cmp /*@ target=Object::== */ ?? v);
   }
 
   void barD([int cmp(E a, E b)]) {
-    foo<E>(this, cmp ?? _default);
+    foo<E>(this, cmp /*@ target=Object::== */ ?? _default);
   }
 
   void barE([int cmp(E a, E b)]) {
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.strong.expect b/pkg/front_end/testcases/inference/bug30624.dart.strong.expect
index 5f1bb52..825e93c 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.strong.expect
@@ -7,17 +7,17 @@
     : super core::Object::•()
     ;
   method barA([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
   }
   method barB([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
   }
   method barC([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
     (self::C::E*, self::C::E*) →* core::int* v = #C2;
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
   }
   method barD([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
   }
   method barE([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
     self::foo<self::C::E*>(this, cmp.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : cmp);
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
index 5f1bb52..825e93c 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
@@ -7,17 +7,17 @@
     : super core::Object::•()
     ;
   method barA([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
   }
   method barB([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
   }
   method barC([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
     (self::C::E*, self::C::E*) →* core::int* v = #C2;
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
   }
   method barD([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
-    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
+    self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
   }
   method barE([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
     self::foo<self::C::E*>(this, cmp.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : cmp);
diff --git a/pkg/front_end/testcases/inference/bug32291.dart b/pkg/front_end/testcases/inference/bug32291.dart
index e325f33..08ea27f 100644
--- a/pkg/front_end/testcases/inference/bug32291.dart
+++ b/pkg/front_end/testcases/inference/bug32291.dart
@@ -12,7 +12,7 @@
   var /*@ type=Iterable<List<String*>*>* */ i1 =
       l. /*@target=Iterable::map*/ /*@ typeArgs=List<String*>* */ map(
           /*@ returnType=List<String*>* */ (/*@ type=List<String*>* */ ll) =>
-              ll ?? /*@ typeArgs=String* */ []);
+              ll /*@ target=List::== */ ?? /*@ typeArgs=String* */ []);
   var /*@ type=Iterable<int*>* */ i2 =
       i1. /*@target=Iterable::map*/ /*@ typeArgs=int* */ map(
           /*@ returnType=int* */ (List<String> l) =>
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.strong.expect b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
index 6c30ca4..b8775a7 100644
--- a/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
@@ -4,7 +4,7 @@
 
 static method main() → void {
   core::List<core::List<core::String*>*>* l = <core::List<core::String*>*>[<core::String*>["hi", "world"]];
-  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.==(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
+  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
   core::Iterable<core::int*>* i2 = i1.{core::Iterable::map}<core::int*>((core::List<core::String*>* l) → core::int* => l.{core::List::length});
   core::print(i2);
 }
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
index 6c30ca4..b8775a7 100644
--- a/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 
 static method main() → void {
   core::List<core::List<core::String*>*>* l = <core::List<core::String*>*>[<core::String*>["hi", "world"]];
-  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.==(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
+  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
   core::Iterable<core::int*>* i2 = i1.{core::Iterable::map}<core::int*>((core::List<core::String*>* l) → core::int* => l.{core::List::length});
   core::print(i2);
 }
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.outline.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.outline.expect
index 5df14ed..3801c07 100644
--- a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 class A<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field (self::A::T*) →* self::A::T* x;
   constructor •((self::A::T*) →* self::A::T* x) → self::A<self::A::T*>*
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.expect
index 53daa23..7655fcc 100644
--- a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 class A<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field (self::A::T*) →* self::A::T* x;
   constructor •((self::A::T*) →* self::A::T* x) → self::A<self::A::T*>*
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
index 53daa23..7655fcc 100644
--- a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 class A<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field (self::A::T*) →* self::A::T* x;
   constructor •((self::A::T*) →* self::A::T* x) → self::A<self::A::T*>*
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
index 38a6f9a..74ed489 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = () →* void;
+typedef F<unrelated T extends core::Object* = dynamic> = () →* void;
 class Foo extends core::Object {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.outline.expect
index e0a7edc..2f4353d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
 class Foo extends core::Object {
   field core::List<core::int*>* x;
   constructor •([core::List<core::int*>* x]) → self::Foo*
diff --git a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.expect
index ae4583b..2cfdda7 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
 class Foo extends core::Object {
   field core::List<core::int*>* x;
   constructor •([core::List<core::int*>* x = #C2]) → self::Foo*
diff --git a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.transformed.expect
index ae4583b..2cfdda7 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = ([S*]) →* T*;
 class Foo extends core::Object {
   field core::List<core::int*>* x;
   constructor •([core::List<core::int*>* x = #C2]) → self::Foo*
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.outline.expect
index 3539aa7..86b1ec1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 static method test() → void
   ;
 static method main() → dynamic
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 7c74d42..e7f54af 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
@@ -61,7 +61,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant 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;
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 7c74d42..e7f54af 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
@@ -61,7 +61,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
+typedef Function2<contravariant 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;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
index 57c5b68..2fc00f4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Asserter<T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
 class DartType extends core::Object {
   synthetic constructor •() → self::DartType*
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
index ca17455..43326c3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Asserter<T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
 class DartType extends core::Object {
   synthetic constructor •() → self::DartType*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
index ca17455..43326c3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Asserter<T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
 class DartType extends core::Object {
   synthetic constructor •() → self::DartType*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart b/pkg/front_end/testcases/inference/future_then_ifNull.dart
index 2246903..d84927f 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart
@@ -18,18 +18,20 @@
   MyFuture<int> f;
   Future<int> t1 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
       /*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async =>
-          x ?? await new Future<int>.value(3));
+          x /*@ target=num::== */ ?? await new Future<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
       /*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async {
-    return /*info:DOWN_CAST_COMPOSITE*/ await x ?? new Future<int>.value(3);
+    return /*info:DOWN_CAST_COMPOSITE*/ await x /*@ target=num::== */ ??
+        new Future<int>.value(3);
   });
   Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
       /*error:INVALID_CAST_FUNCTION_EXPR*/
       /*@ returnType=FutureOr<int*>* */ (/*@ type=int* */ x) =>
-          x ?? new Future<int>.value(3));
+          x /*@ target=num::== */ ?? new Future<int>.value(3));
   Future<int> t6 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
       /*@ returnType=FutureOr<int*>* */ (/*@ type=int* */ x) {
-    return /*info:DOWN_CAST_COMPOSITE*/ x ?? new Future<int>.value(3);
+    return /*info:DOWN_CAST_COMPOSITE*/ x /*@ target=num::== */ ??
+        new Future<int>.value(3);
   });
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
index 000016c..0bec8e6 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
@@ -25,13 +25,13 @@
 }
 static method test() → void {
   self::MyFuture<core::int*>* f;
-  asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async => let final core::int* #t1 = x in #t1.==(null) ?{core::int*} await asy::Future::value<core::int*>(3) : #t1);
+  asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async => let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::int*} await asy::Future::value<core::int*>(3) : #t1);
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async {
-    return (let final core::int* #t2 = await x in #t2.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t2) as{TypeError} asy::FutureOr<core::int*>*;
+    return (let final core::int* #t2 = await x in #t2.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t2) as{TypeError} asy::FutureOr<core::int*>*;
   });
-  asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t3 = x in #t3.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t3) as{TypeError} asy::FutureOr<core::int*>*);
+  asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t3 = x in #t3.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t3) as{TypeError} asy::FutureOr<core::int*>*);
   asy::Future<core::int*>* t6 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* {
-    return (let final core::int* #t4 = x in #t4.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
+    return (let final core::int* #t4 = x in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index ce5d23f1..49ce857 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
         #L1:
         {
           final core::int* #t1 = x;
-          if(#t1.==(null)) {
+          if(#t1.{core::num::==}(null)) {
             [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = :result;
           }
@@ -76,7 +76,7 @@
         #L2:
         {
           [yield] let dynamic #t3 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = (let final core::int* #t4 = :result in #t4.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
+          :return_value = (let final core::int* #t4 = :result in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -91,9 +91,9 @@
     :async_completer.start(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t5 = x in #t5.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t5) as{TypeError} asy::FutureOr<core::int*>*);
+  asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t5 = x in #t5.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t5) as{TypeError} asy::FutureOr<core::int*>*);
   asy::Future<core::int*>* t6 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* {
-    return (let final core::int* #t6 = x in #t6.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t6) as{TypeError} asy::FutureOr<core::int*>*;
+    return (let final core::int* #t6 = x in #t6.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t6) as{TypeError} asy::FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.outline.expect b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.outline.expect
index c410a31..3a0416f 100644
--- a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.outline.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef ToValue<T extends core::Object* = dynamic> = (T*) →* void;
+typedef ToValue<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.outline.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.outline.expect
index 465372c..c2f4469 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<V extends core::Object* = dynamic> = (V*) →* void;
+typedef F<contravariant V extends core::Object* = dynamic> = (V*) →* void;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
index f47805d..abcd1fc 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<V extends core::Object* = dynamic> = (V*) →* void;
+typedef F<contravariant V extends core::Object* = dynamic> = (V*) →* void;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.transformed.expect
index f47805d..abcd1fc 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<V extends core::Object* = dynamic> = (V*) →* void;
+typedef F<contravariant V extends core::Object* = dynamic> = (V*) →* void;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
index cd56022..4c088aa 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
index bd37b92..90e061b 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
index bd37b92..90e061b 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart
index 68a2344..6d7ebaa 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart
@@ -7,7 +7,8 @@
 
 abstract class C<E> {
   void sort([int compare(E a, E b)]) {
-    /*@ typeArgs=C::E* */ sort2(this, compare ?? _compareAny);
+    /*@ typeArgs=C::E* */ sort2(
+        this, compare /*@ target=Object::== */ ?? _compareAny);
   }
 
   static int _compareAny(a, b) {
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.expect
index d7c1006..c6a9ba8 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method sort([(self::C::E*, self::C::E*) →* core::int* compare = #C1]) → void {
-    self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
+    self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
   }
   static method _compareAny(dynamic a, dynamic b) → core::int* {
     throw "unimplemented";
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.transformed.expect
index d7c1006..c6a9ba8 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method sort([(self::C::E*, self::C::E*) →* core::int* compare = #C1]) → void {
-    self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
+    self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
   }
   static method _compareAny(dynamic a, dynamic b) → core::int* {
     throw "unimplemented";
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 118957d..4973261 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
@@ -27,15 +27,20 @@
     /*@target=Test::member*/ /*@target=Test::member*/ member
         /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
 
-    /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
 
-    /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
 
-    /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
 
-    -- /*@target=Test::member*/ member;
+    /*@ target=B::- */ -- /*@target=Test::member*/ /*@target=Test::member*/
+        member;
 
-    /*@target=Test::member*/ member--;
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
 
     var /*@ type=B* */ v1 = /*@target=Test::member*/ member =
         /*@ typeArgs=B* */ f();
@@ -43,15 +48,24 @@
     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=A* */ v3 = /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ target=B::+ */ +=
+            /*@ typeArgs=C* */ f();
 
-    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &=
-        /*@ typeArgs=dynamic */ f();
+    var /*@ type=B* */ v4 = /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ target=B::* */ *=
+            /*@ typeArgs=B* */ f();
 
-    var /*@ type=B* */ v6 = -- /*@target=Test::member*/ member;
+    var /*@ type=C* */ v5 = /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ target=B::& */ &=
+            /*@ typeArgs=A* */ f();
 
-    var /*@ type=B* */ v7 = /*@target=Test::member*/ member--;
+    var /*@ type=B* */ v6 = /*@ target=B::- */ --
+        /*@target=Test::member*/ /*@target=Test::member*/ member;
+
+    var /*@ type=B* */ v7 =
+        /*@ type=B* */ /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ type=B* */ /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.expect
index 41cf1f1..043ccf2 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.expect
@@ -33,15 +33,16 @@
   method test() → void {
     this.{self::Test::member} = self::f<self::B*>();
     this.{self::Test::member}.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : null;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = this.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = this.{self::Test::member} in #t1.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : #t1;
-    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = this.{self::Test::member} in let final self::B* #t3 = this.{self::Test::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.transformed.expect
index 41cf1f1..043ccf2 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.strong.transformed.expect
@@ -33,15 +33,16 @@
   method test() → void {
     this.{self::Test::member} = self::f<self::B*>();
     this.{self::Test::member}.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : null;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = this.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = this.{self::Test::member} in #t1.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : #t1;
-    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = this.{self::Test::member} in let final self::B* #t3 = this.{self::Test::member} = #t2.{self::B::-}(1) in #t2;
   }
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 0f111a2..25db588 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
@@ -18,11 +18,15 @@
     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* */ v7 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::+ */ += getInt();
 
-    var /*@ type=int* */ v10 = ++ /*@target=Test1::t*/ t;
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++
+        /*@target=Test1::t*/ /*@target=Test1::t*/ t;
 
-    var /*@ type=int* */ v11 = /*@target=Test1::t*/ t++;
+    var /*@ type=int* */ v11 =
+        /*@ type=int* */ /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -45,15 +49,21 @@
     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* */ v7 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getInt();
 
-    var /*@ type=num* */ v8 = /*@target=Test2::t*/ t += getNum();
+    var /*@ type=num* */ v8 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getNum();
 
-    var /*@ type=num* */ v9 = /*@target=Test2::t*/ t += getDouble();
+    var /*@ type=num* */ v9 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getDouble();
 
-    var /*@ type=num* */ v10 = ++ /*@target=Test2::t*/ t;
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++
+        /*@target=Test2::t*/ /*@target=Test2::t*/ t;
 
-    var /*@ type=num* */ v11 = /*@target=Test2::t*/ t++;
+    var /*@ type=num* */ v11 =
+        /*@ type=num* */ /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -66,15 +76,21 @@
     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* */ v7 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getInt();
 
-    var /*@ type=double* */ v8 = /*@target=Test3::t*/ t += getNum();
+    var /*@ type=double* */ v8 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getNum();
 
-    var /*@ type=double* */ v9 = /*@target=Test3::t*/ t += getDouble();
+    var /*@ type=double* */ v9 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getDouble();
 
-    var /*@ type=double* */ v10 = ++ /*@target=Test3::t*/ t;
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++
+        /*@target=Test3::t*/ /*@target=Test3::t*/ t;
 
-    var /*@ type=double* */ v11 = /*@target=Test3::t*/ t++;
+    var /*@ type=double* */ v11 =
+        /*@ type=double* */ /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
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 d344928..5fb409e 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
@@ -30,8 +30,8 @@
     t /*@target=Test::[]=*/ [
         /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
 
-    t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()]
-        /*@ target=Object::== */ /*@ target=Test::[]= */
+    t /*@target=Test::[]*/ /*@ target=Test::[]= */ [/*@ typeArgs=Index* */ f()]
+        /*@ target=Object::== */
         ??= /*@ typeArgs=B* */ f();
 
     t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
@@ -54,9 +54,9 @@
     var /*@ type=B* */ v1 = t /*@target=Test::[]=*/ [
         /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
 
-    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ [
+    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ /*@ target=Test::[]= */ [
             /*@ typeArgs=Index* */ f()]
-        /*@ target=Object::== */ /*@ target=Test::[]= */
+        /*@ target=Object::== */
         ??= /*@ typeArgs=B* */ f();
 
     var /*@ type=B* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart
index 0d41509..838656d 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart
@@ -28,29 +28,56 @@
 class Test extends Base {
   void test() {
     super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=Object::== */
+        ??= /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ --super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        [/*@ typeArgs=Index* */ f()];
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        [/*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v4 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 =
-        --super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 =
-        super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=Object::== */
+        ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    var /*@ type=B* */ v4 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = /*@ target=B::- */ --super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 = super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.expect
index 88446ef..6386cbd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.expect
@@ -43,19 +43,20 @@
     : super self::Base::•()
     ;
   method test() → void {
-    super.{self::Base::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in super.{self::Base::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = super.{self::Base::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in super.{self::Base::[]=}(#t4 as{TypeError} self::Index*, super.{self::Base::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in super.{self::Base::[]=}(#t5 as{TypeError} self::Index*, super.{self::Base::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in super.{self::Base::[]=}(#t6 as{TypeError} self::Index*, super.{self::Base::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = super.{self::Base::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = super.{self::Base::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in super.{self::Base::[]=}(#t10 as{TypeError} self::Index*, super.{self::Base::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = super.{self::Base::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = super.{self::Base::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = super.{self::Base::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::B* v4 = let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = super.{self::Base::[]}(#t18 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t20 = super.{self::Base::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::C* v5 = let final dynamic #t21 = self::f<dynamic>() in let final self::C* #t22 = super.{self::Base::[]}(#t21 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t23 = super.{self::Base::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::B* v6 = let final dynamic #t24 = self::f<dynamic>() in let final self::B* #t25 = super.{self::Base::[]}(#t24 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t26 = super.{self::Base::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v7 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = super.{self::Base::[]}(#t27 as{TypeError} self::Index*) in let final void #t29 = super.{self::Base::[]=}(#t27 as{TypeError} self::Index*, #t28.{self::B::-}(1)) in #t28;
+    super.{self::Base::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in super.{self::Base::[]}(#t1).{core::Object::==}(null) ?{self::B*} super.{self::Base::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in super.{self::Base::[]=}(#t2, super.{self::Base::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in super.{self::Base::[]=}(#t3, super.{self::Base::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in super.{self::Base::[]=}(#t4, super.{self::Base::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = super.{self::Base::[]}(#t5).{self::B::-}(1) in let final void #t7 = super.{self::Base::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in super.{self::Base::[]=}(#t8, super.{self::Base::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = super.{self::Base::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = super.{self::Base::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = super.{self::Base::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = super.{self::Base::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = super.{self::Base::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = super.{self::Base::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = super.{self::Base::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = super.{self::Base::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = super.{self::Base::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = super.{self::Base::[]}(#t25).{self::B::-}(1) in let final void #t27 = super.{self::Base::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = super.{self::Base::[]}(#t28) in let final void #t30 = super.{self::Base::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.transformed.expect
index 88446ef..6386cbd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.strong.transformed.expect
@@ -43,19 +43,20 @@
     : super self::Base::•()
     ;
   method test() → void {
-    super.{self::Base::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in super.{self::Base::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = super.{self::Base::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in super.{self::Base::[]=}(#t4 as{TypeError} self::Index*, super.{self::Base::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in super.{self::Base::[]=}(#t5 as{TypeError} self::Index*, super.{self::Base::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in super.{self::Base::[]=}(#t6 as{TypeError} self::Index*, super.{self::Base::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = super.{self::Base::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = super.{self::Base::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in super.{self::Base::[]=}(#t10 as{TypeError} self::Index*, super.{self::Base::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = super.{self::Base::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = super.{self::Base::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = super.{self::Base::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::B* v4 = let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = super.{self::Base::[]}(#t18 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t20 = super.{self::Base::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::C* v5 = let final dynamic #t21 = self::f<dynamic>() in let final self::C* #t22 = super.{self::Base::[]}(#t21 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t23 = super.{self::Base::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::B* v6 = let final dynamic #t24 = self::f<dynamic>() in let final self::B* #t25 = super.{self::Base::[]}(#t24 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t26 = super.{self::Base::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v7 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = super.{self::Base::[]}(#t27 as{TypeError} self::Index*) in let final void #t29 = super.{self::Base::[]=}(#t27 as{TypeError} self::Index*, #t28.{self::B::-}(1)) in #t28;
+    super.{self::Base::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in super.{self::Base::[]}(#t1).{core::Object::==}(null) ?{self::B*} super.{self::Base::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in super.{self::Base::[]=}(#t2, super.{self::Base::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in super.{self::Base::[]=}(#t3, super.{self::Base::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in super.{self::Base::[]=}(#t4, super.{self::Base::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = super.{self::Base::[]}(#t5).{self::B::-}(1) in let final void #t7 = super.{self::Base::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in super.{self::Base::[]=}(#t8, super.{self::Base::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = super.{self::Base::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = super.{self::Base::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = super.{self::Base::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = super.{self::Base::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = super.{self::Base::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = super.{self::Base::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = super.{self::Base::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = super.{self::Base::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = super.{self::Base::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = super.{self::Base::[]}(#t25).{self::B::-}(1) in let final void #t27 = super.{self::Base::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = super.{self::Base::[]}(#t28) in let final void #t30 = super.{self::Base::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart
index 539a43d..b2919a1 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart
@@ -26,29 +26,55 @@
 
   void test() {
     this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=Object::== */
+        ??= /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::+ */
+        += /*@ typeArgs=C* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::* */
+        *= /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::& */
+        &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ --this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v4 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 =
-        --this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 =
-        this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=Object::== */
+        ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v4 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::+ */
+        += /*@ typeArgs=C* */ f();
+
+    var /*@ type=B* */ v3 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::* */
+        *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()] /*@ target=B::& */
+        &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = /*@ target=B::- */ --this
+        /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
index cc540e8..116991f 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
@@ -38,19 +38,20 @@
     return null;
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
-    this.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in this.{self::Test::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = this.{self::Test::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in this.{self::Test::[]=}(#t4 as{TypeError} self::Index*, this.{self::Test::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in this.{self::Test::[]=}(#t5 as{TypeError} self::Index*, this.{self::Test::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in this.{self::Test::[]=}(#t6 as{TypeError} self::Index*, this.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = this.{self::Test::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = this.{self::Test::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in this.{self::Test::[]=}(#t10 as{TypeError} self::Index*, this.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = this.{self::Test::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = this.{self::Test::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = this.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::B* v4 = let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = this.{self::Test::[]}(#t18 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t20 = this.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::C* v5 = let final dynamic #t21 = self::f<dynamic>() in let final self::C* #t22 = this.{self::Test::[]}(#t21 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t23 = this.{self::Test::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::B* v6 = let final dynamic #t24 = self::f<dynamic>() in let final self::B* #t25 = this.{self::Test::[]}(#t24 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t26 = this.{self::Test::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v7 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = this.{self::Test::[]}(#t27 as{TypeError} self::Index*) in let final void #t29 = this.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28.{self::B::-}(1)) in #t28;
+    this.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in this.{self::Test::[]}(#t1).{core::Object::==}(null) ?{self::B*} this.{self::Test::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in this.{self::Test::[]=}(#t2, this.{self::Test::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in this.{self::Test::[]=}(#t3, this.{self::Test::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
+    self::A* v4 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
+    self::B* v3 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
+    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
+    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
+    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{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/infer_assign_to_index_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
index cc540e8..116991f 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
@@ -38,19 +38,20 @@
     return null;
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
-    this.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in this.{self::Test::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = this.{self::Test::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in this.{self::Test::[]=}(#t4 as{TypeError} self::Index*, this.{self::Test::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in this.{self::Test::[]=}(#t5 as{TypeError} self::Index*, this.{self::Test::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in this.{self::Test::[]=}(#t6 as{TypeError} self::Index*, this.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = this.{self::Test::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = this.{self::Test::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in this.{self::Test::[]=}(#t10 as{TypeError} self::Index*, this.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = this.{self::Test::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = this.{self::Test::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = this.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::B* v4 = let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = this.{self::Test::[]}(#t18 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t20 = this.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::C* v5 = let final dynamic #t21 = self::f<dynamic>() in let final self::C* #t22 = this.{self::Test::[]}(#t21 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t23 = this.{self::Test::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::B* v6 = let final dynamic #t24 = self::f<dynamic>() in let final self::B* #t25 = this.{self::Test::[]}(#t24 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t26 = this.{self::Test::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v7 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = this.{self::Test::[]}(#t27 as{TypeError} self::Index*) in let final void #t29 = this.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28.{self::B::-}(1)) in #t28;
+    this.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in this.{self::Test::[]}(#t1).{core::Object::==}(null) ?{self::B*} this.{self::Test::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in this.{self::Test::[]=}(#t2, this.{self::Test::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in this.{self::Test::[]=}(#t3, this.{self::Test::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
+    self::A* v4 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
+    self::B* v3 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
+    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
+    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
+    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{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/infer_assign_to_local.dart b/pkg/front_end/testcases/inference/infer_assign_to_local.dart
index ebc99ac..16eb415 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart
@@ -21,18 +21,32 @@
 void test() {
   B local;
   local = /*@ typeArgs=B* */ f();
-  local ??= /*@ typeArgs=B* */ f();
+
+  local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
   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* */ v2 =
+      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
   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::- */ --;
 }
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 e0dc7dd..cd4a8a3 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
@@ -1,42 +1,42 @@
 pkg/front_end/testcases/inference/infer_assign_to_local.dart:23:9: Context: Write to local@474
   local = /*@ typeArgs=B* */ f();
         ^
-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:28: Context: Write to local@474
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:25:34: Context: Write to local@474
+  local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+                                 ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:27: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:29: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:31: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:33: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:35: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:37: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:52: Context: Write to local@474
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:40:38: Context: Write to local@474
+      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+                                     ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:42: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:44: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:46: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:48: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
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:51: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 fef536a..8619d3b 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
@@ -11,33 +11,55 @@
 
 void test1(int t) {
   var /*@ type=int* */ v1 = t = getInt();
-  var /*@ type=int* */ v4 = t ??= getInt();
+
+  var /*@ type=int* */ v4 = t /*@target=num::==*/ ??= getInt();
+
   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::+*/ ++;
+
+  var /*@ type=int* */ v11 = /*@ type=int* */ t
+      /*@ type=int* */ /*@target=num::+*/ ++;
 }
 
 void test2(num t) {
   var /*@ type=int* */ v1 = t = getInt();
+
   var /*@ type=num* */ v2 = t = getNum();
+
   var /*@ type=double* */ v3 = t = getDouble();
-  var /*@ type=num* */ v4 = t ??= getInt();
-  var /*@ type=num* */ v5 = t ??= getNum();
-  var /*@ type=num* */ v6 = t ??= getDouble();
+
+  var /*@ type=num* */ v4 = t /*@target=num::==*/ ??= getInt();
+
+  var /*@ type=num* */ v5 = t /*@target=num::==*/ ??= getNum();
+
+  var /*@ type=num* */ v6 = t /*@target=num::==*/ ??= getDouble();
+
   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::+*/ ++;
+
+  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* */ v6 = t /*@target=num::==*/ ??= getDouble();
+
   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::+*/ ++;
 }
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 80ef25c..e4950d8 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
@@ -1,69 +1,69 @@
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:13:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
-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:50: Context: Write to t@343
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:15:51: Context: Write to t@343
+  var /*@ type=int* */ v4 = t /*@target=num::==*/ ??= getInt();
+                                                  ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:17: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:19: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:22:43: Context: Write to t@343
+      /*@ type=int* */ /*@target=num::+*/ ++;
+                                          ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:22:31: Context: Write to t@343
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:28:31: Context: Write to t@343
   var /*@ type=num* */ v2 = t = getNum();
                               ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:23:34: Context: Write to t@343
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:30:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:24:31: Context: Write to t@343
-  var /*@ type=num* */ v4 = t ??= getInt();
-                              ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:25:31: Context: Write to t@343
-  var /*@ type=num* */ v5 = t ??= getNum();
-                              ^^^
-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:50: Context: Write to t@343
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:32:51: Context: Write to t@343
+  var /*@ type=num* */ v4 = t /*@target=num::==*/ ??= getInt();
+                                                  ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:34:51: Context: Write to t@343
+  var /*@ type=num* */ v5 = t /*@target=num::==*/ ??= getNum();
+                                                  ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:36:51: Context: Write to t@343
+  var /*@ type=num* */ v6 = t /*@target=num::==*/ ??= getDouble();
+                                                  ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:38: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:40: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:42: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:44: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:47:43: Context: Write to t@343
+      /*@ type=num* */ /*@target=num::+*/ ++;
+                                          ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:51: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:56: Context: Write to t@343
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:53:54: Context: Write to t@343
+  var /*@ type=double* */ v6 = t /*@target=num::==*/ ??= getDouble();
+                                                     ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:55: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:57: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:59: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:61: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
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:64:49: Context: Write to t@343
       /*@ type=double* */ /*@target=double::+*/ ++;
                                                 ^^
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 55d9fb1..e28b42c 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
@@ -24,23 +24,62 @@
   static void test(Test t) {
     /*@ 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();
-    t?. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --t?. /*@target=Test::member*/ member;
-    t?. /*@target=Test::member*/ member--;
+
+    /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ -- /*@ target=Object::== */ t
+        ?. /*@target=Test::member*/ /*@target=Test::member*/ member;
+
+    /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 =
         /*@ type=Test* */ /*@target=Object::==*/ t?. /*@target=Test::member*/
             member = /*@ typeArgs=B* */ f();
+
     var /*@ type=B* */ v2 =
-        t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+        /*@ target=Object::== */ t
+                ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 =
+        /*@ target=Object::== */ 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();
+        /*@ target=Object::== */ 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--;
+        /*@ target=Object::== */ t
+                ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 =
+        /*@ target=B::- */ -- /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member;
+
+    var /*@ type=B* */ v7 =
+        /*@ target=Object::== */ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
   }
 }
 
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 6c00bcb4..60aa66d 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
@@ -32,18 +32,19 @@
     ;
   static method test(self::Test* t) → void {
     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.{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*);
-    self::B* v6 = let final self::Test* #t13 = t in #t13.==(null) ?{self::B*} null : #t13.{self::Test::member} = #t13.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t14 = t in #t14.==(null) ?{self::B*} null : let final self::B* #t15 = #t14.{self::Test::member} in let final self::B* #t16 = #t14.{self::Test::member} = #t15.{self::B::-}(1) in #t15;
+    let final self::Test* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t4 = t in #t4.{core::Object::==}(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t5 = t in #t5.{core::Object::==}(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    let final self::Test* #t6 = t in #t6.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t7 = #t6.{self::Test::member}.{self::B::-}(1) in let final void #t8 = #t6.{self::Test::member} = #t7 in #t7;
+    let final self::Test* #t9 = t in #t9.{core::Object::==}(null) ?{self::B*} null : #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::-}(1);
+    self::B* v1 = let final self::Test* #t10 = t in #t10.{core::Object::==}(null) ?{self::B*} null : #t10.{self::Test::member} = self::f<self::B*>();
+    self::B* v2 = let final self::Test* #t11 = t in #t11.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t12 = #t11.{self::Test::member} in #t12.{core::Object::==}(null) ?{self::B*} #t11.{self::Test::member} = self::f<self::B*>() : #t12;
+    self::A* v3 = let final self::Test* #t13 = t in #t13.{core::Object::==}(null) ?{self::A*} null : let final self::A* #t14 = #t13.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t15 = #t13.{self::Test::member} = #t14 in #t14;
+    self::B* v4 = let final self::Test* #t16 = t in #t16.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t17 = #t16.{self::Test::member}.{self::B::*}(self::f<self::B*>()) in let final void #t18 = #t16.{self::Test::member} = #t17 in #t17;
+    self::C* v5 = let final self::Test* #t19 = t in #t19.{core::Object::==}(null) ?{self::C*} null : let final self::C* #t20 = #t19.{self::Test::member}.{self::B::&}(self::f<self::A*>()) in let final void #t21 = #t19.{self::Test::member} = #t20 in #t20;
+    self::B* v6 = let final self::Test* #t22 = t in #t22.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t23 = #t22.{self::Test::member}.{self::B::-}(1) in let final void #t24 = #t22.{self::Test::member} = #t23 in #t23;
+    self::B* v7 = let final self::Test* #t25 = t in #t25.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t26 = #t25.{self::Test::member} in let final void #t27 = #t25.{self::Test::member} = #t26.{self::B::-}(1) in #t26;
   }
 }
 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.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.transformed.expect
index 6c00bcb4..60aa66d 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
@@ -32,18 +32,19 @@
     ;
   static method test(self::Test* t) → void {
     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.{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*);
-    self::B* v6 = let final self::Test* #t13 = t in #t13.==(null) ?{self::B*} null : #t13.{self::Test::member} = #t13.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t14 = t in #t14.==(null) ?{self::B*} null : let final self::B* #t15 = #t14.{self::Test::member} in let final self::B* #t16 = #t14.{self::Test::member} = #t15.{self::B::-}(1) in #t15;
+    let final self::Test* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t4 = t in #t4.{core::Object::==}(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t5 = t in #t5.{core::Object::==}(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    let final self::Test* #t6 = t in #t6.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t7 = #t6.{self::Test::member}.{self::B::-}(1) in let final void #t8 = #t6.{self::Test::member} = #t7 in #t7;
+    let final self::Test* #t9 = t in #t9.{core::Object::==}(null) ?{self::B*} null : #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::-}(1);
+    self::B* v1 = let final self::Test* #t10 = t in #t10.{core::Object::==}(null) ?{self::B*} null : #t10.{self::Test::member} = self::f<self::B*>();
+    self::B* v2 = let final self::Test* #t11 = t in #t11.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t12 = #t11.{self::Test::member} in #t12.{core::Object::==}(null) ?{self::B*} #t11.{self::Test::member} = self::f<self::B*>() : #t12;
+    self::A* v3 = let final self::Test* #t13 = t in #t13.{core::Object::==}(null) ?{self::A*} null : let final self::A* #t14 = #t13.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t15 = #t13.{self::Test::member} = #t14 in #t14;
+    self::B* v4 = let final self::Test* #t16 = t in #t16.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t17 = #t16.{self::Test::member}.{self::B::*}(self::f<self::B*>()) in let final void #t18 = #t16.{self::Test::member} = #t17 in #t17;
+    self::C* v5 = let final self::Test* #t19 = t in #t19.{core::Object::==}(null) ?{self::C*} null : let final self::C* #t20 = #t19.{self::Test::member}.{self::B::&}(self::f<self::A*>()) in let final void #t21 = #t19.{self::Test::member} = #t20 in #t20;
+    self::B* v6 = let final self::Test* #t22 = t in #t22.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t23 = #t22.{self::Test::member}.{self::B::-}(1) in let final void #t24 = #t22.{self::Test::member} = #t23 in #t23;
+    self::B* v7 = let final self::Test* #t25 = t in #t25.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t26 = #t25.{self::Test::member} in let final void #t27 = #t25.{self::Test::member} = #t26.{self::B::-}(1) in #t26;
   }
 }
 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_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart
index eab5036..6b4a521 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
@@ -15,10 +15,24 @@
   static void test(Test1 t) {
     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;
-    var /*@ type=int* */ v11 = t?. /*@target=Test1::prop*/ prop++;
+
+    var /*@ type=int* */ v4 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+            /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=int* */ v7 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+            /*@target=num::+*/ += getInt();
+
+    var /*@ type=int* */ v10 = /*@target=num::+*/ ++ /*@target=Object::==*/ t
+        ?. /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop;
+
+    var /*@ type=int* */ v11 =
+        /*@target=Object::==*/ t
+            ?. /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -28,18 +42,49 @@
   static void test(Test2 t) {
     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();
-    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 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v6 = /*@target=Object::==*/ t
+            ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=num* */ v7 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@target=num::+*/ += getNum();
+
+    var /*@ type=num* */ v9 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@target=num::+*/ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@target=num::+*/ ++ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop;
+
+    var /*@ type=num* */ v11 =
+        /*@target=Object::==*/ t
+            ?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -50,14 +95,35 @@
     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();
+        /*@target=Object::==*/ t?.
+                /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=double* */ v7 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@target=double::+*/ += getInt();
+
+    var /*@ type=double* */ v8 =
+        /*@target=Object::==*/ t
+                ?. /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@target=double::+*/ += 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++;
+        /*@target=Object::==*/ t?.
+                /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@target=double::+*/ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@target=double::+*/ ++
+        /*@target=Object::==*/ t
+            ?. /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop;
+
+    var /*@ type=double* */ v11 =
+        /*@target=Object::==*/ t
+            ?. /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@target=double::+*/ ++;
   }
 }
 
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 891b1bd..c7353f0 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
@@ -9,10 +9,10 @@
     ;
   static method test(self::Test1* t) → void {
     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);
-    core::int* v11 = let final self::Test1* #t6 = t in #t6.==(null) ?{core::int*} null : let final core::int* #t7 = #t6.{self::Test1::prop} in let final core::int* #t8 = #t6.{self::Test1::prop} = #t7.{core::num::+}(1) in #t7;
+    core::int* v4 = let final self::Test1* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t5 = #t4.{self::Test1::prop}.{core::num::+}(self::getInt()) in let final void #t6 = #t4.{self::Test1::prop} = #t5 in #t5;
+    core::int* v10 = let final self::Test1* #t7 = t in #t7.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t8 = #t7.{self::Test1::prop}.{core::num::+}(1) in let final void #t9 = #t7.{self::Test1::prop} = #t8 in #t8;
+    core::int* v11 = let final self::Test1* #t10 = t in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = #t10.{self::Test1::prop} in let final void #t12 = #t10.{self::Test1::prop} = #t11.{core::num::+}(1) in #t11;
   }
 }
 class Test2 extends core::Object {
@@ -21,17 +21,17 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    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;
-    core::num* v7 = let final self::Test2* #t18 = t in #t18.==(null) ?{core::num*} null : #t18.{self::Test2::prop} = #t18.{self::Test2::prop}.{core::num::+}(self::getInt());
-    core::num* v8 = let final self::Test2* #t19 = t in #t19.==(null) ?{core::num*} null : #t19.{self::Test2::prop} = #t19.{self::Test2::prop}.{core::num::+}(self::getNum());
-    core::num* v9 = let final self::Test2* #t20 = t in #t20.==(null) ?{core::num*} null : #t20.{self::Test2::prop} = #t20.{self::Test2::prop}.{core::num::+}(self::getDouble());
-    core::num* v10 = let final self::Test2* #t21 = t in #t21.==(null) ?{core::num*} null : #t21.{self::Test2::prop} = #t21.{self::Test2::prop}.{core::num::+}(1);
-    core::num* v11 = let final self::Test2* #t22 = t in #t22.==(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop} in let final core::num* #t24 = #t22.{self::Test2::prop} = #t23.{core::num::+}(1) in #t23;
+    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.{core::Object::==}(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.{core::Object::==}(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.{core::Object::==}(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;
+    core::num* v7 = let final self::Test2* #t22 = t in #t22.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop}.{core::num::+}(self::getInt()) in let final void #t24 = #t22.{self::Test2::prop} = #t23 in #t23;
+    core::num* v8 = let final self::Test2* #t25 = t in #t25.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t26 = #t25.{self::Test2::prop}.{core::num::+}(self::getNum()) in let final void #t27 = #t25.{self::Test2::prop} = #t26 in #t26;
+    core::num* v9 = let final self::Test2* #t28 = t in #t28.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t29 = #t28.{self::Test2::prop}.{core::num::+}(self::getDouble()) in let final void #t30 = #t28.{self::Test2::prop} = #t29 in #t29;
+    core::num* v10 = let final self::Test2* #t31 = t in #t31.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t32 = #t31.{self::Test2::prop}.{core::num::+}(1) in let final void #t33 = #t31.{self::Test2::prop} = #t32 in #t32;
+    core::num* v11 = let final self::Test2* #t34 = t in #t34.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t35 = #t34.{self::Test2::prop} in let final void #t36 = #t34.{self::Test2::prop} = #t35.{core::num::+}(1) in #t35;
   }
 }
 class Test3 extends core::Object {
@@ -40,13 +40,13 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    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());
-    core::double* v9 = let final self::Test3* #t30 = t in #t30.==(null) ?{core::double*} null : #t30.{self::Test3::prop} = #t30.{self::Test3::prop}.{core::double::+}(self::getDouble());
-    core::double* v10 = let final self::Test3* #t31 = t in #t31.==(null) ?{core::double*} null : #t31.{self::Test3::prop} = #t31.{self::Test3::prop}.{core::double::+}(1);
-    core::double* v11 = let final self::Test3* #t32 = t in #t32.==(null) ?{core::double*} null : let final core::double* #t33 = #t32.{self::Test3::prop} in let final core::double* #t34 = #t32.{self::Test3::prop} = #t33.{core::double::+}(1) in #t33;
+    core::double* v3 = let final self::Test3* #t37 = t in #t37.{core::Object::==}(null) ?{core::double*} null : #t37.{self::Test3::prop} = self::getDouble();
+    core::double* v6 = let final self::Test3* #t38 = t in #t38.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t39 = #t38.{self::Test3::prop} in #t39.{core::num::==}(null) ?{core::double*} #t38.{self::Test3::prop} = self::getDouble() : #t39;
+    core::double* v7 = let final self::Test3* #t40 = t in #t40.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t41 = #t40.{self::Test3::prop}.{core::double::+}(self::getInt()) in let final void #t42 = #t40.{self::Test3::prop} = #t41 in #t41;
+    core::double* v8 = let final self::Test3* #t43 = t in #t43.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t44 = #t43.{self::Test3::prop}.{core::double::+}(self::getNum()) in let final void #t45 = #t43.{self::Test3::prop} = #t44 in #t44;
+    core::double* v9 = let final self::Test3* #t46 = t in #t46.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t47 = #t46.{self::Test3::prop}.{core::double::+}(self::getDouble()) in let final void #t48 = #t46.{self::Test3::prop} = #t47 in #t47;
+    core::double* v10 = let final self::Test3* #t49 = t in #t49.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t50 = #t49.{self::Test3::prop}.{core::double::+}(1) in let final void #t51 = #t49.{self::Test3::prop} = #t50 in #t50;
+    core::double* v11 = let final self::Test3* #t52 = t in #t52.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t53 = #t52.{self::Test3::prop} in let final void #t54 = #t52.{self::Test3::prop} = #t53.{core::double::+}(1) in #t53;
   }
 }
 static method getInt() → core::int*
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 891b1bd..c7353f0 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
@@ -9,10 +9,10 @@
     ;
   static method test(self::Test1* t) → void {
     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);
-    core::int* v11 = let final self::Test1* #t6 = t in #t6.==(null) ?{core::int*} null : let final core::int* #t7 = #t6.{self::Test1::prop} in let final core::int* #t8 = #t6.{self::Test1::prop} = #t7.{core::num::+}(1) in #t7;
+    core::int* v4 = let final self::Test1* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t5 = #t4.{self::Test1::prop}.{core::num::+}(self::getInt()) in let final void #t6 = #t4.{self::Test1::prop} = #t5 in #t5;
+    core::int* v10 = let final self::Test1* #t7 = t in #t7.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t8 = #t7.{self::Test1::prop}.{core::num::+}(1) in let final void #t9 = #t7.{self::Test1::prop} = #t8 in #t8;
+    core::int* v11 = let final self::Test1* #t10 = t in #t10.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t11 = #t10.{self::Test1::prop} in let final void #t12 = #t10.{self::Test1::prop} = #t11.{core::num::+}(1) in #t11;
   }
 }
 class Test2 extends core::Object {
@@ -21,17 +21,17 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    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;
-    core::num* v7 = let final self::Test2* #t18 = t in #t18.==(null) ?{core::num*} null : #t18.{self::Test2::prop} = #t18.{self::Test2::prop}.{core::num::+}(self::getInt());
-    core::num* v8 = let final self::Test2* #t19 = t in #t19.==(null) ?{core::num*} null : #t19.{self::Test2::prop} = #t19.{self::Test2::prop}.{core::num::+}(self::getNum());
-    core::num* v9 = let final self::Test2* #t20 = t in #t20.==(null) ?{core::num*} null : #t20.{self::Test2::prop} = #t20.{self::Test2::prop}.{core::num::+}(self::getDouble());
-    core::num* v10 = let final self::Test2* #t21 = t in #t21.==(null) ?{core::num*} null : #t21.{self::Test2::prop} = #t21.{self::Test2::prop}.{core::num::+}(1);
-    core::num* v11 = let final self::Test2* #t22 = t in #t22.==(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop} in let final core::num* #t24 = #t22.{self::Test2::prop} = #t23.{core::num::+}(1) in #t23;
+    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.{core::Object::==}(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.{core::Object::==}(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.{core::Object::==}(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;
+    core::num* v7 = let final self::Test2* #t22 = t in #t22.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop}.{core::num::+}(self::getInt()) in let final void #t24 = #t22.{self::Test2::prop} = #t23 in #t23;
+    core::num* v8 = let final self::Test2* #t25 = t in #t25.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t26 = #t25.{self::Test2::prop}.{core::num::+}(self::getNum()) in let final void #t27 = #t25.{self::Test2::prop} = #t26 in #t26;
+    core::num* v9 = let final self::Test2* #t28 = t in #t28.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t29 = #t28.{self::Test2::prop}.{core::num::+}(self::getDouble()) in let final void #t30 = #t28.{self::Test2::prop} = #t29 in #t29;
+    core::num* v10 = let final self::Test2* #t31 = t in #t31.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t32 = #t31.{self::Test2::prop}.{core::num::+}(1) in let final void #t33 = #t31.{self::Test2::prop} = #t32 in #t32;
+    core::num* v11 = let final self::Test2* #t34 = t in #t34.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t35 = #t34.{self::Test2::prop} in let final void #t36 = #t34.{self::Test2::prop} = #t35.{core::num::+}(1) in #t35;
   }
 }
 class Test3 extends core::Object {
@@ -40,13 +40,13 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    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());
-    core::double* v9 = let final self::Test3* #t30 = t in #t30.==(null) ?{core::double*} null : #t30.{self::Test3::prop} = #t30.{self::Test3::prop}.{core::double::+}(self::getDouble());
-    core::double* v10 = let final self::Test3* #t31 = t in #t31.==(null) ?{core::double*} null : #t31.{self::Test3::prop} = #t31.{self::Test3::prop}.{core::double::+}(1);
-    core::double* v11 = let final self::Test3* #t32 = t in #t32.==(null) ?{core::double*} null : let final core::double* #t33 = #t32.{self::Test3::prop} in let final core::double* #t34 = #t32.{self::Test3::prop} = #t33.{core::double::+}(1) in #t33;
+    core::double* v3 = let final self::Test3* #t37 = t in #t37.{core::Object::==}(null) ?{core::double*} null : #t37.{self::Test3::prop} = self::getDouble();
+    core::double* v6 = let final self::Test3* #t38 = t in #t38.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t39 = #t38.{self::Test3::prop} in #t39.{core::num::==}(null) ?{core::double*} #t38.{self::Test3::prop} = self::getDouble() : #t39;
+    core::double* v7 = let final self::Test3* #t40 = t in #t40.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t41 = #t40.{self::Test3::prop}.{core::double::+}(self::getInt()) in let final void #t42 = #t40.{self::Test3::prop} = #t41 in #t41;
+    core::double* v8 = let final self::Test3* #t43 = t in #t43.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t44 = #t43.{self::Test3::prop}.{core::double::+}(self::getNum()) in let final void #t45 = #t43.{self::Test3::prop} = #t44 in #t44;
+    core::double* v9 = let final self::Test3* #t46 = t in #t46.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t47 = #t46.{self::Test3::prop}.{core::double::+}(self::getDouble()) in let final void #t48 = #t46.{self::Test3::prop} = #t47 in #t47;
+    core::double* v10 = let final self::Test3* #t49 = t in #t49.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t50 = #t49.{self::Test3::prop}.{core::double::+}(1) in let final void #t51 = #t49.{self::Test3::prop} = #t50 in #t50;
+    core::double* v11 = let final self::Test3* #t52 = t in #t52.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t53 = #t52.{self::Test3::prop} in let final void #t54 = #t52.{self::Test3::prop} = #t53.{core::double::+}(1) in #t53;
   }
 }
 static method getInt() → core::int*
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
index e56ff7a..1ce9cd4 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::T*>*
     ;
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
index 1124614..310bddf 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
index 1124614..310bddf 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart b/pkg/front_end/testcases/inference/null_coalescing_operator.dart
index ac55bb7..bbf853c 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator.dart
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator.dart
@@ -7,6 +7,7 @@
 
 main() {
   List<int> x;
-  var /*@ type=List<int*>* */ y = x ?? /*@ typeArgs=int* */ [];
+  var /*@ type=List<int*>* */ y =
+      x /*@ target=List::== */ ?? /*@ typeArgs=int* */ [];
   List<int> z = y;
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.expect b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.expect
index f2e6ea1..ec63329 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.expect
@@ -4,6 +4,6 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
+  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
   core::List<core::int*>* z = y;
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
index f2e6ea1..ec63329 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
@@ -4,6 +4,6 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
+  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
   core::List<core::int*>* z = y;
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart
index c8888a7..0836850 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart
@@ -7,5 +7,5 @@
 
 main() {
   List<int> x;
-  List<num> y = x ?? /*@ typeArgs=num* */ [];
+  List<num> y = x /*@ target=List::== */ ?? /*@ typeArgs=num* */ [];
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.expect b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.expect
index 1b28952..c4ca3fe 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.expect
@@ -4,5 +4,5 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
+  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
index 1b28952..c4ca3fe 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
@@ -4,5 +4,5 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
+  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
 }
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart
index e85b749..757a80f 100644
--- a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart
+++ b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart
@@ -15,9 +15,9 @@
   }
 
   void opEq(int b) {
-    /*@target=C::a*/ a += b;
-    /*@target=C::a*/ a -= b;
-    /*@target=C::a*/ a *= b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::+*/ += b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::-*/ -= b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::**/ *= b;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart
index 60ab287..17f1189 100644
--- a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart
+++ b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart
@@ -15,9 +15,9 @@
   }
 
   void opEq(T b) {
-    /*@target=C::a*/ a += b;
-    /*@target=C::a*/ a -= b;
-    /*@target=C::a*/ a *= b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::+*/ += b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::-*/ -= b;
+    /*@target=C::a*/ /*@target=C::a*/ a /*@target=num::**/ *= b;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/super_index_set.dart b/pkg/front_end/testcases/inference/super_index_set.dart
index 82ad78d..195028e 100644
--- a/pkg/front_end/testcases/inference/super_index_set.dart
+++ b/pkg/front_end/testcases/inference/super_index_set.dart
@@ -16,9 +16,8 @@
 class C extends B {
   void operator []=(Object x, Object y) {}
   void h() {
-    // Note: the index is inferred with an empty context due to issue 31336.
     super /*@target=B::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=String* */ f();
+        /*@ typeArgs=int* */ f()] = /*@ typeArgs=String* */ f();
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/super_index_set.dart.strong.expect b/pkg/front_end/testcases/inference/super_index_set.dart.strong.expect
index 7e58394..6683122 100644
--- a/pkg/front_end/testcases/inference/super_index_set.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/super_index_set.dart.strong.expect
@@ -16,7 +16,7 @@
     ;
   operator []=(core::Object* x, core::Object* y) → void {}
   method h() → void {
-    super.{self::B::[]=}(self::f<dynamic>() as{TypeError} core::int*, self::f<core::String*>());
+    super.{self::B::[]=}(self::f<core::int*>(), self::f<core::String*>());
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/super_index_set.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/super_index_set.dart.strong.transformed.expect
index 7e58394..6683122 100644
--- a/pkg/front_end/testcases/inference/super_index_set.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/super_index_set.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
     ;
   operator []=(core::Object* x, core::Object* y) → void {}
   method h() → void {
-    super.{self::B::[]=}(self::f<dynamic>() as{TypeError} core::int*, self::f<core::String*>());
+    super.{self::B::[]=}(self::f<core::int*>(), self::f<core::String*>());
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/super_index_set_substitution.dart b/pkg/front_end/testcases/inference/super_index_set_substitution.dart
index e686edc..f17da64 100644
--- a/pkg/front_end/testcases/inference/super_index_set_substitution.dart
+++ b/pkg/front_end/testcases/inference/super_index_set_substitution.dart
@@ -16,9 +16,9 @@
 class C<U> extends B<Future<U>> {
   void operator []=(Object x, Object y) {}
   void h() {
-    // Note: the index is inferred with an empty context due to issue 31336.
     super /*@target=B::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=List<Future<C::U*>*>* */ f();
+            /*@ typeArgs=Map<int*, Future<C::U*>*>* */ f()] =
+        /*@ typeArgs=List<Future<C::U*>*>* */ f();
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.expect b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.expect
index 7827c2f..6d2e13b 100644
--- a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.expect
@@ -17,7 +17,7 @@
     ;
   operator []=(generic-covariant-impl core::Object* x, generic-covariant-impl core::Object* y) → void {}
   method h() → void {
-    super.{self::B::[]=}(self::f<dynamic>() as{TypeError} core::Map<core::int*, asy::Future<self::C::U*>*>*, self::f<core::List<asy::Future<self::C::U*>*>*>());
+    super.{self::B::[]=}(self::f<core::Map<core::int*, asy::Future<self::C::U*>*>*>(), self::f<core::List<asy::Future<self::C::U*>*>*>());
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.transformed.expect
index 7827c2f..6d2e13b 100644
--- a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
     ;
   operator []=(generic-covariant-impl core::Object* x, generic-covariant-impl core::Object* y) → void {}
   method h() → void {
-    super.{self::B::[]=}(self::f<dynamic>() as{TypeError} core::Map<core::int*, asy::Future<self::C::U*>*>*, self::f<core::List<asy::Future<self::C::U*>*>*>());
+    super.{self::B::[]=}(self::f<core::Map<core::int*, asy::Future<self::C::U*>*>*>(), self::f<core::List<asy::Future<self::C::U*>*>*>());
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart b/pkg/front_end/testcases/inference/unresolved_super.dart
index f9e96ce..fc14162 100644
--- a/pkg/front_end/testcases/inference/unresolved_super.dart
+++ b/pkg/front_end/testcases/inference/unresolved_super.dart
@@ -9,10 +9,10 @@
 
 class C {
   void test() {
-    var /*@type=dynamic*/ v1 = super.foo(/*@typeArgs=dynamic*/ f());
+    /*var /*@type=dynamic*/ v1 = super.foo(/*@typeArgs=dynamic*/ f());
     var /*@type=dynamic*/ v2 = super.bar;
     var /*@type=dynamic*/ v3 = super[0];
-    var /*@type=dynamic*/ v4 = super.bar = /*@typeArgs=dynamic*/ f();
+    var /*@type=dynamic*/ v4 = super.bar = /*@typeArgs=dynamic*/ f();*/
     var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
   }
 }
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
index 0addd70..d7d9a11 100644
--- a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
@@ -2,25 +2,9 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/unresolved_super.dart:12:38: Error: Superclass has no method named 'foo'.
-//     var /*@type=dynamic*/ v1 = super.foo(/*@typeArgs=dynamic*/ f());
-//                                      ^^^
-//
-// pkg/front_end/testcases/inference/unresolved_super.dart:13:38: Error: Superclass has no getter named 'bar'.
-//     var /*@type=dynamic*/ v2 = super.bar;
-//                                      ^^^
-//
-// pkg/front_end/testcases/inference/unresolved_super.dart:14:37: Error: Superclass has no method named '[]'.
-//     var /*@type=dynamic*/ v3 = super[0];
-//                                     ^
-//
-// pkg/front_end/testcases/inference/unresolved_super.dart:15:38: Error: Superclass has no setter named 'bar'.
-//     var /*@type=dynamic*/ v4 = super.bar = /*@typeArgs=dynamic*/ f();
-//                                      ^^^
-//
 // pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
 //     var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
-//                                     ^
+//                                     ^^^
 //
 import self as self;
 import "dart:core" as core;
@@ -30,11 +14,9 @@
     : super core::Object::•()
     ;
   method test() → void {
-    dynamic v1 = super.foo(self::f<dynamic>());
-    dynamic v2 = super.bar;
-    dynamic v3 = super.[](0);
-    dynamic v4 = super.bar = self::f<dynamic>();
-    dynamic v5 = let final core::int* #t1 = 0 in let final dynamic #t2 = self::f<dynamic>() in let final void #t3 = super.[]=(#t1, #t2) in #t2;
+    dynamic v5 = let final core::int* #t1 = 0 in let final dynamic #t2 = self::f<dynamic>() in let final void #t3 = invalid-expression "pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
+    var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
+                                    ^^^" in #t2;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect
new file mode 100644
index 0000000..d7d9a11
--- /dev/null
+++ b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
+//     var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
+//                                     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  method test() → void {
+    dynamic v5 = let final core::int* #t1 = 0 in let final dynamic #t2 = self::f<dynamic>() in let final void #t3 = invalid-expression "pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
+    var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
+                                    ^^^" in #t2;
+  }
+}
+static method f<T extends core::Object* = dynamic>() → self::f::T*
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
index e56ff7a..1ce9cd4 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::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 c1f792b..6895096 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::T*>*
     : super core::Object::•()
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 c1f792b..6895096 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
+typedef F<contravariant U extends core::Object* = dynamic, V extends core::Object* = dynamic> = (U*) →* V*;
 class Foo<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::Foo<self::Foo::T*>*
     : super core::Object::•()
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 f1f28c4..0501678 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
@@ -27,15 +27,20 @@
     /*@target=Test::member*/ /*@target=Test::member*/ member
         /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
 
-    /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
 
-    /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
 
-    /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
 
-    -- /*@target=Test::member*/ member;
+    /*@ target=B::- */ --
+        /*@target=Test::member*/ /*@target=Test::member*/ member;
 
-    /*@target=Test::member*/ member--;
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
 
     var /*@ type=B* */ v1 = /*@target=Test::member*/ member =
         /*@ typeArgs=B* */ f();
@@ -44,18 +49,27 @@
         member
             /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
 
-    var /*@ type=A* */ v3 = /*@target=Test::member*/ member +=
-        /*@ typeArgs=dynamic */ f();
+    var /*@ type=A* */ v3 =
+        /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::+ */ +=
+            /*@ typeArgs=C* */ f();
 
-    var /*@ type=B* */ v4 = /*@target=Test::member*/ member *=
-        /*@ typeArgs=dynamic */ f();
+    var /*@ type=B* */ v4 =
+        /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::* */ *=
+            /*@ typeArgs=B* */ f();
 
-    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &=
-        /*@ typeArgs=dynamic */ f();
+    var /*@ type=C* */ v5 =
+        /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::& */ &=
+            /*@ typeArgs=A* */ f();
 
-    var /*@ type=B* */ v6 = -- /*@target=Test::member*/ member;
+    var /*@ type=B* */ v6 = /*@ target=B::- */ --
+        /*@target=Test::member*/ /*@target=Test::member*/ member;
 
-    var /*@ type=B* */ v7 = /*@target=Test::member*/ member--;
+    var /*@ type=B* */ v7 =
+        /*@ 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_implicit_this.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.expect
index 9986ad5..043ccf2 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.expect
@@ -33,16 +33,16 @@
   method test() → void {
     this.{self::Test::member} = self::f<self::B*>();
     this.{self::Test::member}.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : null;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = this.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = this.{self::Test::member} in #t1.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : #t1;
-    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = this.{self::Test::member} in let final self::B* #t3 = this.{self::Test::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.transformed.expect
index 9986ad5..043ccf2 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.strong.transformed.expect
@@ -33,16 +33,16 @@
   method test() → void {
     this.{self::Test::member} = self::f<self::B*>();
     this.{self::Test::member}.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : null;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = this.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = this.{self::Test::member} in #t1.{core::Object::==}(null) ?{self::B*} this.{self::Test::member} = self::f<self::B*>() : #t1;
-    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = this.{self::Test::member} in let final self::B* #t3 = this.{self::Test::member} = #t2.{self::B::-}(1) in #t2;
   }
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 cfabd2b..e042927 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
@@ -23,13 +23,18 @@
     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=int* */ v7 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::+ */ += getInt();
 
-    var /*@ type=num* */ v8 = /*@target=Test1::t*/ t += getNum();
+    var /*@ type=num* */ v8 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::+ */ += getNum();
 
-    var /*@ type=int* */ v10 = ++ /*@target=Test1::t*/ t;
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++
+        /*@target=Test1::t*/ /*@target=Test1::t*/ t;
 
-    var /*@ type=int* */ v11 = /*@target=Test1::t*/ t++;
+    var /*@ type=int* */ v11 =
+        /*@ type=int* */ /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -52,15 +57,21 @@
     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* */ v7 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getInt();
 
-    var /*@ type=num* */ v8 = /*@target=Test2::t*/ t += getNum();
+    var /*@ type=num* */ v8 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getNum();
 
-    var /*@ type=num* */ v9 = /*@target=Test2::t*/ t += getDouble();
+    var /*@ type=num* */ v9 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::+ */ += getDouble();
 
-    var /*@ type=num* */ v10 = ++ /*@target=Test2::t*/ t;
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++
+        /*@target=Test2::t*/ /*@target=Test2::t*/ t;
 
-    var /*@ type=num* */ v11 = /*@target=Test2::t*/ t++;
+    var /*@ type=num* */ v11 =
+        /*@ type=num* */ /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -78,15 +89,21 @@
     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* */ v7 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getInt();
 
-    var /*@ type=double* */ v8 = /*@target=Test3::t*/ t += getNum();
+    var /*@ type=double* */ v8 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getNum();
 
-    var /*@ type=double* */ v9 = /*@target=Test3::t*/ t += getDouble();
+    var /*@ type=double* */ v9 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=double::+ */ += getDouble();
 
-    var /*@ type=double* */ v10 = ++ /*@target=Test3::t*/ t;
+    var /*@ type=double* */ v10 =
+        /*@ target=double::+ */ ++ /*@target=Test3::t*/ /*@target=Test3::t*/ t;
 
-    var /*@ type=double* */ v11 = /*@target=Test3::t*/ t++;
+    var /*@ type=double* */ v11 =
+        /*@ type=double* */ /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
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 4d3a249..4b6482c 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
@@ -30,9 +30,9 @@
     t /*@target=Test::[]=*/ [
         /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
 
-    t /*@target=Test::[]*/ [
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
             /*@ typeArgs=Index* */ f()]
-        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=B* */ f();
+        /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
 
     t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
         /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
@@ -55,9 +55,9 @@
     var /*@ type=B* */ v1 = t /*@target=Test::[]=*/ [
         /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
 
-    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ [
+    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
             /*@ typeArgs=Index* */ f()]
-        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=B* */ f();
+        /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
 
     var /*@ type=A* */ v3 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
             /*@ typeArgs=Index* */ f()]
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 4f4b0ba..4bebdb8 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
@@ -37,9 +37,8 @@
     t /*@target=Test::[]=*/ [
         /*@ 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=Object::==*/ ??= /*@ typeArgs=A* */ f();
 
     t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
         /*@ target=B::+ */ += /*@ typeArgs=E* */ f();
@@ -53,9 +52,9 @@
     var /*@ type=A* */ v1 = t /*@target=Test::[]=*/ [
         /*@ typeArgs=Index* */ f()] = /*@ typeArgs=A* */ f();
 
-    var /*@ type=A* */ v2 = t /*@target=Test::[]*/ [
+    var /*@ type=A* */ v2 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
             /*@ typeArgs=Index* */ f()]
-        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=A* */ f();
+        /*@target=Object::==*/ ??= /*@ typeArgs=A* */ f();
 
     var /*@ type=D* */ v3 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
             /*@ typeArgs=Index* */ f()]
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart
index 06b4ca1..6b091a7 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart
@@ -28,31 +28,54 @@
 class Test extends Base {
   void test() {
     super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::-*/ --super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        [/*@ typeArgs=Index* */ f()];
+
+    super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        [/*@ typeArgs=Index* */ f()] /*@ target=B::-*/ --;
+
     var /*@ type=B* */ v1 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=A* */ v3 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v4 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = super /*@target=Base::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 =
-        --super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 =
-        super /*@target=Base::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    var /*@ type=B* */ v4 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = super /*@target=Base::[]*/ /*@target=Base::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = /*@ target=B::-*/ --super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ [/*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        [/*@ typeArgs=Index* */ f()] /*@ target=B::-*/ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.expect
index ade4cca..6386cbd 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.expect
@@ -43,20 +43,20 @@
     : super self::Base::•()
     ;
   method test() → void {
-    super.{self::Base::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in super.{self::Base::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = super.{self::Base::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in super.{self::Base::[]=}(#t4 as{TypeError} self::Index*, super.{self::Base::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in super.{self::Base::[]=}(#t5 as{TypeError} self::Index*, super.{self::Base::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in super.{self::Base::[]=}(#t6 as{TypeError} self::Index*, super.{self::Base::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = super.{self::Base::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = super.{self::Base::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in super.{self::Base::[]=}(#t10 as{TypeError} self::Index*, super.{self::Base::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = super.{self::Base::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = super.{self::Base::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = super.{self::Base::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::A* v3 = let final dynamic #t18 = self::f<dynamic>() in let final self::A* #t19 = super.{self::Base::[]}(#t18 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t20 = super.{self::Base::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v4 = let final dynamic #t21 = self::f<dynamic>() in let final self::B* #t22 = super.{self::Base::[]}(#t21 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t23 = super.{self::Base::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::C* v5 = let final dynamic #t24 = self::f<dynamic>() in let final self::C* #t25 = super.{self::Base::[]}(#t24 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t26 = super.{self::Base::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v6 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = super.{self::Base::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = super.{self::Base::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v7 = let final dynamic #t30 = self::f<dynamic>() in let final self::B* #t31 = super.{self::Base::[]}(#t30 as{TypeError} self::Index*) in let final void #t32 = super.{self::Base::[]=}(#t30 as{TypeError} self::Index*, #t31.{self::B::-}(1)) in #t31;
+    super.{self::Base::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in super.{self::Base::[]}(#t1).{core::Object::==}(null) ?{self::B*} super.{self::Base::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in super.{self::Base::[]=}(#t2, super.{self::Base::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in super.{self::Base::[]=}(#t3, super.{self::Base::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in super.{self::Base::[]=}(#t4, super.{self::Base::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = super.{self::Base::[]}(#t5).{self::B::-}(1) in let final void #t7 = super.{self::Base::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in super.{self::Base::[]=}(#t8, super.{self::Base::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = super.{self::Base::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = super.{self::Base::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = super.{self::Base::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = super.{self::Base::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = super.{self::Base::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = super.{self::Base::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = super.{self::Base::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = super.{self::Base::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = super.{self::Base::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = super.{self::Base::[]}(#t25).{self::B::-}(1) in let final void #t27 = super.{self::Base::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = super.{self::Base::[]}(#t28) in let final void #t30 = super.{self::Base::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.transformed.expect
index ade4cca..6386cbd 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.strong.transformed.expect
@@ -43,20 +43,20 @@
     : super self::Base::•()
     ;
   method test() → void {
-    super.{self::Base::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in super.{self::Base::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = super.{self::Base::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in super.{self::Base::[]=}(#t4 as{TypeError} self::Index*, super.{self::Base::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in super.{self::Base::[]=}(#t5 as{TypeError} self::Index*, super.{self::Base::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in super.{self::Base::[]=}(#t6 as{TypeError} self::Index*, super.{self::Base::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = super.{self::Base::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = super.{self::Base::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in super.{self::Base::[]=}(#t10 as{TypeError} self::Index*, super.{self::Base::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = super.{self::Base::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = super.{self::Base::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = super.{self::Base::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::A* v3 = let final dynamic #t18 = self::f<dynamic>() in let final self::A* #t19 = super.{self::Base::[]}(#t18 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t20 = super.{self::Base::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v4 = let final dynamic #t21 = self::f<dynamic>() in let final self::B* #t22 = super.{self::Base::[]}(#t21 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t23 = super.{self::Base::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::C* v5 = let final dynamic #t24 = self::f<dynamic>() in let final self::C* #t25 = super.{self::Base::[]}(#t24 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t26 = super.{self::Base::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v6 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = super.{self::Base::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = super.{self::Base::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v7 = let final dynamic #t30 = self::f<dynamic>() in let final self::B* #t31 = super.{self::Base::[]}(#t30 as{TypeError} self::Index*) in let final void #t32 = super.{self::Base::[]=}(#t30 as{TypeError} self::Index*, #t31.{self::B::-}(1)) in #t31;
+    super.{self::Base::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in super.{self::Base::[]}(#t1).{core::Object::==}(null) ?{self::B*} super.{self::Base::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in super.{self::Base::[]=}(#t2, super.{self::Base::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in super.{self::Base::[]=}(#t3, super.{self::Base::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in super.{self::Base::[]=}(#t4, super.{self::Base::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = super.{self::Base::[]}(#t5).{self::B::-}(1) in let final void #t7 = super.{self::Base::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in super.{self::Base::[]=}(#t8, super.{self::Base::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = super.{self::Base::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = super.{self::Base::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = super.{self::Base::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = super.{self::Base::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = super.{self::Base::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = super.{self::Base::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = super.{self::Base::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = super.{self::Base::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = super.{self::Base::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = super.{self::Base::[]}(#t25).{self::B::-}(1) in let final void #t27 = super.{self::Base::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = super.{self::Base::[]}(#t28) in let final void #t30 = super.{self::Base::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart
index 0ea9a12e..ebd811a 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart
@@ -20,129 +20,321 @@
 abstract class Test1 extends Base<int, int> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=int* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=int* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=int* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=int* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=int* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test2 extends Base<int, num> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=int* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=int* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=int* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=int* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=int* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=double* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test3 extends Base<int, double> {
   void test() {
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=int* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=int* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=int* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=double* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test4 extends Base<num, int> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=num* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=num* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test5 extends Base<num, num> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=num* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=num* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=num* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=num* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test6 extends Base<num, double> {
   void test() {
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=num* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=num* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=num* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=num* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = super /*@target=Base::[]*/ /*@target=Base::[]=*/
+        ['x'] /*@ target=num::+ */ ++;
   }
 }
 
 abstract class Test7 extends Base<double, int> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=num* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=num* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=double* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getNum();
+
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/
+            ['x'] /*@ target=double::+ */ ++;
   }
 }
 
 abstract class Test8 extends Base<double, num> {
   void test() {
     var /*@ type=int* */ v1 = super /*@target=Base::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v4 = super /*@target=Base::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=double* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=double* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v4 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=double* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=double* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getNum();
+
+    var /*@ type=double* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/
+            ['x'] /*@ target=double::+ */ ++;
   }
 }
 
 abstract class Test9 extends Base<double, double> {
   void test() {
     var /*@ type=num* */ v2 = super /*@target=Base::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = super /*@target=Base::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = super /*@target=Base::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v6 = super /*@target=Base::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=double* */ v7 = super /*@target=Base::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = super /*@target=Base::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = super /*@target=Base::[]=*/ ['x'] += getDouble();
-    var /*@ type=double* */ v10 = ++super /*@target=Base::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = super /*@target=Base::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        super /*@target=Base::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=double* */ v6 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=double* */ v7 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getNum();
+
+    var /*@ type=double* */ v9 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x']
+            /*@ target=double::+ */ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+        /*@target=Base::[]*/ /*@target=Base::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 =
+        super /*@target=Base::[]*/ /*@target=Base::[]=*/
+            ['x'] /*@ target=double::+ */ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.strong.expect
index 3a8ed7b..82e6557 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.strong.expect
@@ -2,40 +2,40 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:55:65: 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_super_upwards.dart:108:34: 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 = super /*@target=Base::[]=*/ ['x'] += getInt();
-//                                                                 ^
+//             /*@ target=num::+ */ += getInt();
+//                                  ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:58:32: 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_super_upwards.dart:118:53: 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 = ++super /*@target=Base::[]=*/ ['x'];
-//                                ^
+//     var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+//                                                     ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:59:65: 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_super_upwards.dart:122:36: 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 = super /*@target=Base::[]=*/ ['x']++;
-//                                                                 ^
+//         ['x'] /*@ target=num::+ */ ++;
+//                                    ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:112:68: 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_super_upwards.dart:248:37: 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 = super /*@target=Base::[]=*/ ['x'] += getInt();
-//                                                                    ^
+//             /*@ target=double::+ */ += getInt();
+//                                     ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:113:68: 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_super_upwards.dart:252:37: 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 = super /*@target=Base::[]=*/ ['x'] += getNum();
-//                                                                    ^
+//             /*@ target=double::+ */ += getNum();
+//                                     ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:114:35: 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_super_upwards.dart:254:59: 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 = ++super /*@target=Base::[]=*/ ['x'];
-//                                   ^
+//     var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+//                                                           ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:115:68: 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_super_upwards.dart:259:43: 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 = super /*@target=Base::[]=*/ ['x']++;
-//                                                                    ^
+//             ['x'] /*@ target=double::+ */ ++;
+//                                           ^
 //
 import self as self;
 import "dart:core" as core;
@@ -93,20 +93,20 @@
     core::double* v3 = let final core::String* #t66 = "x" in let final core::double* #t67 = self::getDouble() in let final void #t68 = super.{self::Base::[]=}(#t66, #t67) in #t67;
     core::num* v5 = let final core::String* #t69 = "x" in let final core::int* #t70 = super.{self::Base::[]}(#t69) in #t70.{core::num::==}(null) ?{core::num*} let final core::num* #t71 = self::getNum() as{TypeError} core::double* in let final void #t72 = super.{self::Base::[]=}(#t69, #t71) in #t71 : #t70;
     core::num* v6 = let final core::String* #t73 = "x" in let final core::int* #t74 = super.{self::Base::[]}(#t73) in #t74.{core::num::==}(null) ?{core::num*} let final core::double* #t75 = self::getDouble() in let final void #t76 = super.{self::Base::[]=}(#t73, #t75) in #t75 : #t74;
-    core::int* v7 = let final core::String* #t77 = "x" in let final core::int* #t78 = let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:55:65: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    core::int* v7 = let final core::String* #t77 = "x" in let final core::int* #t78 = let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:108:34: 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 = super /*@target=Base::[]=*/ ['x'] += getInt();
-                                                                ^" in super.{self::Base::[]}(#t77).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t80 = super.{self::Base::[]=}(#t77, #t78) in #t78;
+            /*@ target=num::+ */ += getInt();
+                                 ^" in super.{self::Base::[]}(#t77).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t80 = super.{self::Base::[]=}(#t77, #t78) in #t78;
     core::num* v8 = let final core::String* #t81 = "x" in let final core::num* #t82 = super.{self::Base::[]}(#t81).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t83 = super.{self::Base::[]=}(#t81, #t82) in #t82;
     core::double* v9 = let final core::String* #t84 = "x" in let final core::double* #t85 = super.{self::Base::[]}(#t84).{core::num::+}(self::getDouble()) in let final void #t86 = super.{self::Base::[]=}(#t84, #t85) in #t85;
-    core::int* v10 = let final core::String* #t87 = "x" in let final core::int* #t88 = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:58:32: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    core::int* v10 = let final core::String* #t87 = "x" in let final core::int* #t88 = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:118:53: 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 = ++super /*@target=Base::[]=*/ ['x'];
-                               ^" in super.{self::Base::[]}(#t87).{core::num::+}(1) as{TypeError} core::double* in let final void #t90 = super.{self::Base::[]=}(#t87, #t88) in #t88;
-    core::int* v11 = let final core::String* #t91 = "x" in let final core::int* #t92 = super.{self::Base::[]}(#t91) in let final void #t93 = super.{self::Base::[]=}(#t91, let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:59:65: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+                                                    ^" in super.{self::Base::[]}(#t87).{core::num::+}(1) as{TypeError} core::double* in let final void #t90 = super.{self::Base::[]=}(#t87, #t88) in #t88;
+    core::int* v11 = let final core::String* #t91 = "x" in let final core::int* #t92 = super.{self::Base::[]}(#t91) in let final void #t93 = super.{self::Base::[]=}(#t91, let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:122:36: 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 = super /*@target=Base::[]=*/ ['x']++;
-                                                                ^" in #t92.{core::num::+}(1) as{TypeError} core::double*) in #t92;
+        ['x'] /*@ target=num::+ */ ++;
+                                   ^" in #t92.{core::num::+}(1) as{TypeError} core::double*) in #t92;
   }
 }
 abstract class Test4 extends self::Base<core::num*, core::int*> {
@@ -167,22 +167,22 @@
     core::num* v2 = let final core::String* #t189 = "x" in let final core::num* #t190 = self::getNum() as{TypeError} core::int* in let final void #t191 = super.{self::Base::[]=}(#t189, #t190) in #t190;
     core::num* v4 = let final core::String* #t192 = "x" in let final core::double* #t193 = super.{self::Base::[]}(#t192) in #t193.{core::num::==}(null) ?{core::num*} let final core::int* #t194 = self::getInt() in let final void #t195 = super.{self::Base::[]=}(#t192, #t194) in #t194 : #t193;
     core::num* v5 = let final core::String* #t196 = "x" in let final core::double* #t197 = super.{self::Base::[]}(#t196) in #t197.{core::num::==}(null) ?{core::num*} let final core::num* #t198 = self::getNum() as{TypeError} core::int* in let final void #t199 = super.{self::Base::[]=}(#t196, #t198) in #t198 : #t197;
-    core::double* v7 = let final core::String* #t200 = "x" in let final core::double* #t201 = let final<BottomType> #t202 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:112:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+    core::double* v7 = let final core::String* #t200 = "x" in let final core::double* #t201 = let final<BottomType> #t202 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:248:37: 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 = super /*@target=Base::[]=*/ ['x'] += getInt();
-                                                                   ^" in super.{self::Base::[]}(#t200).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t203 = super.{self::Base::[]=}(#t200, #t201) in #t201;
-    core::double* v8 = let final core::String* #t204 = "x" in let final core::double* #t205 = let final<BottomType> #t206 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:113:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+            /*@ target=double::+ */ += getInt();
+                                    ^" in super.{self::Base::[]}(#t200).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t203 = super.{self::Base::[]=}(#t200, #t201) in #t201;
+    core::double* v8 = let final core::String* #t204 = "x" in let final core::double* #t205 = let final<BottomType> #t206 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:252:37: 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 = super /*@target=Base::[]=*/ ['x'] += getNum();
-                                                                   ^" in super.{self::Base::[]}(#t204).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t207 = super.{self::Base::[]=}(#t204, #t205) in #t205;
-    core::double* v10 = let final core::String* #t208 = "x" in let final core::double* #t209 = let final<BottomType> #t210 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:114:35: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+            /*@ target=double::+ */ += getNum();
+                                    ^" in super.{self::Base::[]}(#t204).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t207 = super.{self::Base::[]=}(#t204, #t205) in #t205;
+    core::double* v10 = let final core::String* #t208 = "x" in let final core::double* #t209 = let final<BottomType> #t210 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:254:59: 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 = ++super /*@target=Base::[]=*/ ['x'];
-                                  ^" in super.{self::Base::[]}(#t208).{core::double::+}(1) as{TypeError} core::int* in let final void #t211 = super.{self::Base::[]=}(#t208, #t209) in #t209;
-    core::double* v11 = let final core::String* #t212 = "x" in let final core::double* #t213 = super.{self::Base::[]}(#t212) in let final void #t214 = super.{self::Base::[]=}(#t212, let final<BottomType> #t215 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:115:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+                                                          ^" in super.{self::Base::[]}(#t208).{core::double::+}(1) as{TypeError} core::int* in let final void #t211 = super.{self::Base::[]=}(#t208, #t209) in #t209;
+    core::double* v11 = let final core::String* #t212 = "x" in let final core::double* #t213 = super.{self::Base::[]}(#t212) in let final void #t214 = super.{self::Base::[]=}(#t212, let final<BottomType> #t215 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart:259:43: 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 = super /*@target=Base::[]=*/ ['x']++;
-                                                                   ^" in #t213.{core::double::+}(1) as{TypeError} core::int*) in #t213;
+            ['x'] /*@ target=double::+ */ ++;
+                                          ^" in #t213.{core::double::+}(1) as{TypeError} core::int*) in #t213;
   }
 }
 abstract class Test8 extends self::Base<core::double*, core::num*> {
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart
index ccccceb..c584f61 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart
@@ -26,31 +26,55 @@
 
   void test() {
     this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ --this /*@target=Test::[]*/ /*@target=Test::[]=*/
+        [/*@ typeArgs=Index* */ f()];
+
+    this /*@target=Test::[]*/ /*@target=Test::[]=*/
+        [/*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=A* */ v3 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v4 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = this /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    var /*@ type=B* */ v4 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = this /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
     var /*@ type=B* */ v6 =
-        --this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 =
-        this /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ target=B::- */ --this /*@target=Test::[]*/ /*@target=Test::[]=*/
+            [/*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 = this /*@target=Test::[]*/ /*@target=Test::[]=*/
+        [/*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
index 036a9c0..909ee1a 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
@@ -38,20 +38,20 @@
     return null;
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
-    this.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in this.{self::Test::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = this.{self::Test::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in this.{self::Test::[]=}(#t4 as{TypeError} self::Index*, this.{self::Test::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in this.{self::Test::[]=}(#t5 as{TypeError} self::Index*, this.{self::Test::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in this.{self::Test::[]=}(#t6 as{TypeError} self::Index*, this.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = this.{self::Test::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = this.{self::Test::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in this.{self::Test::[]=}(#t10 as{TypeError} self::Index*, this.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = this.{self::Test::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = this.{self::Test::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = this.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::A* v3 = let final dynamic #t18 = self::f<dynamic>() in let final self::A* #t19 = this.{self::Test::[]}(#t18 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t20 = this.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v4 = let final dynamic #t21 = self::f<dynamic>() in let final self::B* #t22 = this.{self::Test::[]}(#t21 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t23 = this.{self::Test::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::C* v5 = let final dynamic #t24 = self::f<dynamic>() in let final self::C* #t25 = this.{self::Test::[]}(#t24 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t26 = this.{self::Test::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v6 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = this.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = this.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v7 = let final dynamic #t30 = self::f<dynamic>() in let final self::B* #t31 = this.{self::Test::[]}(#t30 as{TypeError} self::Index*) in let final void #t32 = this.{self::Test::[]=}(#t30 as{TypeError} self::Index*, #t31.{self::B::-}(1)) in #t31;
+    this.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in this.{self::Test::[]}(#t1).{core::Object::==}(null) ?{self::B*} this.{self::Test::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in this.{self::Test::[]=}(#t2, this.{self::Test::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in this.{self::Test::[]=}(#t3, this.{self::Test::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
+    self::A* v3 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
+    self::B* v4 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
+    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
+    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
+    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{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_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
index 036a9c0..909ee1a 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
@@ -38,20 +38,20 @@
     return null;
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
-    this.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final dynamic #t1 = self::f<dynamic>() in this.{self::Test::[]}(#t1 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t2 = self::f<self::B*>() in let final void #t3 = this.{self::Test::[]=}(#t1 as{TypeError} self::Index*, #t2) in #t2 : null;
-    let final dynamic #t4 = self::f<dynamic>() in this.{self::Test::[]=}(#t4 as{TypeError} self::Index*, this.{self::Test::[]}(#t4 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final dynamic #t5 = self::f<dynamic>() in this.{self::Test::[]=}(#t5 as{TypeError} self::Index*, this.{self::Test::[]}(#t5 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final dynamic #t6 = self::f<dynamic>() in this.{self::Test::[]=}(#t6 as{TypeError} self::Index*, this.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final dynamic #t7 = self::f<dynamic>() in let final self::B* #t8 = this.{self::Test::[]}(#t7 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t9 = this.{self::Test::[]=}(#t7 as{TypeError} self::Index*, #t8) in #t8;
-    let final dynamic #t10 = self::f<dynamic>() in this.{self::Test::[]=}(#t10 as{TypeError} self::Index*, this.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final dynamic #t11 = self::f<dynamic>() in let final self::B* #t12 = self::f<self::B*>() in let final void #t13 = this.{self::Test::[]=}(#t11 as{TypeError} self::Index*, #t12) in #t12;
-    self::B* v2 = let final dynamic #t14 = self::f<dynamic>() in let final self::B* #t15 = this.{self::Test::[]}(#t14 as{TypeError} self::Index*) in #t15.{core::Object::==}(null) ?{self::B*} let final self::B* #t16 = self::f<self::B*>() in let final void #t17 = this.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t16) in #t16 : #t15;
-    self::A* v3 = let final dynamic #t18 = self::f<dynamic>() in let final self::A* #t19 = this.{self::Test::[]}(#t18 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t20 = this.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v4 = let final dynamic #t21 = self::f<dynamic>() in let final self::B* #t22 = this.{self::Test::[]}(#t21 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t23 = this.{self::Test::[]=}(#t21 as{TypeError} self::Index*, #t22) in #t22;
-    self::C* v5 = let final dynamic #t24 = self::f<dynamic>() in let final self::C* #t25 = this.{self::Test::[]}(#t24 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t26 = this.{self::Test::[]=}(#t24 as{TypeError} self::Index*, #t25) in #t25;
-    self::B* v6 = let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = this.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = this.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v7 = let final dynamic #t30 = self::f<dynamic>() in let final self::B* #t31 = this.{self::Test::[]}(#t30 as{TypeError} self::Index*) in let final void #t32 = this.{self::Test::[]=}(#t30 as{TypeError} self::Index*, #t31.{self::B::-}(1)) in #t31;
+    this.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Index* #t1 = self::f<self::Index*>() in this.{self::Test::[]}(#t1).{core::Object::==}(null) ?{self::B*} this.{self::Test::[]=}(#t1, self::f<self::B*>()) : null;
+    let final self::Index* #t2 = self::f<self::Index*>() in this.{self::Test::[]=}(#t2, this.{self::Test::[]}(#t2).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Index* #t3 = self::f<self::Index*>() in this.{self::Test::[]=}(#t3, this.{self::Test::[]}(#t3).{self::B::*}(self::f<self::B*>()));
+    let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
+    let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
+    let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
+    self::A* v3 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
+    self::B* v4 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
+    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
+    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
+    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{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_this_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart
index 4656c2b..35de18e 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart
@@ -15,13 +15,31 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test1::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = this /*@target=Test1::[]=*/ ['x'] = getNum();
-    var /*@ type=int* */ v4 = this /*@target=Test1::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test1::[]=*/ ['x'] ??= getNum();
-    var /*@ type=int* */ v7 = this /*@target=Test1::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test1::[]=*/ ['x'] += getNum();
-    var /*@ type=int* */ v10 = ++this /*@target=Test1::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = this /*@target=Test1::[]=*/ ['x']++;
+
+    var /*@ type=int* */ v4 = this
+            /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=int* */ v7 = this
+            /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = this
+            /*@target=Test1::[]*/ /*@target=Test1::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -31,16 +49,42 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test2::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = this /*@target=Test2::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test2::[]=*/ ['x'] = getDouble();
-    var /*@ type=int* */ v4 = this /*@target=Test2::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test2::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = this /*@target=Test2::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=int* */ v7 = this /*@target=Test2::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test2::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = this /*@target=Test2::[]=*/ ['x'] += getDouble();
-    var /*@ type=int* */ v10 = ++this /*@target=Test2::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = this /*@target=Test2::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        this /*@target=Test2::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=int* */ v4 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v6 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=int* */ v7 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=double* */ v9 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::+*/ += getDouble();
+
+    var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = this
+            /*@target=Test2::[]*/ /*@target=Test2::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -50,14 +94,36 @@
 
   void test() {
     var /*@ type=num* */ v2 = this /*@target=Test3::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test3::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = this /*@target=Test3::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = this /*@target=Test3::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=int* */ v7 = this /*@target=Test3::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test3::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = this /*@target=Test3::[]=*/ ['x'] += getDouble();
-    var /*@ type=int* */ v10 = ++this /*@target=Test3::[]=*/ ['x'];
-    var /*@ type=int* */ v11 = this /*@target=Test3::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        this /*@target=Test3::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v6 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=int* */ v7 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=double* */ v9 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::+*/ += getDouble();
+
+    var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x'];
+
+    var /*@ type=int* */ v11 = this
+            /*@target=Test3::[]*/ /*@target=Test3::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -67,13 +133,31 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test4::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = this /*@target=Test4::[]=*/ ['x'] = getNum();
-    var /*@ type=num* */ v4 = this /*@target=Test4::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test4::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v7 = this /*@target=Test4::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test4::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v10 = ++this /*@target=Test4::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = this /*@target=Test4::[]=*/ ['x']++;
+
+    var /*@ type=num* */ v4 = this
+            /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v7 = this
+            /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=num* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = this
+            /*@target=Test4::[]*/ /*@target=Test4::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -83,16 +167,42 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test5::[]=*/ ['x'] = getInt();
+
     var /*@ type=num* */ v2 = this /*@target=Test5::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test5::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v4 = this /*@target=Test5::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test5::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = this /*@target=Test5::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=num* */ v7 = this /*@target=Test5::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test5::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v9 = this /*@target=Test5::[]=*/ ['x'] += getDouble();
-    var /*@ type=num* */ v10 = ++this /*@target=Test5::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = this /*@target=Test5::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        this /*@target=Test5::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v4 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v6 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=num* */ v7 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=num* */ v9 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::+*/ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = this
+            /*@target=Test5::[]*/ /*@target=Test5::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -102,14 +212,36 @@
 
   void test() {
     var /*@ type=num* */ v2 = this /*@target=Test6::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test6::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = this /*@target=Test6::[]=*/ ['x'] ??= getNum();
-    var /*@ type=num* */ v6 = this /*@target=Test6::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=num* */ v7 = this /*@target=Test6::[]=*/ ['x'] += getInt();
-    var /*@ type=num* */ v8 = this /*@target=Test6::[]=*/ ['x'] += getNum();
-    var /*@ type=num* */ v9 = this /*@target=Test6::[]=*/ ['x'] += getDouble();
-    var /*@ type=num* */ v10 = ++this /*@target=Test6::[]=*/ ['x'];
-    var /*@ type=num* */ v11 = this /*@target=Test6::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 =
+        this /*@target=Test6::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=num* */ v6 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=num* */ v7 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::+*/ += getInt();
+
+    var /*@ type=num* */ v8 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::+*/ += getNum();
+
+    var /*@ type=num* */ v9 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::+*/ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@target=num::+*/ ++this
+        /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x'];
+
+    var /*@ type=num* */ v11 = this
+            /*@target=Test6::[]*/ /*@target=Test6::[]=*/ ['x']
+        /*@target=num::+*/ ++;
   }
 }
 
@@ -119,13 +251,32 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test7::[]=*/ ['x'] = getInt();
-    var /*@ type=num* */ v2 = this /*@target=Test7::[]=*/ ['x'] = getNum();
-    var /*@ type=num* */ v4 = this /*@target=Test7::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test7::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v7 = this /*@target=Test7::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = this /*@target=Test7::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v10 = ++this /*@target=Test7::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = this /*@target=Test7::[]=*/ ['x']++;
+
+    var /*@ type=num* */ v2 = this
+        /*@target=Test7::[]=*/ ['x'] = getNum();
+
+    var /*@ type=num* */ v4 = this
+            /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=double* */ v7 = this
+            /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x']
+        /*@target=double::+*/ += getInt();
+
+    var /*@ type=double* */ v8 = this
+            /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x']
+        /*@target=double::+*/ += getNum();
+
+    var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
+        /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 = this
+            /*@target=Test7::[]*/ /*@target=Test7::[]=*/ ['x']
+        /*@target=double::+*/ ++;
   }
 }
 
@@ -135,16 +286,43 @@
 
   void test() {
     var /*@ type=int* */ v1 = this /*@target=Test8::[]=*/ ['x'] = getInt();
-    var /*@ type=num* */ v2 = this /*@target=Test8::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test8::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v4 = this /*@target=Test8::[]=*/ ['x'] ??= getInt();
-    var /*@ type=num* */ v5 = this /*@target=Test8::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v6 = this /*@target=Test8::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=double* */ v7 = this /*@target=Test8::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = this /*@target=Test8::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = this /*@target=Test8::[]=*/ ['x'] += getDouble();
-    var /*@ type=double* */ v10 = ++this /*@target=Test8::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = this /*@target=Test8::[]=*/ ['x']++;
+
+    var /*@ type=num* */ v2 = this
+        /*@target=Test8::[]=*/ ['x'] = getNum();
+
+    var /*@ type=double* */ v3 = this
+        /*@target=Test8::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v4 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=num::==*/ ??= getInt();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=double* */ v6 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=double* */ v7 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=double::+*/ += getInt();
+
+    var /*@ type=double* */ v8 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=double::+*/ += getNum();
+
+    var /*@ type=double* */ v9 = this
+            /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x']
+        /*@target=double::+*/ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
+        /*@target=Test8::[]*/ /*@target=Test8::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 = this
+        /*@target=Test8::[]*/ /*@target=Test8::[]=*/ [
+        'x'] /*@target=double::+*/ ++;
   }
 }
 
@@ -154,14 +332,36 @@
 
   void test() {
     var /*@ type=num* */ v2 = this /*@target=Test9::[]=*/ ['x'] = getNum();
-    var /*@ type=double* */ v3 = this /*@target=Test9::[]=*/ ['x'] = getDouble();
-    var /*@ type=num* */ v5 = this /*@target=Test9::[]=*/ ['x'] ??= getNum();
-    var /*@ type=double* */ v6 = this /*@target=Test9::[]=*/ ['x'] ??= getDouble();
-    var /*@ type=double* */ v7 = this /*@target=Test9::[]=*/ ['x'] += getInt();
-    var /*@ type=double* */ v8 = this /*@target=Test9::[]=*/ ['x'] += getNum();
-    var /*@ type=double* */ v9 = this /*@target=Test9::[]=*/ ['x'] += getDouble();
-    var /*@ type=double* */ v10 = ++this /*@target=Test9::[]=*/ ['x'];
-    var /*@ type=double* */ v11 = this /*@target=Test9::[]=*/ ['x']++;
+
+    var /*@ type=double* */ v3 = this
+        /*@target=Test9::[]=*/ ['x'] = getDouble();
+
+    var /*@ type=num* */ v5 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=num::==*/ ??= getNum();
+
+    var /*@ type=double* */ v6 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=num::==*/ ??= getDouble();
+
+    var /*@ type=double* */ v7 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=double::+*/ += getInt();
+
+    var /*@ type=double* */ v8 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=double::+*/ += getNum();
+
+    var /*@ type=double* */ v9 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=double::+*/ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
+        /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x'];
+
+    var /*@ type=double* */ v11 = this
+            /*@target=Test9::[]*/ /*@target=Test9::[]=*/ ['x']
+        /*@target=double::+*/ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
index 2baa260..805d030 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
@@ -2,40 +2,40 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:56:65: 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_this_upwards.dart:111: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* */ v7 = this /*@target=Test3::[]=*/ ['x'] += getInt();
-//                                                                 ^
+//         /*@target=num::+*/ += getInt();
+//                            ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:59:32: 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_this_upwards.dart:121:51: 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 = ++this /*@target=Test3::[]=*/ ['x'];
-//                                ^
+//     var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
+//                                                   ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:60:65: 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_this_upwards.dart:126: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* */ v11 = this /*@target=Test3::[]=*/ ['x']++;
-//                                                                 ^
+//         /*@target=num::+*/ ++;
+//                            ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:125:68: 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_this_upwards.dart:268: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* */ v7 = this /*@target=Test7::[]=*/ ['x'] += getInt();
-//                                                                    ^
+//         /*@target=double::+*/ += getInt();
+//                               ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:126:68: 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_this_upwards.dart:272: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* */ v8 = this /*@target=Test7::[]=*/ ['x'] += getNum();
-//                                                                    ^
+//         /*@target=double::+*/ += getNum();
+//                               ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:127:35: 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_this_upwards.dart:274:57: 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 = ++this /*@target=Test7::[]=*/ ['x'];
-//                                   ^
+//     var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
+//                                                         ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:128:68: 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_this_upwards.dart:279: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* */ v11 = this /*@target=Test7::[]=*/ ['x']++;
-//                                                                    ^
+//         /*@target=double::+*/ ++;
+//                               ^
 //
 import self as self;
 import "dart:core" as core;
@@ -47,14 +47,14 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t1 = "x" in let final core::int* #t2 = self::getInt() in let final void #t3 = this.{self::Test1::[]=}(#t1, #t2) in #t2;
-    core::num* v2 = let final core::String* #t4 = "x" in let final core::num* #t5 = self::getNum() as{TypeError} core::int* in let final void #t6 = this.{self::Test1::[]=}(#t4, #t5) in #t5;
-    core::int* v4 = let final core::String* #t7 = "x" in let final core::int* #t8 = this.{self::Test1::[]}(#t7) in #t8.{core::num::==}(null) ?{core::int*} let final core::int* #t9 = self::getInt() in let final void #t10 = this.{self::Test1::[]=}(#t7, #t9) in #t9 : #t8;
-    core::num* v5 = let final core::String* #t11 = "x" in let final core::int* #t12 = this.{self::Test1::[]}(#t11) in #t12.{core::num::==}(null) ?{core::num*} let final core::num* #t13 = self::getNum() as{TypeError} core::int* in let final void #t14 = this.{self::Test1::[]=}(#t11, #t13) in #t13 : #t12;
-    core::int* v7 = let final core::String* #t15 = "x" in let final core::int* #t16 = this.{self::Test1::[]}(#t15).{core::num::+}(self::getInt()) in let final void #t17 = this.{self::Test1::[]=}(#t15, #t16) in #t16;
-    core::num* v8 = let final core::String* #t18 = "x" in let final core::num* #t19 = this.{self::Test1::[]}(#t18).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t20 = this.{self::Test1::[]=}(#t18, #t19) in #t19;
-    core::int* v10 = let final core::String* #t21 = "x" in let final core::int* #t22 = this.{self::Test1::[]}(#t21).{core::num::+}(1) in let final void #t23 = this.{self::Test1::[]=}(#t21, #t22) in #t22;
-    core::int* v11 = let final core::String* #t24 = "x" in let final core::int* #t25 = this.{self::Test1::[]}(#t24) in let final void #t26 = this.{self::Test1::[]=}(#t24, #t25.{core::num::+}(1)) in #t25;
+    core::int* v1 = let final self::Test1* #t1 = this in let final core::String* #t2 = "x" in let final core::int* #t3 = self::getInt() in let final void #t4 = #t1.{self::Test1::[]=}(#t2, #t3) in #t3;
+    core::num* v2 = let final self::Test1* #t5 = this in let final core::String* #t6 = "x" in let final core::num* #t7 = self::getNum() as{TypeError} core::int* in let final void #t8 = #t5.{self::Test1::[]=}(#t6, #t7) in #t7;
+    core::int* v4 = let final core::String* #t9 = "x" in let final core::int* #t10 = this.{self::Test1::[]}(#t9) in #t10.{core::num::==}(null) ?{core::int*} let final core::int* #t11 = self::getInt() in let final void #t12 = this.{self::Test1::[]=}(#t9, #t11) in #t11 : #t10;
+    core::num* v5 = let final core::String* #t13 = "x" in let final core::int* #t14 = this.{self::Test1::[]}(#t13) in #t14.{core::num::==}(null) ?{core::num*} let final core::num* #t15 = self::getNum() as{TypeError} core::int* in let final void #t16 = this.{self::Test1::[]=}(#t13, #t15) in #t15 : #t14;
+    core::int* v7 = let final core::String* #t17 = "x" in let final core::int* #t18 = this.{self::Test1::[]}(#t17).{core::num::+}(self::getInt()) in let final void #t19 = this.{self::Test1::[]=}(#t17, #t18) in #t18;
+    core::num* v8 = let final core::String* #t20 = "x" in let final core::num* #t21 = this.{self::Test1::[]}(#t20).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t22 = this.{self::Test1::[]=}(#t20, #t21) in #t21;
+    core::int* v10 = let final core::String* #t23 = "x" in let final core::int* #t24 = this.{self::Test1::[]}(#t23).{core::num::+}(1) in let final void #t25 = this.{self::Test1::[]=}(#t23, #t24) in #t24;
+    core::int* v11 = let final core::String* #t26 = "x" in let final core::int* #t27 = this.{self::Test1::[]}(#t26) in let final void #t28 = this.{self::Test1::[]=}(#t26, #t27.{core::num::+}(1)) in #t27;
   }
 }
 abstract class Test2 extends core::Object {
@@ -64,17 +64,17 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t27 = "x" in let final core::int* #t28 = self::getInt() in let final void #t29 = this.{self::Test2::[]=}(#t27, #t28) in #t28;
-    core::num* v2 = let final core::String* #t30 = "x" in let final core::num* #t31 = self::getNum() in let final void #t32 = this.{self::Test2::[]=}(#t30, #t31) in #t31;
-    core::double* v3 = let final core::String* #t33 = "x" in let final core::double* #t34 = self::getDouble() in let final void #t35 = this.{self::Test2::[]=}(#t33, #t34) in #t34;
-    core::int* v4 = let final core::String* #t36 = "x" in let final core::int* #t37 = this.{self::Test2::[]}(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final core::int* #t38 = self::getInt() in let final void #t39 = this.{self::Test2::[]=}(#t36, #t38) in #t38 : #t37;
-    core::num* v5 = let final core::String* #t40 = "x" in let final core::int* #t41 = this.{self::Test2::[]}(#t40) in #t41.{core::num::==}(null) ?{core::num*} let final core::num* #t42 = self::getNum() in let final void #t43 = this.{self::Test2::[]=}(#t40, #t42) in #t42 : #t41;
-    core::num* v6 = let final core::String* #t44 = "x" in let final core::int* #t45 = this.{self::Test2::[]}(#t44) in #t45.{core::num::==}(null) ?{core::num*} let final core::double* #t46 = self::getDouble() in let final void #t47 = this.{self::Test2::[]=}(#t44, #t46) in #t46 : #t45;
-    core::int* v7 = let final core::String* #t48 = "x" in let final core::int* #t49 = this.{self::Test2::[]}(#t48).{core::num::+}(self::getInt()) in let final void #t50 = this.{self::Test2::[]=}(#t48, #t49) in #t49;
-    core::num* v8 = let final core::String* #t51 = "x" in let final core::num* #t52 = this.{self::Test2::[]}(#t51).{core::num::+}(self::getNum()) in let final void #t53 = this.{self::Test2::[]=}(#t51, #t52) in #t52;
-    core::double* v9 = let final core::String* #t54 = "x" in let final core::double* #t55 = this.{self::Test2::[]}(#t54).{core::num::+}(self::getDouble()) in let final void #t56 = this.{self::Test2::[]=}(#t54, #t55) in #t55;
-    core::int* v10 = let final core::String* #t57 = "x" in let final core::int* #t58 = this.{self::Test2::[]}(#t57).{core::num::+}(1) in let final void #t59 = this.{self::Test2::[]=}(#t57, #t58) in #t58;
-    core::int* v11 = let final core::String* #t60 = "x" in let final core::int* #t61 = this.{self::Test2::[]}(#t60) in let final void #t62 = this.{self::Test2::[]=}(#t60, #t61.{core::num::+}(1)) in #t61;
+    core::int* v1 = let final self::Test2* #t29 = this in let final core::String* #t30 = "x" in let final core::int* #t31 = self::getInt() in let final void #t32 = #t29.{self::Test2::[]=}(#t30, #t31) in #t31;
+    core::num* v2 = let final self::Test2* #t33 = this in let final core::String* #t34 = "x" in let final core::num* #t35 = self::getNum() in let final void #t36 = #t33.{self::Test2::[]=}(#t34, #t35) in #t35;
+    core::double* v3 = let final self::Test2* #t37 = this in let final core::String* #t38 = "x" in let final core::double* #t39 = self::getDouble() in let final void #t40 = #t37.{self::Test2::[]=}(#t38, #t39) in #t39;
+    core::int* v4 = let final core::String* #t41 = "x" in let final core::int* #t42 = this.{self::Test2::[]}(#t41) in #t42.{core::num::==}(null) ?{core::int*} let final core::int* #t43 = self::getInt() in let final void #t44 = this.{self::Test2::[]=}(#t41, #t43) in #t43 : #t42;
+    core::num* v5 = let final core::String* #t45 = "x" in let final core::int* #t46 = this.{self::Test2::[]}(#t45) in #t46.{core::num::==}(null) ?{core::num*} let final core::num* #t47 = self::getNum() in let final void #t48 = this.{self::Test2::[]=}(#t45, #t47) in #t47 : #t46;
+    core::num* v6 = let final core::String* #t49 = "x" in let final core::int* #t50 = this.{self::Test2::[]}(#t49) in #t50.{core::num::==}(null) ?{core::num*} let final core::double* #t51 = self::getDouble() in let final void #t52 = this.{self::Test2::[]=}(#t49, #t51) in #t51 : #t50;
+    core::int* v7 = let final core::String* #t53 = "x" in let final core::int* #t54 = this.{self::Test2::[]}(#t53).{core::num::+}(self::getInt()) in let final void #t55 = this.{self::Test2::[]=}(#t53, #t54) in #t54;
+    core::num* v8 = let final core::String* #t56 = "x" in let final core::num* #t57 = this.{self::Test2::[]}(#t56).{core::num::+}(self::getNum()) in let final void #t58 = this.{self::Test2::[]=}(#t56, #t57) in #t57;
+    core::double* v9 = let final core::String* #t59 = "x" in let final core::double* #t60 = this.{self::Test2::[]}(#t59).{core::num::+}(self::getDouble()) in let final void #t61 = this.{self::Test2::[]=}(#t59, #t60) in #t60;
+    core::int* v10 = let final core::String* #t62 = "x" in let final core::int* #t63 = this.{self::Test2::[]}(#t62).{core::num::+}(1) in let final void #t64 = this.{self::Test2::[]=}(#t62, #t63) in #t63;
+    core::int* v11 = let final core::String* #t65 = "x" in let final core::int* #t66 = this.{self::Test2::[]}(#t65) in let final void #t67 = this.{self::Test2::[]=}(#t65, #t66.{core::num::+}(1)) in #t66;
   }
 }
 abstract class Test3 extends core::Object {
@@ -84,24 +84,24 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final core::String* #t63 = "x" in let final core::num* #t64 = self::getNum() as{TypeError} core::double* in let final void #t65 = this.{self::Test3::[]=}(#t63, #t64) in #t64;
-    core::double* v3 = let final core::String* #t66 = "x" in let final core::double* #t67 = self::getDouble() in let final void #t68 = this.{self::Test3::[]=}(#t66, #t67) in #t67;
-    core::num* v5 = let final core::String* #t69 = "x" in let final core::int* #t70 = this.{self::Test3::[]}(#t69) in #t70.{core::num::==}(null) ?{core::num*} let final core::num* #t71 = self::getNum() as{TypeError} core::double* in let final void #t72 = this.{self::Test3::[]=}(#t69, #t71) in #t71 : #t70;
-    core::num* v6 = let final core::String* #t73 = "x" in let final core::int* #t74 = this.{self::Test3::[]}(#t73) in #t74.{core::num::==}(null) ?{core::num*} let final core::double* #t75 = self::getDouble() in let final void #t76 = this.{self::Test3::[]=}(#t73, #t75) in #t75 : #t74;
-    core::int* v7 = let final core::String* #t77 = "x" in let final core::int* #t78 = let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:56:65: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    core::num* v2 = let final self::Test3* #t68 = this in let final core::String* #t69 = "x" in let final core::num* #t70 = self::getNum() as{TypeError} core::double* in let final void #t71 = #t68.{self::Test3::[]=}(#t69, #t70) in #t70;
+    core::double* v3 = let final self::Test3* #t72 = this in let final core::String* #t73 = "x" in let final core::double* #t74 = self::getDouble() in let final void #t75 = #t72.{self::Test3::[]=}(#t73, #t74) in #t74;
+    core::num* v5 = let final core::String* #t76 = "x" in let final core::int* #t77 = this.{self::Test3::[]}(#t76) in #t77.{core::num::==}(null) ?{core::num*} let final core::num* #t78 = self::getNum() as{TypeError} core::double* in let final void #t79 = this.{self::Test3::[]=}(#t76, #t78) in #t78 : #t77;
+    core::num* v6 = let final core::String* #t80 = "x" in let final core::int* #t81 = this.{self::Test3::[]}(#t80) in #t81.{core::num::==}(null) ?{core::num*} let final core::double* #t82 = self::getDouble() in let final void #t83 = this.{self::Test3::[]=}(#t80, #t82) in #t82 : #t81;
+    core::int* v7 = let final core::String* #t84 = "x" in let final core::int* #t85 = let final<BottomType> #t86 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:111: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* */ v7 = this /*@target=Test3::[]=*/ ['x'] += getInt();
-                                                                ^" in this.{self::Test3::[]}(#t77).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t80 = this.{self::Test3::[]=}(#t77, #t78) in #t78;
-    core::num* v8 = let final core::String* #t81 = "x" in let final core::num* #t82 = this.{self::Test3::[]}(#t81).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t83 = this.{self::Test3::[]=}(#t81, #t82) in #t82;
-    core::double* v9 = let final core::String* #t84 = "x" in let final core::double* #t85 = this.{self::Test3::[]}(#t84).{core::num::+}(self::getDouble()) in let final void #t86 = this.{self::Test3::[]=}(#t84, #t85) in #t85;
-    core::int* v10 = let final core::String* #t87 = "x" in let final core::int* #t88 = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:59:32: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+        /*@target=num::+*/ += getInt();
+                           ^" in this.{self::Test3::[]}(#t84).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t87 = this.{self::Test3::[]=}(#t84, #t85) in #t85;
+    core::num* v8 = let final core::String* #t88 = "x" in let final core::num* #t89 = this.{self::Test3::[]}(#t88).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t90 = this.{self::Test3::[]=}(#t88, #t89) in #t89;
+    core::double* v9 = let final core::String* #t91 = "x" in let final core::double* #t92 = this.{self::Test3::[]}(#t91).{core::num::+}(self::getDouble()) in let final void #t93 = this.{self::Test3::[]=}(#t91, #t92) in #t92;
+    core::int* v10 = let final core::String* #t94 = "x" in let final core::int* #t95 = let final<BottomType> #t96 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:121:51: 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 = ++this /*@target=Test3::[]=*/ ['x'];
-                               ^" in this.{self::Test3::[]}(#t87).{core::num::+}(1) as{TypeError} core::double* in let final void #t90 = this.{self::Test3::[]=}(#t87, #t88) in #t88;
-    core::int* v11 = let final core::String* #t91 = "x" in let final core::int* #t92 = this.{self::Test3::[]}(#t91) in let final void #t93 = this.{self::Test3::[]=}(#t91, let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:60:65: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
+                                                  ^" in this.{self::Test3::[]}(#t94).{core::num::+}(1) as{TypeError} core::double* in let final void #t97 = this.{self::Test3::[]=}(#t94, #t95) in #t95;
+    core::int* v11 = let final core::String* #t98 = "x" in let final core::int* #t99 = this.{self::Test3::[]}(#t98) in let final void #t100 = this.{self::Test3::[]=}(#t98, let final<BottomType> #t101 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:126: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* */ v11 = this /*@target=Test3::[]=*/ ['x']++;
-                                                                ^" in #t92.{core::num::+}(1) as{TypeError} core::double*) in #t92;
+        /*@target=num::+*/ ++;
+                           ^" in #t99.{core::num::+}(1) as{TypeError} core::double*) in #t99;
   }
 }
 abstract class Test4 extends core::Object {
@@ -111,14 +111,14 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t95 = "x" in let final core::int* #t96 = self::getInt() in let final void #t97 = this.{self::Test4::[]=}(#t95, #t96) in #t96;
-    core::num* v2 = let final core::String* #t98 = "x" in let final core::num* #t99 = self::getNum() as{TypeError} core::int* in let final void #t100 = this.{self::Test4::[]=}(#t98, #t99) in #t99;
-    core::num* v4 = let final core::String* #t101 = "x" in let final core::num* #t102 = this.{self::Test4::[]}(#t101) in #t102.{core::num::==}(null) ?{core::num*} let final core::int* #t103 = self::getInt() in let final void #t104 = this.{self::Test4::[]=}(#t101, #t103) in #t103 : #t102;
-    core::num* v5 = let final core::String* #t105 = "x" in let final core::num* #t106 = this.{self::Test4::[]}(#t105) in #t106.{core::num::==}(null) ?{core::num*} let final core::num* #t107 = self::getNum() as{TypeError} core::int* in let final void #t108 = this.{self::Test4::[]=}(#t105, #t107) in #t107 : #t106;
-    core::num* v7 = let final core::String* #t109 = "x" in let final core::num* #t110 = this.{self::Test4::[]}(#t109).{core::num::+}(self::getInt()) as{TypeError} core::int* in let final void #t111 = this.{self::Test4::[]=}(#t109, #t110) in #t110;
-    core::num* v8 = let final core::String* #t112 = "x" in let final core::num* #t113 = this.{self::Test4::[]}(#t112).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t114 = this.{self::Test4::[]=}(#t112, #t113) in #t113;
-    core::num* v10 = let final core::String* #t115 = "x" in let final core::num* #t116 = this.{self::Test4::[]}(#t115).{core::num::+}(1) as{TypeError} core::int* in let final void #t117 = this.{self::Test4::[]=}(#t115, #t116) in #t116;
-    core::num* v11 = let final core::String* #t118 = "x" in let final core::num* #t119 = this.{self::Test4::[]}(#t118) in let final void #t120 = this.{self::Test4::[]=}(#t118, #t119.{core::num::+}(1) as{TypeError} core::int*) in #t119;
+    core::int* v1 = let final self::Test4* #t102 = this in let final core::String* #t103 = "x" in let final core::int* #t104 = self::getInt() in let final void #t105 = #t102.{self::Test4::[]=}(#t103, #t104) in #t104;
+    core::num* v2 = let final self::Test4* #t106 = this in let final core::String* #t107 = "x" in let final core::num* #t108 = self::getNum() as{TypeError} core::int* in let final void #t109 = #t106.{self::Test4::[]=}(#t107, #t108) in #t108;
+    core::num* v4 = let final core::String* #t110 = "x" in let final core::num* #t111 = this.{self::Test4::[]}(#t110) in #t111.{core::num::==}(null) ?{core::num*} let final core::int* #t112 = self::getInt() in let final void #t113 = this.{self::Test4::[]=}(#t110, #t112) in #t112 : #t111;
+    core::num* v5 = let final core::String* #t114 = "x" in let final core::num* #t115 = this.{self::Test4::[]}(#t114) in #t115.{core::num::==}(null) ?{core::num*} let final core::num* #t116 = self::getNum() as{TypeError} core::int* in let final void #t117 = this.{self::Test4::[]=}(#t114, #t116) in #t116 : #t115;
+    core::num* v7 = let final core::String* #t118 = "x" in let final core::num* #t119 = this.{self::Test4::[]}(#t118).{core::num::+}(self::getInt()) as{TypeError} core::int* in let final void #t120 = this.{self::Test4::[]=}(#t118, #t119) in #t119;
+    core::num* v8 = let final core::String* #t121 = "x" in let final core::num* #t122 = this.{self::Test4::[]}(#t121).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t123 = this.{self::Test4::[]=}(#t121, #t122) in #t122;
+    core::num* v10 = let final core::String* #t124 = "x" in let final core::num* #t125 = this.{self::Test4::[]}(#t124).{core::num::+}(1) as{TypeError} core::int* in let final void #t126 = this.{self::Test4::[]=}(#t124, #t125) in #t125;
+    core::num* v11 = let final core::String* #t127 = "x" in let final core::num* #t128 = this.{self::Test4::[]}(#t127) in let final void #t129 = this.{self::Test4::[]=}(#t127, #t128.{core::num::+}(1) as{TypeError} core::int*) in #t128;
   }
 }
 abstract class Test5 extends core::Object {
@@ -128,17 +128,17 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t121 = "x" in let final core::int* #t122 = self::getInt() in let final void #t123 = this.{self::Test5::[]=}(#t121, #t122) in #t122;
-    core::num* v2 = let final core::String* #t124 = "x" in let final core::num* #t125 = self::getNum() in let final void #t126 = this.{self::Test5::[]=}(#t124, #t125) in #t125;
-    core::double* v3 = let final core::String* #t127 = "x" in let final core::double* #t128 = self::getDouble() in let final void #t129 = this.{self::Test5::[]=}(#t127, #t128) in #t128;
-    core::num* v4 = let final core::String* #t130 = "x" in let final core::num* #t131 = this.{self::Test5::[]}(#t130) in #t131.{core::num::==}(null) ?{core::num*} let final core::int* #t132 = self::getInt() in let final void #t133 = this.{self::Test5::[]=}(#t130, #t132) in #t132 : #t131;
-    core::num* v5 = let final core::String* #t134 = "x" in let final core::num* #t135 = this.{self::Test5::[]}(#t134) in #t135.{core::num::==}(null) ?{core::num*} let final core::num* #t136 = self::getNum() in let final void #t137 = this.{self::Test5::[]=}(#t134, #t136) in #t136 : #t135;
-    core::num* v6 = let final core::String* #t138 = "x" in let final core::num* #t139 = this.{self::Test5::[]}(#t138) in #t139.{core::num::==}(null) ?{core::num*} let final core::double* #t140 = self::getDouble() in let final void #t141 = this.{self::Test5::[]=}(#t138, #t140) in #t140 : #t139;
-    core::num* v7 = let final core::String* #t142 = "x" in let final core::num* #t143 = this.{self::Test5::[]}(#t142).{core::num::+}(self::getInt()) in let final void #t144 = this.{self::Test5::[]=}(#t142, #t143) in #t143;
-    core::num* v8 = let final core::String* #t145 = "x" in let final core::num* #t146 = this.{self::Test5::[]}(#t145).{core::num::+}(self::getNum()) in let final void #t147 = this.{self::Test5::[]=}(#t145, #t146) in #t146;
-    core::num* v9 = let final core::String* #t148 = "x" in let final core::num* #t149 = this.{self::Test5::[]}(#t148).{core::num::+}(self::getDouble()) in let final void #t150 = this.{self::Test5::[]=}(#t148, #t149) in #t149;
-    core::num* v10 = let final core::String* #t151 = "x" in let final core::num* #t152 = this.{self::Test5::[]}(#t151).{core::num::+}(1) in let final void #t153 = this.{self::Test5::[]=}(#t151, #t152) in #t152;
-    core::num* v11 = let final core::String* #t154 = "x" in let final core::num* #t155 = this.{self::Test5::[]}(#t154) in let final void #t156 = this.{self::Test5::[]=}(#t154, #t155.{core::num::+}(1)) in #t155;
+    core::int* v1 = let final self::Test5* #t130 = this in let final core::String* #t131 = "x" in let final core::int* #t132 = self::getInt() in let final void #t133 = #t130.{self::Test5::[]=}(#t131, #t132) in #t132;
+    core::num* v2 = let final self::Test5* #t134 = this in let final core::String* #t135 = "x" in let final core::num* #t136 = self::getNum() in let final void #t137 = #t134.{self::Test5::[]=}(#t135, #t136) in #t136;
+    core::double* v3 = let final self::Test5* #t138 = this in let final core::String* #t139 = "x" in let final core::double* #t140 = self::getDouble() in let final void #t141 = #t138.{self::Test5::[]=}(#t139, #t140) in #t140;
+    core::num* v4 = let final core::String* #t142 = "x" in let final core::num* #t143 = this.{self::Test5::[]}(#t142) in #t143.{core::num::==}(null) ?{core::num*} let final core::int* #t144 = self::getInt() in let final void #t145 = this.{self::Test5::[]=}(#t142, #t144) in #t144 : #t143;
+    core::num* v5 = let final core::String* #t146 = "x" in let final core::num* #t147 = this.{self::Test5::[]}(#t146) in #t147.{core::num::==}(null) ?{core::num*} let final core::num* #t148 = self::getNum() in let final void #t149 = this.{self::Test5::[]=}(#t146, #t148) in #t148 : #t147;
+    core::num* v6 = let final core::String* #t150 = "x" in let final core::num* #t151 = this.{self::Test5::[]}(#t150) in #t151.{core::num::==}(null) ?{core::num*} let final core::double* #t152 = self::getDouble() in let final void #t153 = this.{self::Test5::[]=}(#t150, #t152) in #t152 : #t151;
+    core::num* v7 = let final core::String* #t154 = "x" in let final core::num* #t155 = this.{self::Test5::[]}(#t154).{core::num::+}(self::getInt()) in let final void #t156 = this.{self::Test5::[]=}(#t154, #t155) in #t155;
+    core::num* v8 = let final core::String* #t157 = "x" in let final core::num* #t158 = this.{self::Test5::[]}(#t157).{core::num::+}(self::getNum()) in let final void #t159 = this.{self::Test5::[]=}(#t157, #t158) in #t158;
+    core::num* v9 = let final core::String* #t160 = "x" in let final core::num* #t161 = this.{self::Test5::[]}(#t160).{core::num::+}(self::getDouble()) in let final void #t162 = this.{self::Test5::[]=}(#t160, #t161) in #t161;
+    core::num* v10 = let final core::String* #t163 = "x" in let final core::num* #t164 = this.{self::Test5::[]}(#t163).{core::num::+}(1) in let final void #t165 = this.{self::Test5::[]=}(#t163, #t164) in #t164;
+    core::num* v11 = let final core::String* #t166 = "x" in let final core::num* #t167 = this.{self::Test5::[]}(#t166) in let final void #t168 = this.{self::Test5::[]=}(#t166, #t167.{core::num::+}(1)) in #t167;
   }
 }
 abstract class Test6 extends core::Object {
@@ -148,15 +148,15 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final core::String* #t157 = "x" in let final core::num* #t158 = self::getNum() as{TypeError} core::double* in let final void #t159 = this.{self::Test6::[]=}(#t157, #t158) in #t158;
-    core::double* v3 = let final core::String* #t160 = "x" in let final core::double* #t161 = self::getDouble() in let final void #t162 = this.{self::Test6::[]=}(#t160, #t161) in #t161;
-    core::num* v5 = let final core::String* #t163 = "x" in let final core::num* #t164 = this.{self::Test6::[]}(#t163) in #t164.{core::num::==}(null) ?{core::num*} let final core::num* #t165 = self::getNum() as{TypeError} core::double* in let final void #t166 = this.{self::Test6::[]=}(#t163, #t165) in #t165 : #t164;
-    core::num* v6 = let final core::String* #t167 = "x" in let final core::num* #t168 = this.{self::Test6::[]}(#t167) in #t168.{core::num::==}(null) ?{core::num*} let final core::double* #t169 = self::getDouble() in let final void #t170 = this.{self::Test6::[]=}(#t167, #t169) in #t169 : #t168;
-    core::num* v7 = let final core::String* #t171 = "x" in let final core::num* #t172 = this.{self::Test6::[]}(#t171).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t173 = this.{self::Test6::[]=}(#t171, #t172) in #t172;
-    core::num* v8 = let final core::String* #t174 = "x" in let final core::num* #t175 = this.{self::Test6::[]}(#t174).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t176 = this.{self::Test6::[]=}(#t174, #t175) in #t175;
-    core::num* v9 = let final core::String* #t177 = "x" in let final core::num* #t178 = this.{self::Test6::[]}(#t177).{core::num::+}(self::getDouble()) as{TypeError} core::double* in let final void #t179 = this.{self::Test6::[]=}(#t177, #t178) in #t178;
-    core::num* v10 = let final core::String* #t180 = "x" in let final core::num* #t181 = this.{self::Test6::[]}(#t180).{core::num::+}(1) as{TypeError} core::double* in let final void #t182 = this.{self::Test6::[]=}(#t180, #t181) in #t181;
-    core::num* v11 = let final core::String* #t183 = "x" in let final core::num* #t184 = this.{self::Test6::[]}(#t183) in let final void #t185 = this.{self::Test6::[]=}(#t183, #t184.{core::num::+}(1) as{TypeError} core::double*) in #t184;
+    core::num* v2 = let final self::Test6* #t169 = this in let final core::String* #t170 = "x" in let final core::num* #t171 = self::getNum() as{TypeError} core::double* in let final void #t172 = #t169.{self::Test6::[]=}(#t170, #t171) in #t171;
+    core::double* v3 = let final self::Test6* #t173 = this in let final core::String* #t174 = "x" in let final core::double* #t175 = self::getDouble() in let final void #t176 = #t173.{self::Test6::[]=}(#t174, #t175) in #t175;
+    core::num* v5 = let final core::String* #t177 = "x" in let final core::num* #t178 = this.{self::Test6::[]}(#t177) in #t178.{core::num::==}(null) ?{core::num*} let final core::num* #t179 = self::getNum() as{TypeError} core::double* in let final void #t180 = this.{self::Test6::[]=}(#t177, #t179) in #t179 : #t178;
+    core::num* v6 = let final core::String* #t181 = "x" in let final core::num* #t182 = this.{self::Test6::[]}(#t181) in #t182.{core::num::==}(null) ?{core::num*} let final core::double* #t183 = self::getDouble() in let final void #t184 = this.{self::Test6::[]=}(#t181, #t183) in #t183 : #t182;
+    core::num* v7 = let final core::String* #t185 = "x" in let final core::num* #t186 = this.{self::Test6::[]}(#t185).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t187 = this.{self::Test6::[]=}(#t185, #t186) in #t186;
+    core::num* v8 = let final core::String* #t188 = "x" in let final core::num* #t189 = this.{self::Test6::[]}(#t188).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t190 = this.{self::Test6::[]=}(#t188, #t189) in #t189;
+    core::num* v9 = let final core::String* #t191 = "x" in let final core::num* #t192 = this.{self::Test6::[]}(#t191).{core::num::+}(self::getDouble()) as{TypeError} core::double* in let final void #t193 = this.{self::Test6::[]=}(#t191, #t192) in #t192;
+    core::num* v10 = let final core::String* #t194 = "x" in let final core::num* #t195 = this.{self::Test6::[]}(#t194).{core::num::+}(1) as{TypeError} core::double* in let final void #t196 = this.{self::Test6::[]=}(#t194, #t195) in #t195;
+    core::num* v11 = let final core::String* #t197 = "x" in let final core::num* #t198 = this.{self::Test6::[]}(#t197) in let final void #t199 = this.{self::Test6::[]=}(#t197, #t198.{core::num::+}(1) as{TypeError} core::double*) in #t198;
   }
 }
 abstract class Test7 extends core::Object {
@@ -166,26 +166,26 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t186 = "x" in let final core::int* #t187 = self::getInt() in let final void #t188 = this.{self::Test7::[]=}(#t186, #t187) in #t187;
-    core::num* v2 = let final core::String* #t189 = "x" in let final core::num* #t190 = self::getNum() as{TypeError} core::int* in let final void #t191 = this.{self::Test7::[]=}(#t189, #t190) in #t190;
-    core::num* v4 = let final core::String* #t192 = "x" in let final core::double* #t193 = this.{self::Test7::[]}(#t192) in #t193.{core::num::==}(null) ?{core::num*} let final core::int* #t194 = self::getInt() in let final void #t195 = this.{self::Test7::[]=}(#t192, #t194) in #t194 : #t193;
-    core::num* v5 = let final core::String* #t196 = "x" in let final core::double* #t197 = this.{self::Test7::[]}(#t196) in #t197.{core::num::==}(null) ?{core::num*} let final core::num* #t198 = self::getNum() as{TypeError} core::int* in let final void #t199 = this.{self::Test7::[]=}(#t196, #t198) in #t198 : #t197;
-    core::double* v7 = let final core::String* #t200 = "x" in let final core::double* #t201 = let final<BottomType> #t202 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:125:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+    core::int* v1 = let final self::Test7* #t200 = this in let final core::String* #t201 = "x" in let final core::int* #t202 = self::getInt() in let final void #t203 = #t200.{self::Test7::[]=}(#t201, #t202) in #t202;
+    core::num* v2 = let final self::Test7* #t204 = this in let final core::String* #t205 = "x" in let final core::num* #t206 = self::getNum() as{TypeError} core::int* in let final void #t207 = #t204.{self::Test7::[]=}(#t205, #t206) in #t206;
+    core::num* v4 = let final core::String* #t208 = "x" in let final core::double* #t209 = this.{self::Test7::[]}(#t208) in #t209.{core::num::==}(null) ?{core::num*} let final core::int* #t210 = self::getInt() in let final void #t211 = this.{self::Test7::[]=}(#t208, #t210) in #t210 : #t209;
+    core::num* v5 = let final core::String* #t212 = "x" in let final core::double* #t213 = this.{self::Test7::[]}(#t212) in #t213.{core::num::==}(null) ?{core::num*} let final core::num* #t214 = self::getNum() as{TypeError} core::int* in let final void #t215 = this.{self::Test7::[]=}(#t212, #t214) in #t214 : #t213;
+    core::double* v7 = let final core::String* #t216 = "x" in let final core::double* #t217 = let final<BottomType> #t218 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:268: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* */ v7 = this /*@target=Test7::[]=*/ ['x'] += getInt();
-                                                                   ^" in this.{self::Test7::[]}(#t200).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t203 = this.{self::Test7::[]=}(#t200, #t201) in #t201;
-    core::double* v8 = let final core::String* #t204 = "x" in let final core::double* #t205 = let final<BottomType> #t206 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:126:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+        /*@target=double::+*/ += getInt();
+                              ^" in this.{self::Test7::[]}(#t216).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t219 = this.{self::Test7::[]=}(#t216, #t217) in #t217;
+    core::double* v8 = let final core::String* #t220 = "x" in let final core::double* #t221 = let final<BottomType> #t222 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:272: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* */ v8 = this /*@target=Test7::[]=*/ ['x'] += getNum();
-                                                                   ^" in this.{self::Test7::[]}(#t204).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t207 = this.{self::Test7::[]=}(#t204, #t205) in #t205;
-    core::double* v10 = let final core::String* #t208 = "x" in let final core::double* #t209 = let final<BottomType> #t210 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:127:35: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+        /*@target=double::+*/ += getNum();
+                              ^" in this.{self::Test7::[]}(#t220).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t223 = this.{self::Test7::[]=}(#t220, #t221) in #t221;
+    core::double* v10 = let final core::String* #t224 = "x" in let final core::double* #t225 = let final<BottomType> #t226 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:274:57: 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 = ++this /*@target=Test7::[]=*/ ['x'];
-                                  ^" in this.{self::Test7::[]}(#t208).{core::double::+}(1) as{TypeError} core::int* in let final void #t211 = this.{self::Test7::[]=}(#t208, #t209) in #t209;
-    core::double* v11 = let final core::String* #t212 = "x" in let final core::double* #t213 = this.{self::Test7::[]}(#t212) in let final void #t214 = this.{self::Test7::[]=}(#t212, let final<BottomType> #t215 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:128:68: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+    var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
+                                                        ^" in this.{self::Test7::[]}(#t224).{core::double::+}(1) as{TypeError} core::int* in let final void #t227 = this.{self::Test7::[]=}(#t224, #t225) in #t225;
+    core::double* v11 = let final core::String* #t228 = "x" in let final core::double* #t229 = this.{self::Test7::[]}(#t228) in let final void #t230 = this.{self::Test7::[]=}(#t228, let final<BottomType> #t231 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:279: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* */ v11 = this /*@target=Test7::[]=*/ ['x']++;
-                                                                   ^" in #t213.{core::double::+}(1) as{TypeError} core::int*) in #t213;
+        /*@target=double::+*/ ++;
+                              ^" in #t229.{core::double::+}(1) as{TypeError} core::int*) in #t229;
   }
 }
 abstract class Test8 extends core::Object {
@@ -195,17 +195,17 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final core::String* #t216 = "x" in let final core::int* #t217 = self::getInt() in let final void #t218 = this.{self::Test8::[]=}(#t216, #t217) in #t217;
-    core::num* v2 = let final core::String* #t219 = "x" in let final core::num* #t220 = self::getNum() in let final void #t221 = this.{self::Test8::[]=}(#t219, #t220) in #t220;
-    core::double* v3 = let final core::String* #t222 = "x" in let final core::double* #t223 = self::getDouble() in let final void #t224 = this.{self::Test8::[]=}(#t222, #t223) in #t223;
-    core::num* v4 = let final core::String* #t225 = "x" in let final core::double* #t226 = this.{self::Test8::[]}(#t225) in #t226.{core::num::==}(null) ?{core::num*} let final core::int* #t227 = self::getInt() in let final void #t228 = this.{self::Test8::[]=}(#t225, #t227) in #t227 : #t226;
-    core::num* v5 = let final core::String* #t229 = "x" in let final core::double* #t230 = this.{self::Test8::[]}(#t229) in #t230.{core::num::==}(null) ?{core::num*} let final core::num* #t231 = self::getNum() in let final void #t232 = this.{self::Test8::[]=}(#t229, #t231) in #t231 : #t230;
-    core::double* v6 = let final core::String* #t233 = "x" in let final core::double* #t234 = this.{self::Test8::[]}(#t233) in #t234.{core::num::==}(null) ?{core::double*} let final core::double* #t235 = self::getDouble() in let final void #t236 = this.{self::Test8::[]=}(#t233, #t235) in #t235 : #t234;
-    core::double* v7 = let final core::String* #t237 = "x" in let final core::double* #t238 = this.{self::Test8::[]}(#t237).{core::double::+}(self::getInt()) in let final void #t239 = this.{self::Test8::[]=}(#t237, #t238) in #t238;
-    core::double* v8 = let final core::String* #t240 = "x" in let final core::double* #t241 = this.{self::Test8::[]}(#t240).{core::double::+}(self::getNum()) in let final void #t242 = this.{self::Test8::[]=}(#t240, #t241) in #t241;
-    core::double* v9 = let final core::String* #t243 = "x" in let final core::double* #t244 = this.{self::Test8::[]}(#t243).{core::double::+}(self::getDouble()) in let final void #t245 = this.{self::Test8::[]=}(#t243, #t244) in #t244;
-    core::double* v10 = let final core::String* #t246 = "x" in let final core::double* #t247 = this.{self::Test8::[]}(#t246).{core::double::+}(1) in let final void #t248 = this.{self::Test8::[]=}(#t246, #t247) in #t247;
-    core::double* v11 = let final core::String* #t249 = "x" in let final core::double* #t250 = this.{self::Test8::[]}(#t249) in let final void #t251 = this.{self::Test8::[]=}(#t249, #t250.{core::double::+}(1)) in #t250;
+    core::int* v1 = let final self::Test8* #t232 = this in let final core::String* #t233 = "x" in let final core::int* #t234 = self::getInt() in let final void #t235 = #t232.{self::Test8::[]=}(#t233, #t234) in #t234;
+    core::num* v2 = let final self::Test8* #t236 = this in let final core::String* #t237 = "x" in let final core::num* #t238 = self::getNum() in let final void #t239 = #t236.{self::Test8::[]=}(#t237, #t238) in #t238;
+    core::double* v3 = let final self::Test8* #t240 = this in let final core::String* #t241 = "x" in let final core::double* #t242 = self::getDouble() in let final void #t243 = #t240.{self::Test8::[]=}(#t241, #t242) in #t242;
+    core::num* v4 = let final core::String* #t244 = "x" in let final core::double* #t245 = this.{self::Test8::[]}(#t244) in #t245.{core::num::==}(null) ?{core::num*} let final core::int* #t246 = self::getInt() in let final void #t247 = this.{self::Test8::[]=}(#t244, #t246) in #t246 : #t245;
+    core::num* v5 = let final core::String* #t248 = "x" in let final core::double* #t249 = this.{self::Test8::[]}(#t248) in #t249.{core::num::==}(null) ?{core::num*} let final core::num* #t250 = self::getNum() in let final void #t251 = this.{self::Test8::[]=}(#t248, #t250) in #t250 : #t249;
+    core::double* v6 = let final core::String* #t252 = "x" in let final core::double* #t253 = this.{self::Test8::[]}(#t252) in #t253.{core::num::==}(null) ?{core::double*} let final core::double* #t254 = self::getDouble() in let final void #t255 = this.{self::Test8::[]=}(#t252, #t254) in #t254 : #t253;
+    core::double* v7 = let final core::String* #t256 = "x" in let final core::double* #t257 = this.{self::Test8::[]}(#t256).{core::double::+}(self::getInt()) in let final void #t258 = this.{self::Test8::[]=}(#t256, #t257) in #t257;
+    core::double* v8 = let final core::String* #t259 = "x" in let final core::double* #t260 = this.{self::Test8::[]}(#t259).{core::double::+}(self::getNum()) in let final void #t261 = this.{self::Test8::[]=}(#t259, #t260) in #t260;
+    core::double* v9 = let final core::String* #t262 = "x" in let final core::double* #t263 = this.{self::Test8::[]}(#t262).{core::double::+}(self::getDouble()) in let final void #t264 = this.{self::Test8::[]=}(#t262, #t263) in #t263;
+    core::double* v10 = let final core::String* #t265 = "x" in let final core::double* #t266 = this.{self::Test8::[]}(#t265).{core::double::+}(1) in let final void #t267 = this.{self::Test8::[]=}(#t265, #t266) in #t266;
+    core::double* v11 = let final core::String* #t268 = "x" in let final core::double* #t269 = this.{self::Test8::[]}(#t268) in let final void #t270 = this.{self::Test8::[]=}(#t268, #t269.{core::double::+}(1)) in #t269;
   }
 }
 abstract class Test9 extends core::Object {
@@ -215,15 +215,15 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final core::String* #t252 = "x" in let final core::num* #t253 = self::getNum() as{TypeError} core::double* in let final void #t254 = this.{self::Test9::[]=}(#t252, #t253) in #t253;
-    core::double* v3 = let final core::String* #t255 = "x" in let final core::double* #t256 = self::getDouble() in let final void #t257 = this.{self::Test9::[]=}(#t255, #t256) in #t256;
-    core::num* v5 = let final core::String* #t258 = "x" in let final core::double* #t259 = this.{self::Test9::[]}(#t258) in #t259.{core::num::==}(null) ?{core::num*} let final core::num* #t260 = self::getNum() as{TypeError} core::double* in let final void #t261 = this.{self::Test9::[]=}(#t258, #t260) in #t260 : #t259;
-    core::double* v6 = let final core::String* #t262 = "x" in let final core::double* #t263 = this.{self::Test9::[]}(#t262) in #t263.{core::num::==}(null) ?{core::double*} let final core::double* #t264 = self::getDouble() in let final void #t265 = this.{self::Test9::[]=}(#t262, #t264) in #t264 : #t263;
-    core::double* v7 = let final core::String* #t266 = "x" in let final core::double* #t267 = this.{self::Test9::[]}(#t266).{core::double::+}(self::getInt()) in let final void #t268 = this.{self::Test9::[]=}(#t266, #t267) in #t267;
-    core::double* v8 = let final core::String* #t269 = "x" in let final core::double* #t270 = this.{self::Test9::[]}(#t269).{core::double::+}(self::getNum()) in let final void #t271 = this.{self::Test9::[]=}(#t269, #t270) in #t270;
-    core::double* v9 = let final core::String* #t272 = "x" in let final core::double* #t273 = this.{self::Test9::[]}(#t272).{core::double::+}(self::getDouble()) in let final void #t274 = this.{self::Test9::[]=}(#t272, #t273) in #t273;
-    core::double* v10 = let final core::String* #t275 = "x" in let final core::double* #t276 = this.{self::Test9::[]}(#t275).{core::double::+}(1) in let final void #t277 = this.{self::Test9::[]=}(#t275, #t276) in #t276;
-    core::double* v11 = let final core::String* #t278 = "x" in let final core::double* #t279 = this.{self::Test9::[]}(#t278) in let final void #t280 = this.{self::Test9::[]=}(#t278, #t279.{core::double::+}(1)) in #t279;
+    core::num* v2 = let final self::Test9* #t271 = this in let final core::String* #t272 = "x" in let final core::num* #t273 = self::getNum() as{TypeError} core::double* in let final void #t274 = #t271.{self::Test9::[]=}(#t272, #t273) in #t273;
+    core::double* v3 = let final self::Test9* #t275 = this in let final core::String* #t276 = "x" in let final core::double* #t277 = self::getDouble() in let final void #t278 = #t275.{self::Test9::[]=}(#t276, #t277) in #t277;
+    core::num* v5 = let final core::String* #t279 = "x" in let final core::double* #t280 = this.{self::Test9::[]}(#t279) in #t280.{core::num::==}(null) ?{core::num*} let final core::num* #t281 = self::getNum() as{TypeError} core::double* in let final void #t282 = this.{self::Test9::[]=}(#t279, #t281) in #t281 : #t280;
+    core::double* v6 = let final core::String* #t283 = "x" in let final core::double* #t284 = this.{self::Test9::[]}(#t283) in #t284.{core::num::==}(null) ?{core::double*} let final core::double* #t285 = self::getDouble() in let final void #t286 = this.{self::Test9::[]=}(#t283, #t285) in #t285 : #t284;
+    core::double* v7 = let final core::String* #t287 = "x" in let final core::double* #t288 = this.{self::Test9::[]}(#t287).{core::double::+}(self::getInt()) in let final void #t289 = this.{self::Test9::[]=}(#t287, #t288) in #t288;
+    core::double* v8 = let final core::String* #t290 = "x" in let final core::double* #t291 = this.{self::Test9::[]}(#t290).{core::double::+}(self::getNum()) in let final void #t292 = this.{self::Test9::[]=}(#t290, #t291) in #t291;
+    core::double* v9 = let final core::String* #t293 = "x" in let final core::double* #t294 = this.{self::Test9::[]}(#t293).{core::double::+}(self::getDouble()) in let final void #t295 = this.{self::Test9::[]=}(#t293, #t294) in #t294;
+    core::double* v10 = let final core::String* #t296 = "x" in let final core::double* #t297 = this.{self::Test9::[]}(#t296).{core::double::+}(1) in let final void #t298 = this.{self::Test9::[]=}(#t296, #t297) in #t297;
+    core::double* v11 = let final core::String* #t299 = "x" in let final core::double* #t300 = this.{self::Test9::[]}(#t299) in let final void #t301 = this.{self::Test9::[]=}(#t299, #t300.{core::double::+}(1)) in #t300;
   }
 }
 static method getInt() → core::int*
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 dee0c7d..b758ab5 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
@@ -19,13 +19,11 @@
 
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
 
-  var /*@ type=int* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=int* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
   var /*@ type=int* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -49,17 +47,14 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=int* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=int* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
-  var /*@ type=num* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+  var /*@ type=num* */ v6 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=int* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -85,13 +80,11 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
-  var /*@ type=num* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+  var /*@ type=num* */ v6 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=int* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -117,13 +110,11 @@
 
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
 
-  var /*@ type=num* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=num* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
   var /*@ type=num* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -147,17 +138,14 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=num* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=num* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
-  var /*@ type=num* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+  var /*@ type=num* */ v6 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=num* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -183,13 +171,11 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
-  var /*@ type=num* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+  var /*@ type=num* */ v6 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=num* */ v7 =
       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
@@ -215,13 +201,11 @@
 
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
 
-  var /*@ type=num* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=num* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
   var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
       'x'] /*@ target=double::+ */ += getInt();
@@ -244,17 +228,15 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=num* */ v4 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getInt();
+  var /*@ type=num* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getInt();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
   var /*@ type=double* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+          /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
       'x'] /*@ target=double::+ */ += getInt();
@@ -278,13 +260,12 @@
 
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
 
-  var /*@ type=num* */ v5 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getNum();
+  var /*@ type=num* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+      /*@target=num::==*/ ??= getNum();
 
   var /*@ type=double* */ v6 =
-      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
-          getDouble();
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x']
+          /*@target=num::==*/ ??= getDouble();
 
   var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
       'x'] /*@ target=double::+ */ += getInt();
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 6e5b788..7ee2c5a 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,37 +2,37 @@
 //
 // Problems in library:
 //
-// 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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:90: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'.
 //       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
 //                                                                               ^
 //
-// 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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:102: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'.
 //       /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
 //                            ^
 //
-// 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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:105: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'.
 //       'x'] /*@ target=num::+ */ ++;
 //                                 ^
 //
-// 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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:211: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::+ */ += 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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:214: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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:217: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'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:221: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::+ */ ++;
 //                                    ^
@@ -81,17 +81,17 @@
   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:97:79: 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:90: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'.
       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:109:28: 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:102: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'.
       /*@ 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'.
+  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:105: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'.
       'x'] /*@ target=num::+ */ ++;
                                 ^" in #t120.{core::num::+}(1) as{TypeError} core::double*) in #t120;
@@ -135,19 +135,19 @@
   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:227:36: 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:211: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::+ */ += 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'.
+  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:214: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();
                                    ^" 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'.
+  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:217: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
                               ^" 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'.
+  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:221: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::+ */ ++;
                                    ^" in #t277.{core::double::+}(1) as{TypeError} core::int*) in #t277;
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 05354e5..ddc5083 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
@@ -21,21 +21,35 @@
 void test() {
   B local;
   local = /*@ typeArgs=B* */ f();
-  local ??= /*@ typeArgs=B* */ f();
+
+  local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
   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* */ v2 =
+      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
   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::- */ --;
 }
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 7113cbf..64f43c5 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
@@ -1,42 +1,42 @@
 pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:23:9: Context: Write to local@474
   local = /*@ typeArgs=B* */ f();
         ^
-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:28: Context: Write to local@474
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:25:34: Context: Write to local@474
+  local /*@ target=Object::== */ ??= /*@ 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=C* */ f();
                            ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:26:28: Context: Write to local@474
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:29: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:31: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:33: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:35: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:37: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:33:26: Context: Write to local@474
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:40:38: Context: Write to local@474
+      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+                                     ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:43: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:46: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:49: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:51: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:54: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 b88af64..e8b79a0 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
@@ -11,40 +11,65 @@
 
 void test1(int t) {
   var /*@ type=int* */ v1 = t = getInt();
+
   var /*@ type=num* */ v2 = t = getNum();
-  var /*@ type=int* */ v4 = t ??= getInt();
-  var /*@ type=num* */ v5 = t ??= getNum();
+
+  var /*@ type=int* */ v4 = t /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+
   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) {
   var /*@ type=int* */ v1 = t = getInt();
+
   var /*@ type=num* */ v2 = t = getNum();
+
   var /*@ type=double* */ v3 = t = getDouble();
-  var /*@ type=num* */ v4 = t ??= getInt();
-  var /*@ type=num* */ v5 = t ??= getNum();
-  var /*@ type=num* */ v6 = t ??= getDouble();
+
+  var /*@ type=num* */ v4 = t /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=num* */ v6 = t /*@ target=num::== */ ??= getDouble();
+
   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=num* */ v2 = t = getNum();
+
   var /*@ type=double* */ v3 = t = getDouble();
-  var /*@ type=num* */ v5 = t ??= getNum();
-  var /*@ type=double* */ v6 = t ??= getDouble();
+
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=double* */ v6 = t /*@ target=num::== */ ??= getDouble();
+
   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::+ */ ++;
 }
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 e076b03..db044b6 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
@@ -1,84 +1,84 @@
 pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:13:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:14:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:15:31: Context: Write to t@343
   var /*@ type=num* */ v2 = t = getNum();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:15:31: Context: Write to t@343
-  var /*@ type=int* */ v4 = t ??= getInt();
-                              ^^^
-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:52: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:17:53: Context: Write to t@343
+  var /*@ type=int* */ v4 = t /*@ target=num::== */ ??= getInt();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:19:53: Context: Write to t@343
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:21: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:23: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:25: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:28: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:32:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:34:31: Context: Write to t@343
   var /*@ type=num* */ v2 = t = getNum();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:27:34: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:36:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
-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:29:31: Context: Write to t@343
-  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* */ v6 = t ??= getDouble();
-                              ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:31:52: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:38:53: Context: Write to t@343
+  var /*@ type=num* */ v4 = t /*@ target=num::== */ ??= getInt();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:40:53: Context: Write to t@343
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:42:53: Context: Write to t@343
+  var /*@ type=num* */ v6 = t /*@ target=num::== */ ??= getDouble();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:44: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:46: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:48: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:50: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:53: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:57:31: Context: Write to t@343
   var /*@ type=num* */ v2 = 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:59:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
-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: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:44:58: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:61:53: Context: Write to t@343
+  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
+                                                    ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:63:56: Context: Write to t@343
+  var /*@ type=double* */ v6 = t /*@ target=num::== */ ??= getDouble();
+                                                       ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:65: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:67: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:69: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:71: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
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:74: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_null_aware.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart
index b2b1f77..0833acd 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
@@ -24,25 +24,60 @@
   static void test(Test t) {
     /*@ 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();
-    t?. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --t?. /*@target=Test::member*/ member;
-    t?. /*@target=Test::member*/ member--;
+
+    /*@target=Object::==*/ t?.
+            /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+
+    /*@target=Object::==*/ t?.
+            /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    /*@target=Object::==*/ t?.
+            /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    /*@target=Object::==*/ t?.
+            /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ -- /*@target=Object::==*/ t?.
+        /*@target=Test::member*/ /*@target=Test::member*/ member;
+
+    /*@target=Object::==*/ t?.
+            /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 =
         /*@ type=Test* */ /*@target=Object::==*/ t
             ?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
+
     var /*@ type=B* */ v2 =
-        t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+        /*@target=Object::==*/ 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();
+        /*@target=Object::==*/ 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();
+        /*@target=Object::==*/ 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--;
+        /*@target=Object::==*/ t
+                ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = /*@ target=B::- */ -- /*@target=Object::==*/ t
+        ?. /*@target=Test::member*/ /*@target=Test::member*/ member;
+
+    var /*@ type=B* */ v7 = /*@target=Object::==*/ t
+            ?. /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
   }
 }
 
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 52f7978..60aa66d 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
@@ -32,19 +32,19 @@
     ;
   static method test(self::Test* t) → void {
     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.{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*);
-    self::C* v5 = let final self::Test* #t13 = t in #t13.==(null) ?{self::C*} null : #t13.{self::Test::member} = #t13.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
-    self::B* v6 = let final self::Test* #t14 = t in #t14.==(null) ?{self::B*} null : #t14.{self::Test::member} = #t14.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t15 = t in #t15.==(null) ?{self::B*} null : let final self::B* #t16 = #t15.{self::Test::member} in let final self::B* #t17 = #t15.{self::Test::member} = #t16.{self::B::-}(1) in #t16;
+    let final self::Test* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t4 = t in #t4.{core::Object::==}(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t5 = t in #t5.{core::Object::==}(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    let final self::Test* #t6 = t in #t6.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t7 = #t6.{self::Test::member}.{self::B::-}(1) in let final void #t8 = #t6.{self::Test::member} = #t7 in #t7;
+    let final self::Test* #t9 = t in #t9.{core::Object::==}(null) ?{self::B*} null : #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::-}(1);
+    self::B* v1 = let final self::Test* #t10 = t in #t10.{core::Object::==}(null) ?{self::B*} null : #t10.{self::Test::member} = self::f<self::B*>();
+    self::B* v2 = let final self::Test* #t11 = t in #t11.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t12 = #t11.{self::Test::member} in #t12.{core::Object::==}(null) ?{self::B*} #t11.{self::Test::member} = self::f<self::B*>() : #t12;
+    self::A* v3 = let final self::Test* #t13 = t in #t13.{core::Object::==}(null) ?{self::A*} null : let final self::A* #t14 = #t13.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t15 = #t13.{self::Test::member} = #t14 in #t14;
+    self::B* v4 = let final self::Test* #t16 = t in #t16.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t17 = #t16.{self::Test::member}.{self::B::*}(self::f<self::B*>()) in let final void #t18 = #t16.{self::Test::member} = #t17 in #t17;
+    self::C* v5 = let final self::Test* #t19 = t in #t19.{core::Object::==}(null) ?{self::C*} null : let final self::C* #t20 = #t19.{self::Test::member}.{self::B::&}(self::f<self::A*>()) in let final void #t21 = #t19.{self::Test::member} = #t20 in #t20;
+    self::B* v6 = let final self::Test* #t22 = t in #t22.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t23 = #t22.{self::Test::member}.{self::B::-}(1) in let final void #t24 = #t22.{self::Test::member} = #t23 in #t23;
+    self::B* v7 = let final self::Test* #t25 = t in #t25.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t26 = #t25.{self::Test::member} in let final void #t27 = #t25.{self::Test::member} = #t26.{self::B::-}(1) in #t26;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
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 52f7978..60aa66d 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
@@ -32,19 +32,19 @@
     ;
   static method test(self::Test* t) → void {
     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.{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*);
-    self::C* v5 = let final self::Test* #t13 = t in #t13.==(null) ?{self::C*} null : #t13.{self::Test::member} = #t13.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
-    self::B* v6 = let final self::Test* #t14 = t in #t14.==(null) ?{self::B*} null : #t14.{self::Test::member} = #t14.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t15 = t in #t15.==(null) ?{self::B*} null : let final self::B* #t16 = #t15.{self::Test::member} in let final self::B* #t17 = #t15.{self::Test::member} = #t16.{self::B::-}(1) in #t16;
+    let final self::Test* #t2 = t in #t2.{core::Object::==}(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.{core::Object::==}(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t4 = t in #t4.{core::Object::==}(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t5 = t in #t5.{core::Object::==}(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    let final self::Test* #t6 = t in #t6.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t7 = #t6.{self::Test::member}.{self::B::-}(1) in let final void #t8 = #t6.{self::Test::member} = #t7 in #t7;
+    let final self::Test* #t9 = t in #t9.{core::Object::==}(null) ?{self::B*} null : #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::-}(1);
+    self::B* v1 = let final self::Test* #t10 = t in #t10.{core::Object::==}(null) ?{self::B*} null : #t10.{self::Test::member} = self::f<self::B*>();
+    self::B* v2 = let final self::Test* #t11 = t in #t11.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t12 = #t11.{self::Test::member} in #t12.{core::Object::==}(null) ?{self::B*} #t11.{self::Test::member} = self::f<self::B*>() : #t12;
+    self::A* v3 = let final self::Test* #t13 = t in #t13.{core::Object::==}(null) ?{self::A*} null : let final self::A* #t14 = #t13.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t15 = #t13.{self::Test::member} = #t14 in #t14;
+    self::B* v4 = let final self::Test* #t16 = t in #t16.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t17 = #t16.{self::Test::member}.{self::B::*}(self::f<self::B*>()) in let final void #t18 = #t16.{self::Test::member} = #t17 in #t17;
+    self::C* v5 = let final self::Test* #t19 = t in #t19.{core::Object::==}(null) ?{self::C*} null : let final self::C* #t20 = #t19.{self::Test::member}.{self::B::&}(self::f<self::A*>()) in let final void #t21 = #t19.{self::Test::member} = #t20 in #t20;
+    self::B* v6 = let final self::Test* #t22 = t in #t22.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t23 = #t22.{self::Test::member}.{self::B::-}(1) in let final void #t24 = #t22.{self::Test::member} = #t23 in #t23;
+    self::B* v7 = let final self::Test* #t25 = t in #t25.{core::Object::==}(null) ?{self::B*} null : let final self::B* #t26 = #t25.{self::Test::member} in let final void #t27 = #t25.{self::Test::member} = #t26.{self::B::-}(1) in #t26;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
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 a8d4387..75ea000 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
@@ -15,14 +15,33 @@
   static void test(Test1 t) {
     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();
-    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 = /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 = /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=int* */ v7 = /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 = /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::+ */ += getNum();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++
+        /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop;
+
+    var /*@ type=int* */ v11 = /*@target=Object::==*/ t?.
+            /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::+ */ ++;
   }
 }
 
@@ -32,18 +51,43 @@
   static void test(Test2 t) {
     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();
-    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 = /*@target=Object::==*/ t?.
+            /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 = /*@target=Object::==*/ t?.
+            /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 = /*@target=Object::==*/ t?.
+            /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=num* */ v7 = /*@target=Object::==*/ t?.
+            /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 = /*@target=Object::==*/ t?.
+            /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ += getNum();
+
+    var /*@ type=num* */ v9 = /*@target=Object::==*/ t?.
+        /*@target=Test2::prop*/ /*@target=Test2::prop*/
+        prop /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++ /*@target=Object::==*/
+        t?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop;
+
+    var /*@ type=num* */ v11 = /*@target=Object::==*/
+        t?. /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ ++;
   }
 }
 
@@ -53,17 +97,39 @@
   static void test3(Test3 t) {
     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=num* */ v5 = /*@target=Object::==*/ t?.
+            /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=num::== */ ??= 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();
+        /*@target=Object::==*/ t?.
+                /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=double* */ v7 = /*@target=Object::==*/ t?.
+            /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 = /*@target=Object::==*/ t?.
+            /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ += 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++;
+        /*@target=Object::==*/ t?.
+                /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@ target=double::+ */ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++
+        /*@target=Object::==*/ t?.
+            /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop;
+
+    var /*@ type=double* */ v11 = /*@target=Object::==*/
+        t?. /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ ++;
   }
 }
 
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 da54b4b..97a828a 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
@@ -10,12 +10,12 @@
   static method test(self::Test1* t) → void {
     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());
-    core::num* v8 = let final self::Test1* #t8 = t in #t8.==(null) ?{core::num*} null : #t8.{self::Test1::prop} = #t8.{self::Test1::prop}.{core::num::+}(self::getNum()) as{TypeError} core::int*;
-    core::int* v10 = let final self::Test1* #t9 = t in #t9.==(null) ?{core::int*} null : #t9.{self::Test1::prop} = #t9.{self::Test1::prop}.{core::num::+}(1);
-    core::int* v11 = let final self::Test1* #t10 = t in #t10.==(null) ?{core::int*} null : let final core::int* #t11 = #t10.{self::Test1::prop} in let final core::int* #t12 = #t10.{self::Test1::prop} = #t11.{core::num::+}(1) in #t11;
+    core::int* v4 = let final self::Test1* #t3 = t in #t3.{core::Object::==}(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.{core::Object::==}(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.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t8 = #t7.{self::Test1::prop}.{core::num::+}(self::getInt()) in let final void #t9 = #t7.{self::Test1::prop} = #t8 in #t8;
+    core::num* v8 = let final self::Test1* #t10 = t in #t10.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t11 = #t10.{self::Test1::prop}.{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t12 = #t10.{self::Test1::prop} = #t11 in #t11;
+    core::int* v10 = let final self::Test1* #t13 = t in #t13.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t14 = #t13.{self::Test1::prop}.{core::num::+}(1) in let final void #t15 = #t13.{self::Test1::prop} = #t14 in #t14;
+    core::int* v11 = let final self::Test1* #t16 = t in #t16.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t17 = #t16.{self::Test1::prop} in let final void #t18 = #t16.{self::Test1::prop} = #t17.{core::num::+}(1) in #t17;
   }
 }
 class Test2 extends core::Object {
@@ -24,17 +24,17 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    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;
-    core::num* v7 = let final self::Test2* #t22 = t in #t22.==(null) ?{core::num*} null : #t22.{self::Test2::prop} = #t22.{self::Test2::prop}.{core::num::+}(self::getInt());
-    core::num* v8 = let final self::Test2* #t23 = t in #t23.==(null) ?{core::num*} null : #t23.{self::Test2::prop} = #t23.{self::Test2::prop}.{core::num::+}(self::getNum());
-    core::num* v9 = let final self::Test2* #t24 = t in #t24.==(null) ?{core::num*} null : #t24.{self::Test2::prop} = #t24.{self::Test2::prop}.{core::num::+}(self::getDouble());
-    core::num* v10 = let final self::Test2* #t25 = t in #t25.==(null) ?{core::num*} null : #t25.{self::Test2::prop} = #t25.{self::Test2::prop}.{core::num::+}(1);
-    core::num* v11 = let final self::Test2* #t26 = t in #t26.==(null) ?{core::num*} null : let final core::num* #t27 = #t26.{self::Test2::prop} in let final core::num* #t28 = #t26.{self::Test2::prop} = #t27.{core::num::+}(1) in #t27;
+    core::int* v1 = let final self::Test2* #t19 = t in #t19.{core::Object::==}(null) ?{core::int*} null : #t19.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t20 = t in #t20.{core::Object::==}(null) ?{core::num*} null : #t20.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t21 = t in #t21.{core::Object::==}(null) ?{core::double*} null : #t21.{self::Test2::prop} = self::getDouble();
+    core::num* v4 = let final self::Test2* #t22 = t in #t22.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop} in #t23.{core::num::==}(null) ?{core::num*} #t22.{self::Test2::prop} = self::getInt() : #t23;
+    core::num* v5 = let final self::Test2* #t24 = t in #t24.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t25 = #t24.{self::Test2::prop} in #t25.{core::num::==}(null) ?{core::num*} #t24.{self::Test2::prop} = self::getNum() : #t25;
+    core::num* v6 = let final self::Test2* #t26 = t in #t26.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t27 = #t26.{self::Test2::prop} in #t27.{core::num::==}(null) ?{core::num*} #t26.{self::Test2::prop} = self::getDouble() : #t27;
+    core::num* v7 = let final self::Test2* #t28 = t in #t28.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t29 = #t28.{self::Test2::prop}.{core::num::+}(self::getInt()) in let final void #t30 = #t28.{self::Test2::prop} = #t29 in #t29;
+    core::num* v8 = let final self::Test2* #t31 = t in #t31.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t32 = #t31.{self::Test2::prop}.{core::num::+}(self::getNum()) in let final void #t33 = #t31.{self::Test2::prop} = #t32 in #t32;
+    core::num* v9 = let final self::Test2* #t34 = t in #t34.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t35 = #t34.{self::Test2::prop}.{core::num::+}(self::getDouble()) in let final void #t36 = #t34.{self::Test2::prop} = #t35 in #t35;
+    core::num* v10 = let final self::Test2* #t37 = t in #t37.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t38 = #t37.{self::Test2::prop}.{core::num::+}(1) in let final void #t39 = #t37.{self::Test2::prop} = #t38 in #t38;
+    core::num* v11 = let final self::Test2* #t40 = t in #t40.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t41 = #t40.{self::Test2::prop} in let final void #t42 = #t40.{self::Test2::prop} = #t41.{core::num::+}(1) in #t41;
   }
 }
 class Test3 extends core::Object {
@@ -43,15 +43,15 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    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());
-    core::double* v8 = let final self::Test3* #t36 = t in #t36.==(null) ?{core::double*} null : #t36.{self::Test3::prop} = #t36.{self::Test3::prop}.{core::double::+}(self::getNum());
-    core::double* v9 = let final self::Test3* #t37 = t in #t37.==(null) ?{core::double*} null : #t37.{self::Test3::prop} = #t37.{self::Test3::prop}.{core::double::+}(self::getDouble());
-    core::double* v10 = let final self::Test3* #t38 = t in #t38.==(null) ?{core::double*} null : #t38.{self::Test3::prop} = #t38.{self::Test3::prop}.{core::double::+}(1);
-    core::double* v11 = let final self::Test3* #t39 = t in #t39.==(null) ?{core::double*} null : let final core::double* #t40 = #t39.{self::Test3::prop} in let final core::double* #t41 = #t39.{self::Test3::prop} = #t40.{core::double::+}(1) in #t40;
+    core::num* v2 = let final self::Test3* #t43 = t in #t43.{core::Object::==}(null) ?{core::num*} null : #t43.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
+    core::double* v3 = let final self::Test3* #t44 = t in #t44.{core::Object::==}(null) ?{core::double*} null : #t44.{self::Test3::prop} = self::getDouble();
+    core::num* v5 = let final self::Test3* #t45 = t in #t45.{core::Object::==}(null) ?{core::num*} null : let final core::double* #t46 = #t45.{self::Test3::prop} in #t46.{core::num::==}(null) ?{core::num*} #t45.{self::Test3::prop} = self::getNum() as{TypeError} core::double* : #t46;
+    core::double* v6 = let final self::Test3* #t47 = t in #t47.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t48 = #t47.{self::Test3::prop} in #t48.{core::num::==}(null) ?{core::double*} #t47.{self::Test3::prop} = self::getDouble() : #t48;
+    core::double* v7 = let final self::Test3* #t49 = t in #t49.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t50 = #t49.{self::Test3::prop}.{core::double::+}(self::getInt()) in let final void #t51 = #t49.{self::Test3::prop} = #t50 in #t50;
+    core::double* v8 = let final self::Test3* #t52 = t in #t52.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t53 = #t52.{self::Test3::prop}.{core::double::+}(self::getNum()) in let final void #t54 = #t52.{self::Test3::prop} = #t53 in #t53;
+    core::double* v9 = let final self::Test3* #t55 = t in #t55.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t56 = #t55.{self::Test3::prop}.{core::double::+}(self::getDouble()) in let final void #t57 = #t55.{self::Test3::prop} = #t56 in #t56;
+    core::double* v10 = let final self::Test3* #t58 = t in #t58.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t59 = #t58.{self::Test3::prop}.{core::double::+}(1) in let final void #t60 = #t58.{self::Test3::prop} = #t59 in #t59;
+    core::double* v11 = let final self::Test3* #t61 = t in #t61.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t62 = #t61.{self::Test3::prop} in let final void #t63 = #t61.{self::Test3::prop} = #t62.{core::double::+}(1) in #t62;
   }
 }
 static method getInt() → core::int*
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 da54b4b..97a828a 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
@@ -10,12 +10,12 @@
   static method test(self::Test1* t) → void {
     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());
-    core::num* v8 = let final self::Test1* #t8 = t in #t8.==(null) ?{core::num*} null : #t8.{self::Test1::prop} = #t8.{self::Test1::prop}.{core::num::+}(self::getNum()) as{TypeError} core::int*;
-    core::int* v10 = let final self::Test1* #t9 = t in #t9.==(null) ?{core::int*} null : #t9.{self::Test1::prop} = #t9.{self::Test1::prop}.{core::num::+}(1);
-    core::int* v11 = let final self::Test1* #t10 = t in #t10.==(null) ?{core::int*} null : let final core::int* #t11 = #t10.{self::Test1::prop} in let final core::int* #t12 = #t10.{self::Test1::prop} = #t11.{core::num::+}(1) in #t11;
+    core::int* v4 = let final self::Test1* #t3 = t in #t3.{core::Object::==}(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.{core::Object::==}(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.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t8 = #t7.{self::Test1::prop}.{core::num::+}(self::getInt()) in let final void #t9 = #t7.{self::Test1::prop} = #t8 in #t8;
+    core::num* v8 = let final self::Test1* #t10 = t in #t10.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t11 = #t10.{self::Test1::prop}.{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t12 = #t10.{self::Test1::prop} = #t11 in #t11;
+    core::int* v10 = let final self::Test1* #t13 = t in #t13.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t14 = #t13.{self::Test1::prop}.{core::num::+}(1) in let final void #t15 = #t13.{self::Test1::prop} = #t14 in #t14;
+    core::int* v11 = let final self::Test1* #t16 = t in #t16.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t17 = #t16.{self::Test1::prop} in let final void #t18 = #t16.{self::Test1::prop} = #t17.{core::num::+}(1) in #t17;
   }
 }
 class Test2 extends core::Object {
@@ -24,17 +24,17 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    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;
-    core::num* v7 = let final self::Test2* #t22 = t in #t22.==(null) ?{core::num*} null : #t22.{self::Test2::prop} = #t22.{self::Test2::prop}.{core::num::+}(self::getInt());
-    core::num* v8 = let final self::Test2* #t23 = t in #t23.==(null) ?{core::num*} null : #t23.{self::Test2::prop} = #t23.{self::Test2::prop}.{core::num::+}(self::getNum());
-    core::num* v9 = let final self::Test2* #t24 = t in #t24.==(null) ?{core::num*} null : #t24.{self::Test2::prop} = #t24.{self::Test2::prop}.{core::num::+}(self::getDouble());
-    core::num* v10 = let final self::Test2* #t25 = t in #t25.==(null) ?{core::num*} null : #t25.{self::Test2::prop} = #t25.{self::Test2::prop}.{core::num::+}(1);
-    core::num* v11 = let final self::Test2* #t26 = t in #t26.==(null) ?{core::num*} null : let final core::num* #t27 = #t26.{self::Test2::prop} in let final core::num* #t28 = #t26.{self::Test2::prop} = #t27.{core::num::+}(1) in #t27;
+    core::int* v1 = let final self::Test2* #t19 = t in #t19.{core::Object::==}(null) ?{core::int*} null : #t19.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t20 = t in #t20.{core::Object::==}(null) ?{core::num*} null : #t20.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t21 = t in #t21.{core::Object::==}(null) ?{core::double*} null : #t21.{self::Test2::prop} = self::getDouble();
+    core::num* v4 = let final self::Test2* #t22 = t in #t22.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t23 = #t22.{self::Test2::prop} in #t23.{core::num::==}(null) ?{core::num*} #t22.{self::Test2::prop} = self::getInt() : #t23;
+    core::num* v5 = let final self::Test2* #t24 = t in #t24.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t25 = #t24.{self::Test2::prop} in #t25.{core::num::==}(null) ?{core::num*} #t24.{self::Test2::prop} = self::getNum() : #t25;
+    core::num* v6 = let final self::Test2* #t26 = t in #t26.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t27 = #t26.{self::Test2::prop} in #t27.{core::num::==}(null) ?{core::num*} #t26.{self::Test2::prop} = self::getDouble() : #t27;
+    core::num* v7 = let final self::Test2* #t28 = t in #t28.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t29 = #t28.{self::Test2::prop}.{core::num::+}(self::getInt()) in let final void #t30 = #t28.{self::Test2::prop} = #t29 in #t29;
+    core::num* v8 = let final self::Test2* #t31 = t in #t31.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t32 = #t31.{self::Test2::prop}.{core::num::+}(self::getNum()) in let final void #t33 = #t31.{self::Test2::prop} = #t32 in #t32;
+    core::num* v9 = let final self::Test2* #t34 = t in #t34.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t35 = #t34.{self::Test2::prop}.{core::num::+}(self::getDouble()) in let final void #t36 = #t34.{self::Test2::prop} = #t35 in #t35;
+    core::num* v10 = let final self::Test2* #t37 = t in #t37.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t38 = #t37.{self::Test2::prop}.{core::num::+}(1) in let final void #t39 = #t37.{self::Test2::prop} = #t38 in #t38;
+    core::num* v11 = let final self::Test2* #t40 = t in #t40.{core::Object::==}(null) ?{core::num*} null : let final core::num* #t41 = #t40.{self::Test2::prop} in let final void #t42 = #t40.{self::Test2::prop} = #t41.{core::num::+}(1) in #t41;
   }
 }
 class Test3 extends core::Object {
@@ -43,15 +43,15 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    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());
-    core::double* v8 = let final self::Test3* #t36 = t in #t36.==(null) ?{core::double*} null : #t36.{self::Test3::prop} = #t36.{self::Test3::prop}.{core::double::+}(self::getNum());
-    core::double* v9 = let final self::Test3* #t37 = t in #t37.==(null) ?{core::double*} null : #t37.{self::Test3::prop} = #t37.{self::Test3::prop}.{core::double::+}(self::getDouble());
-    core::double* v10 = let final self::Test3* #t38 = t in #t38.==(null) ?{core::double*} null : #t38.{self::Test3::prop} = #t38.{self::Test3::prop}.{core::double::+}(1);
-    core::double* v11 = let final self::Test3* #t39 = t in #t39.==(null) ?{core::double*} null : let final core::double* #t40 = #t39.{self::Test3::prop} in let final core::double* #t41 = #t39.{self::Test3::prop} = #t40.{core::double::+}(1) in #t40;
+    core::num* v2 = let final self::Test3* #t43 = t in #t43.{core::Object::==}(null) ?{core::num*} null : #t43.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
+    core::double* v3 = let final self::Test3* #t44 = t in #t44.{core::Object::==}(null) ?{core::double*} null : #t44.{self::Test3::prop} = self::getDouble();
+    core::num* v5 = let final self::Test3* #t45 = t in #t45.{core::Object::==}(null) ?{core::num*} null : let final core::double* #t46 = #t45.{self::Test3::prop} in #t46.{core::num::==}(null) ?{core::num*} #t45.{self::Test3::prop} = self::getNum() as{TypeError} core::double* : #t46;
+    core::double* v6 = let final self::Test3* #t47 = t in #t47.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t48 = #t47.{self::Test3::prop} in #t48.{core::num::==}(null) ?{core::double*} #t47.{self::Test3::prop} = self::getDouble() : #t48;
+    core::double* v7 = let final self::Test3* #t49 = t in #t49.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t50 = #t49.{self::Test3::prop}.{core::double::+}(self::getInt()) in let final void #t51 = #t49.{self::Test3::prop} = #t50 in #t50;
+    core::double* v8 = let final self::Test3* #t52 = t in #t52.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t53 = #t52.{self::Test3::prop}.{core::double::+}(self::getNum()) in let final void #t54 = #t52.{self::Test3::prop} = #t53 in #t53;
+    core::double* v9 = let final self::Test3* #t55 = t in #t55.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t56 = #t55.{self::Test3::prop}.{core::double::+}(self::getDouble()) in let final void #t57 = #t55.{self::Test3::prop} = #t56 in #t56;
+    core::double* v10 = let final self::Test3* #t58 = t in #t58.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t59 = #t58.{self::Test3::prop}.{core::double::+}(1) in let final void #t60 = #t58.{self::Test3::prop} = #t59 in #t59;
+    core::double* v11 = let final self::Test3* #t61 = t in #t61.{core::Object::==}(null) ?{core::double*} null : let final core::double* #t62 = #t61.{self::Test3::prop} in let final void #t63 = #t61.{self::Test3::prop} = #t62.{core::double::+}(1) in #t62;
   }
 }
 static method getInt() → core::int*
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.outline.expect
index 3d491c7..e828a66 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.expect
index fcd6d80..1a0ffd7 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
index fcd6d80..1a0ffd7 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.outline.expect
index bcf2c7a..d6a3a24 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<U extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::U*>*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.expect
index e923e16..c12b23e 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<U extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::U*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
index e923e16..c12b23e 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<U extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::U*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.outline.expect
index 3d491c7..e828a66 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.expect
index 22d342d..62cd600 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.transformed.expect
index 22d342d..62cd600 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.outline.expect
index f75d4ee..0a850b0 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.expect
index b0dc0d8..455e663 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.transformed.expect
index b0dc0d8..455e663 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.outline.expect
index dcce18a..bb96cdb 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect
index 0ce72d7..d17c1dd 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect
index 0ce72d7..d17c1dd 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant U extends (U*) →* dynamic = (dynamic) →* dynamic> = (U*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
index 1283fc5..5985c4c 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Fisk<TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
 class Hest<TypeX extends () →* void = () →* void> extends core::Object {
   synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
index 548d055..7b9d47f 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Fisk<TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
 class Hest<TypeX extends () →* void = () →* void> extends core::Object {
   synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
index 548d055..7b9d47f 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Fisk<TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
 class Hest<TypeX extends () →* void = () →* void> extends core::Object {
   synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.outline.expect
index a9a5b64..734815e 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.expect
index 47cd11d..e626b04 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.transformed.expect
index 47cd11d..e626b04 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B extends core::Object {
   synthetic constructor •() → self::B*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.outline.expect
index 9af14c6..e6917ea 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::List<(core::num*) →* dynamic>* a;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.expect
index 424bbbe..e5555e7 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::List<(core::num*) →* dynamic>* a = <(core::num*) →* dynamic>[];
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
index 424bbbe..e5555e7 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::List<(core::num*) →* dynamic>* a = <(core::num*) →* dynamic>[];
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.outline.expect
index b2250e8..3a72d6c 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<S extends core::Object* = dynamic> extends core::Object {
   final field core::List<(self::B::S*) →* dynamic>* foo;
   final field core::List<(core::num*) →* dynamic>* bar;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.expect
index 66e0166..95a1206 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<S extends core::Object* = dynamic> extends core::Object {
   final field core::List<(self::B::S*) →* dynamic>* foo = <(self::B::S*) →* dynamic>[];
   final field core::List<(core::num*) →* dynamic>* bar = <(core::num*) →* dynamic>[];
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
index 66e0166..95a1206 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<S extends core::Object* = dynamic> extends core::Object {
   final field core::List<(self::B::S*) →* dynamic>* foo = <(self::B::S*) →* dynamic>[];
   final field core::List<(core::num*) →* dynamic>* bar = <(core::num*) →* dynamic>[];
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.outline.expect
index a1238c5..90306c1 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::Map<(core::num*) →* dynamic, (core::num*) →* dynamic>* a;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.expect
index 45dc4c2..5412826 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::Map<(core::num*) →* dynamic, (core::num*) →* dynamic>* a = <(core::num*) →* dynamic, (core::num*) →* dynamic>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.transformed.expect
index 45dc4c2..5412826 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.strong.transformed.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 static field core::Map<(core::num*) →* dynamic, (core::num*) →* dynamic>* a = <(core::num*) →* dynamic, (core::num*) →* dynamic>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.outline.expect
index aa6c819..63af415 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.expect
index 4bca658..4164860 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.transformed.expect
index 4bca658..4164860 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.outline.expect
index 345eb14..86efbd9 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B<T extends (core::num*) →* dynamic = (core::num*) →* dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.expect
index 4036b32..d46f295 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B<T extends (core::num*) →* dynamic = (core::num*) →* dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.transformed.expect
index 4036b32..d46f295 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::num* = core::num*> = (T*) →* dynamic;
+typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
 class B<T extends (core::num*) →* dynamic = (core::num*) →* dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.outline.expect
index bbce9e4..32182bf 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
 static field ((dynamic) →* dynamic) →* dynamic b;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect
index d59e608..4280623 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
 static field ((dynamic) →* dynamic) →* dynamic b;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect
index d59e608..4280623 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef A<T extends core::Object* = dynamic> = (T*) →* dynamic;
-typedef B<S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
+typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef B<contravariant S extends (S*) →* dynamic = (dynamic) →* dynamic> = (S*) →* dynamic;
 static field ((dynamic) →* dynamic) →* dynamic b;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nested_variance_test.dart b/pkg/front_end/testcases/nested_variance_test.dart
new file mode 100644
index 0000000..28a2f62
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart
@@ -0,0 +1,243 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Testing that i2b and checks for correct super-boundedness are applied
+// to type arguments, taking the variance of type parameters into account.
+
+// Standard type comparison support.
+
+typedef F<X> = void Function<Y extends X>();
+F<X> toF<X>(X x) => null;
+
+// Material specific to this test.
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+
+class Acov<X extends Fcov<Y>, Y> {}
+
+class Acon<X extends Fcon<Y>, Y> {}
+
+class Ainv<X extends Finv<Y>, Y> {}
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+
+class AcovBound<X extends FcovBound<Y>, Y extends num> {}
+
+class AconBound<X extends FconBound<Y>, Y extends num> {}
+
+class AinvBound<X extends FinvBound<Y>, Y extends num> {}
+
+class A<X> {}
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+
+class AcovCyclicBound<X extends FcovCyclicBound<Y>, Y extends A<Y>> {}
+
+class AconCyclicBound<X extends FconCyclicBound<Y>, Y extends A<Y>> {}
+
+class AinvCyclicBound<X extends FinvCyclicBound<Y>, Y extends A<Y>> {}
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+
+class AcovCyclicCoBound<X extends FcovCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AconCyclicCoBound<X extends FconCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AinvCyclicCoBound<X extends FinvCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class B<X> {}
+
+void testTypeAliasAsTypeArgument() {
+  // I2b: Use bounds (Fcov<Y>, dynamic), then replace covariant occurrence
+  // (of `Y` in `Acov<Fcov<Y>, _>`) by `Y`s value `dynamic`. Resulting type
+  // `Acov<Fcov<dynamic>, dynamic>` is regular-bounded.
+  Acov source1;
+  var fsource1 = toF(source1);
+  F<Acov<Fcov<dynamic>, dynamic>> target1 = fsource1;
+
+  // I2b: Use bounds (Fcon<Y>, dynamic), then replace contravariant occurrence
+  // (of `Y` in `Acon<Fcon<Y>, _>`) by `Null`. Resulting type
+  // is super-bounded: Acon<Fcon<Object>, Null> is regular-bounded.
+  Acon source2;
+  var fsource2 = toF(source2);
+  F<Acon<Fcon<Null>, dynamic>> target2 = fsource2;
+
+  // I2b: Use bounds (Finv<Y>, dynamic) then replace invariant occurrence
+  // (of `Y` in `Ainv<Finv<Y>, _>`) by `Y`s value `dynamic`. Resulting type
+  // `Ainv<Finv<dynamic>, dynamic>` is regular-bounded.
+  Ainv source3;
+  var fsource3 = toF(source3);
+  F<Ainv<Finv<dynamic>, dynamic>> target3 = fsource3;
+
+  // I2b: Use bounds (FcovBound<Y>, num), then replace covariant occurrence
+  // (of `Y` in `AcovBound<FcovBound<Y>, _>`) by `Y`s value `num`.
+  // Resulting type `AcovBound<FcovBound<num>, num>` is regular-bounded.
+  AcovBound source4;
+  var fsource4 = toF(source4);
+  F<AcovBound<FcovBound<num>, num>> target4 = fsource4;
+
+  // I2b: Use bounds (FconBound<Y>, num), then replace contravariant occurrence
+  // of `Y` in `AconBound<FconBound<Y>, _>` by `Null`. Resulting type is
+  // super-bounded: AconBound<FconBound<Object>, num> is regular-bounded.
+  AconBound source5;
+  var fsource5 = toF(source5);
+  F<AconBound<FconBound<Null>, num>> target5 = fsource5;
+
+  // I2b: Use bounds (FinvBound<Y>, num), then replace invariant occurrence
+  // of `Y` in `AinvBound<FinvBound<Y>, _>` by `Y`s value `num`. Resulting
+  // type `AinvBound<FinvBound<num>, num>` is regular-bounded.
+  AinvBound source6;
+  var fsource6 = toF(source6);
+  F<AinvBound<FinvBound<num>, num>> target6 = fsource6;
+
+  // I2b: Use bounds (FcovCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AcovCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace covariant occurrence of `Y` in
+  // `AcovCyclicBound<FcovCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
+  // Resulting type `AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>`
+  // is regular-bounded.
+  AcovCyclicBound source7;
+  var fsource7 = toF(source7);
+  F<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>> target7 =
+      fsource7;
+
+  // I2b: Use bounds (FconCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AconCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace contravariant occurrence of `Y` in
+  // `AconCyclicBound<FconCyclicBound<Y>, _>` by `Null`.
+  // Resulting type `AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>>` is
+  // super-bounded because `AconCyclicBound<FconCyclicBound<Object>, A<Null>>>`
+  // is regular-bounded.
+  AconCyclicBound source8;
+  var fsource8 = toF(source8);
+  F<AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>> target8 = fsource8;
+
+  // I2b: Use bounds (FinvCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AinvCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace invariant occurrence of `Y` in
+  // `AinvCyclicBound<FinvCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
+  // Resulting type `AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>`
+  // looks regular-bounded, but contains `FinvCyclicBound<A<dynamic>>` which
+  // is not well-bounded.
+  AinvCyclicBound source9; //# 01: compile-time error
+  // var fsource9 = toF(source9);
+  // F<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>> target9 =
+  //     fsource9;
+
+  // I2b: Use bounds (FcovCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AcovCyclicCoBound<_, Function(Y)>` by `Null`; then replace covariant
+  // occurrence of `Y` in `AcovCyclicCoBound<FcovCyclicCoBound<Y>, _>` by `Y`s
+  // value `Function(Null)`. Resulting type
+  // `AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>`
+  // is regular-bounded, with subterm `FcovCyclicCoBound<Function(Null)>` which
+  // is super-bounded because `FcovCyclicCoBound<Function(Object)>` is
+  // regular-bounded.
+  AcovCyclicCoBound source10;
+  var fsource10 = toF(source10);
+  F<AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>>
+      target10 = fsource10;
+
+  // I2b: Use bounds (FconCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AconCyclicCoBound<_, Function(Y)>` by `Null`; then replace contravariant
+  // occurrence of `Y` in `AconCyclicCoBound<FconCyclicCoBound<Y>, _>` by
+  // `Null`. Resulting type
+  // `AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>` is
+  // super-bounded because
+  // `AconCyclicCoBound<FconCyclicCoBound<Object>, Function(Object)>` is
+  // regular-bounded.
+  AconCyclicCoBound source11;
+  var fsource11 = toF(source11);
+  F<AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>> target11 =
+      fsource11;
+
+  // I2b: Use bounds (FinvCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AinvCyclicCoBound<_, Function(Y)>` by `Null`; then replace invariant
+  // occurrence of `Y` in `AinvCyclicCoBound<FinvCyclicCoBound<Y>, _>` by `Y`s
+  // value `Function(Null)`.
+  // Resulting type
+  // `AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>`
+  // looks regular-bounded, but contains `FinvCyclicCoBound<Function(Null)>`
+  // which is not well-bounded.
+  AinvCyclicCoBound source12; //# 02: compile-time error
+  // var fsource12 = toF(source12);
+  // F<AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>
+  //     target12 = fsource12;
+}
+
+void testNested() {
+  // Everything gets the same treatment when the cases from `testTopLevel`
+  // are duplicated at the nested level in a covariant position.
+
+  B<Acov> source1;
+  var fsource1 = toF(source1);
+  F<B<Acov<Fcov<dynamic>, dynamic>>> target1 = fsource1;
+
+  B<Acon> source2;
+  var fsource2 = toF(source2);
+  F<B<Acon<Fcon<Null>, dynamic>>> target2 = fsource2;
+
+  B<Ainv> source3;
+  var fsource3 = toF(source3);
+  F<B<Ainv<Finv<dynamic>, dynamic>>> target3 = fsource3;
+
+  B<AcovBound> source4;
+  var fsource4 = toF(source4);
+  F<B<AcovBound<FcovBound<num>, num>>> target4 = fsource4;
+
+  B<AconBound> source5;
+  var fsource5 = toF(source5);
+  F<B<AconBound<FconBound<Null>, num>>> target5 = fsource5;
+
+  B<AinvBound> source6;
+  var fsource6 = toF(source6);
+  F<B<AinvBound<FinvBound<num>, num>>> target6 = fsource6;
+
+  B<AcovCyclicBound> source7;
+  var fsource7 = toF(source7);
+  F<B<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>> target7 =
+      fsource7;
+
+  B<AconCyclicBound> source8;
+  var fsource8 = toF(source8);
+  F<B<AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>>> target8 = fsource8;
+
+  B<AinvCyclicBound> source9; //# 03: compile-time error
+  // var fsource9 = toF(source9);
+  // F<B<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>> target9 =
+  //    fsource9;
+
+  B<AcovCyclicCoBound> source10;
+  var fsource10 = toF(source10);
+  F<B<AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>>>
+      target10 = fsource10;
+
+  B<AconCyclicCoBound> source11;
+  var fsource11 = toF(source11);
+  F<B<AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>>> target11 =
+      fsource11;
+
+  B<AinvCyclicCoBound> source12; //# 04: compile-time error
+  // var fsource12 = toF(source12);
+  // F<B<AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>>
+  //     target12 = fsource12;
+}
+
+main() {
+  testTypeAliasAsTypeArgument();
+  testNested();
+}
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.hierarchy.expect b/pkg/front_end/testcases/nested_variance_test.dart.hierarchy.expect
new file mode 100644
index 0000000..943b7be
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.hierarchy.expect
@@ -0,0 +1,257 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Acov:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Acon:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ainv:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AcovBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AconBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AinvBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AcovCyclicBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AconCyclicBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AinvCyclicBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AcovCyclicCoBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AconCyclicCoBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+AinvCyclicCoBound:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.legacy.expect b/pkg/front_end/testcases/nested_variance_test.dart.legacy.expect
new file mode 100644
index 0000000..b9c9ad3
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.legacy.expect
@@ -0,0 +1,161 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object = dynamic> = <Y extends X = dynamic>() → void;
+typedef Fcov<X extends core::Object = dynamic> = () → X;
+typedef Fcon<contravariant X extends core::Object = dynamic> = (X) → dynamic;
+typedef Finv<invariant X extends core::Object = dynamic> = (X) → X;
+typedef FcovBound<X extends core::num = dynamic> = () → X;
+typedef FconBound<contravariant X extends core::num = dynamic> = (X) → dynamic;
+typedef FinvBound<invariant X extends core::num = dynamic> = (X) → X;
+typedef FcovCyclicBound<X extends self::A<X> = dynamic> = () → X;
+typedef FconCyclicBound<contravariant X extends self::A<X> = dynamic> = (X) → dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X> = dynamic> = (X) → X;
+typedef FcovCyclicCoBound<X extends (X) → dynamic = dynamic> = () → X;
+typedef FconCyclicCoBound<contravariant X extends (X) → dynamic = dynamic> = (X) → dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X) → dynamic = dynamic> = (X) → X;
+class Acov<X extends () → self::Acov::Y = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acov<self::Acov::X, self::Acov::Y>
+    : super core::Object::•()
+    ;
+}
+class Acon<X extends (self::Acon::Y) → dynamic = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acon<self::Acon::X, self::Acon::Y>
+    : super core::Object::•()
+    ;
+}
+class Ainv<X extends (self::Ainv::Y) → self::Ainv::Y = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ainv<self::Ainv::X, self::Ainv::Y>
+    : super core::Object::•()
+    ;
+}
+class AcovBound<X extends () → self::AcovBound::Y = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovBound<self::AcovBound::X, self::AcovBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconBound<X extends (self::AconBound::Y) → dynamic = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconBound<self::AconBound::X, self::AconBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvBound<X extends (self::AinvBound::Y) → self::AinvBound::Y = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvBound<self::AinvBound::X, self::AinvBound::Y>
+    : super core::Object::•()
+    ;
+}
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicBound<X extends () → self::AcovCyclicBound::Y = dynamic, Y extends self::A<self::AcovCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicBound<self::AcovCyclicBound::X, self::AcovCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconCyclicBound<X extends (self::AconCyclicBound::Y) → dynamic = dynamic, Y extends self::A<self::AconCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicBound<self::AconCyclicBound::X, self::AconCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicBound<X extends (self::AinvCyclicBound::Y) → self::AinvCyclicBound::Y = dynamic, Y extends self::A<self::AinvCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicBound<self::AinvCyclicBound::X, self::AinvCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicCoBound<X extends () → self::AcovCyclicCoBound::Y = dynamic, Y extends (self::AcovCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicCoBound<self::AcovCyclicCoBound::X, self::AcovCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconCyclicCoBound<X extends (self::AconCyclicCoBound::Y) → dynamic = dynamic, Y extends (self::AconCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicCoBound<self::AconCyclicCoBound::X, self::AconCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicCoBound<X extends (self::AinvCyclicCoBound::Y) → self::AinvCyclicCoBound::Y = dynamic, Y extends (self::AinvCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicCoBound<self::AinvCyclicCoBound::X, self::AinvCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object = dynamic>(self::toF::X x) → <Y extends self::toF::X = dynamic>() → void
+  return null;
+static method testTypeAliasAsTypeArgument() → void {
+  self::Acov<dynamic, dynamic> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::Acov<() → dynamic, dynamic> = dynamic>() → void target1 = fsource1;
+  self::Acon<dynamic, dynamic> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::Acon<(core::Null) → dynamic, dynamic> = dynamic>() → void target2 = fsource2;
+  self::Ainv<dynamic, dynamic> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::Ainv<(dynamic) → dynamic, dynamic> = dynamic>() → void target3 = fsource3;
+  self::AcovBound<dynamic, dynamic> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::AcovBound<() → core::num, core::num> = dynamic>() → void target4 = fsource4;
+  self::AconBound<dynamic, dynamic> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::AconBound<(core::Null) → dynamic, core::num> = dynamic>() → void target5 = fsource5;
+  self::AinvBound<dynamic, dynamic> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::AinvBound<(core::num) → core::num, core::num> = dynamic>() → void target6 = fsource6;
+  self::AcovCyclicBound<dynamic, dynamic> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::AcovCyclicBound<() → self::A<dynamic>, self::A<dynamic>> = dynamic>() → void target7 = fsource7;
+  self::AconCyclicBound<dynamic, dynamic> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::AconCyclicBound<(core::Null) → dynamic, self::A<dynamic>> = dynamic>() → void target8 = fsource8;
+  self::AinvCyclicBound<dynamic, dynamic> source9;
+  self::AcovCyclicCoBound<dynamic, dynamic> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::AcovCyclicCoBound<() → (core::Null) → dynamic, (core::Null) → dynamic> = dynamic>() → void target10 = fsource10;
+  self::AconCyclicCoBound<dynamic, dynamic> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::AconCyclicCoBound<(core::Null) → dynamic, (core::Null) → dynamic> = dynamic>() → void target11 = fsource11;
+  self::AinvCyclicCoBound<dynamic, dynamic> source12;
+}
+static method testNested() → void {
+  self::B<self::Acov<dynamic, dynamic>> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::B<self::Acov<() → dynamic, dynamic>> = dynamic>() → void target1 = fsource1;
+  self::B<self::Acon<dynamic, dynamic>> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::B<self::Acon<(core::Null) → dynamic, dynamic>> = dynamic>() → void target2 = fsource2;
+  self::B<self::Ainv<dynamic, dynamic>> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::B<self::Ainv<(dynamic) → dynamic, dynamic>> = dynamic>() → void target3 = fsource3;
+  self::B<self::AcovBound<dynamic, dynamic>> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::B<self::AcovBound<() → core::num, core::num>> = dynamic>() → void target4 = fsource4;
+  self::B<self::AconBound<dynamic, dynamic>> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::B<self::AconBound<(core::Null) → dynamic, core::num>> = dynamic>() → void target5 = fsource5;
+  self::B<self::AinvBound<dynamic, dynamic>> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::B<self::AinvBound<(core::num) → core::num, core::num>> = dynamic>() → void target6 = fsource6;
+  self::B<self::AcovCyclicBound<dynamic, dynamic>> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::B<self::AcovCyclicBound<() → self::A<dynamic>, self::A<dynamic>>> = dynamic>() → void target7 = fsource7;
+  self::B<self::AconCyclicBound<dynamic, dynamic>> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::B<self::AconCyclicBound<(core::Null) → dynamic, self::A<dynamic>>> = dynamic>() → void target8 = fsource8;
+  self::B<self::AinvCyclicBound<dynamic, dynamic>> source9;
+  self::B<self::AcovCyclicCoBound<dynamic, dynamic>> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::B<self::AcovCyclicCoBound<() → (core::Null) → dynamic, (core::Null) → dynamic>> = dynamic>() → void target10 = fsource10;
+  self::B<self::AconCyclicCoBound<dynamic, dynamic>> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null) → dynamic, (core::Null) → dynamic>> = dynamic>() → void target11 = fsource11;
+  self::B<self::AinvCyclicCoBound<dynamic, dynamic>> source12;
+}
+static method main() → dynamic {
+  self::testTypeAliasAsTypeArgument();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.legacy.transformed.expect b/pkg/front_end/testcases/nested_variance_test.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b9c9ad3
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.legacy.transformed.expect
@@ -0,0 +1,161 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object = dynamic> = <Y extends X = dynamic>() → void;
+typedef Fcov<X extends core::Object = dynamic> = () → X;
+typedef Fcon<contravariant X extends core::Object = dynamic> = (X) → dynamic;
+typedef Finv<invariant X extends core::Object = dynamic> = (X) → X;
+typedef FcovBound<X extends core::num = dynamic> = () → X;
+typedef FconBound<contravariant X extends core::num = dynamic> = (X) → dynamic;
+typedef FinvBound<invariant X extends core::num = dynamic> = (X) → X;
+typedef FcovCyclicBound<X extends self::A<X> = dynamic> = () → X;
+typedef FconCyclicBound<contravariant X extends self::A<X> = dynamic> = (X) → dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X> = dynamic> = (X) → X;
+typedef FcovCyclicCoBound<X extends (X) → dynamic = dynamic> = () → X;
+typedef FconCyclicCoBound<contravariant X extends (X) → dynamic = dynamic> = (X) → dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X) → dynamic = dynamic> = (X) → X;
+class Acov<X extends () → self::Acov::Y = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acov<self::Acov::X, self::Acov::Y>
+    : super core::Object::•()
+    ;
+}
+class Acon<X extends (self::Acon::Y) → dynamic = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acon<self::Acon::X, self::Acon::Y>
+    : super core::Object::•()
+    ;
+}
+class Ainv<X extends (self::Ainv::Y) → self::Ainv::Y = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ainv<self::Ainv::X, self::Ainv::Y>
+    : super core::Object::•()
+    ;
+}
+class AcovBound<X extends () → self::AcovBound::Y = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovBound<self::AcovBound::X, self::AcovBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconBound<X extends (self::AconBound::Y) → dynamic = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconBound<self::AconBound::X, self::AconBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvBound<X extends (self::AinvBound::Y) → self::AinvBound::Y = dynamic, Y extends core::num = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvBound<self::AinvBound::X, self::AinvBound::Y>
+    : super core::Object::•()
+    ;
+}
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicBound<X extends () → self::AcovCyclicBound::Y = dynamic, Y extends self::A<self::AcovCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicBound<self::AcovCyclicBound::X, self::AcovCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconCyclicBound<X extends (self::AconCyclicBound::Y) → dynamic = dynamic, Y extends self::A<self::AconCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicBound<self::AconCyclicBound::X, self::AconCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicBound<X extends (self::AinvCyclicBound::Y) → self::AinvCyclicBound::Y = dynamic, Y extends self::A<self::AinvCyclicBound::Y> = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicBound<self::AinvCyclicBound::X, self::AinvCyclicBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicCoBound<X extends () → self::AcovCyclicCoBound::Y = dynamic, Y extends (self::AcovCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicCoBound<self::AcovCyclicCoBound::X, self::AcovCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AconCyclicCoBound<X extends (self::AconCyclicCoBound::Y) → dynamic = dynamic, Y extends (self::AconCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicCoBound<self::AconCyclicCoBound::X, self::AconCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicCoBound<X extends (self::AinvCyclicCoBound::Y) → self::AinvCyclicCoBound::Y = dynamic, Y extends (self::AinvCyclicCoBound::Y) → dynamic = dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicCoBound<self::AinvCyclicCoBound::X, self::AinvCyclicCoBound::Y>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object = dynamic>(self::toF::X x) → <Y extends self::toF::X = dynamic>() → void
+  return null;
+static method testTypeAliasAsTypeArgument() → void {
+  self::Acov<dynamic, dynamic> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::Acov<() → dynamic, dynamic> = dynamic>() → void target1 = fsource1;
+  self::Acon<dynamic, dynamic> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::Acon<(core::Null) → dynamic, dynamic> = dynamic>() → void target2 = fsource2;
+  self::Ainv<dynamic, dynamic> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::Ainv<(dynamic) → dynamic, dynamic> = dynamic>() → void target3 = fsource3;
+  self::AcovBound<dynamic, dynamic> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::AcovBound<() → core::num, core::num> = dynamic>() → void target4 = fsource4;
+  self::AconBound<dynamic, dynamic> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::AconBound<(core::Null) → dynamic, core::num> = dynamic>() → void target5 = fsource5;
+  self::AinvBound<dynamic, dynamic> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::AinvBound<(core::num) → core::num, core::num> = dynamic>() → void target6 = fsource6;
+  self::AcovCyclicBound<dynamic, dynamic> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::AcovCyclicBound<() → self::A<dynamic>, self::A<dynamic>> = dynamic>() → void target7 = fsource7;
+  self::AconCyclicBound<dynamic, dynamic> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::AconCyclicBound<(core::Null) → dynamic, self::A<dynamic>> = dynamic>() → void target8 = fsource8;
+  self::AinvCyclicBound<dynamic, dynamic> source9;
+  self::AcovCyclicCoBound<dynamic, dynamic> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::AcovCyclicCoBound<() → (core::Null) → dynamic, (core::Null) → dynamic> = dynamic>() → void target10 = fsource10;
+  self::AconCyclicCoBound<dynamic, dynamic> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::AconCyclicCoBound<(core::Null) → dynamic, (core::Null) → dynamic> = dynamic>() → void target11 = fsource11;
+  self::AinvCyclicCoBound<dynamic, dynamic> source12;
+}
+static method testNested() → void {
+  self::B<self::Acov<dynamic, dynamic>> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::B<self::Acov<() → dynamic, dynamic>> = dynamic>() → void target1 = fsource1;
+  self::B<self::Acon<dynamic, dynamic>> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::B<self::Acon<(core::Null) → dynamic, dynamic>> = dynamic>() → void target2 = fsource2;
+  self::B<self::Ainv<dynamic, dynamic>> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::B<self::Ainv<(dynamic) → dynamic, dynamic>> = dynamic>() → void target3 = fsource3;
+  self::B<self::AcovBound<dynamic, dynamic>> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::B<self::AcovBound<() → core::num, core::num>> = dynamic>() → void target4 = fsource4;
+  self::B<self::AconBound<dynamic, dynamic>> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::B<self::AconBound<(core::Null) → dynamic, core::num>> = dynamic>() → void target5 = fsource5;
+  self::B<self::AinvBound<dynamic, dynamic>> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::B<self::AinvBound<(core::num) → core::num, core::num>> = dynamic>() → void target6 = fsource6;
+  self::B<self::AcovCyclicBound<dynamic, dynamic>> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::B<self::AcovCyclicBound<() → self::A<dynamic>, self::A<dynamic>>> = dynamic>() → void target7 = fsource7;
+  self::B<self::AconCyclicBound<dynamic, dynamic>> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::B<self::AconCyclicBound<(core::Null) → dynamic, self::A<dynamic>>> = dynamic>() → void target8 = fsource8;
+  self::B<self::AinvCyclicBound<dynamic, dynamic>> source9;
+  self::B<self::AcovCyclicCoBound<dynamic, dynamic>> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::B<self::AcovCyclicCoBound<() → (core::Null) → dynamic, (core::Null) → dynamic>> = dynamic>() → void target10 = fsource10;
+  self::B<self::AconCyclicCoBound<dynamic, dynamic>> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null) → dynamic, (core::Null) → dynamic>> = dynamic>() → void target11 = fsource11;
+  self::B<self::AinvCyclicCoBound<dynamic, dynamic>> source12;
+}
+static method main() → dynamic {
+  self::testTypeAliasAsTypeArgument();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.outline.expect b/pkg/front_end/testcases/nested_variance_test.dart.outline.expect
new file mode 100644
index 0000000..5bfe24d
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.outline.expect
@@ -0,0 +1,81 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class Acov<X extends () →* self::Acov::Y* = () →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acov<self::Acov::X*, self::Acov::Y*>*
+    ;
+}
+class Acon<X extends (self::Acon::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acon<self::Acon::X*, self::Acon::Y*>*
+    ;
+}
+class Ainv<X extends (self::Ainv::Y*) →* self::Ainv::Y* = (dynamic) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ainv<self::Ainv::X*, self::Ainv::Y*>*
+    ;
+}
+class AcovBound<X extends () →* self::AcovBound::Y* = () →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AcovBound<self::AcovBound::X*, self::AcovBound::Y*>*
+    ;
+}
+class AconBound<X extends (self::AconBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AconBound<self::AconBound::X*, self::AconBound::Y*>*
+    ;
+}
+class AinvBound<X extends (self::AinvBound::Y*) →* self::AinvBound::Y* = (core::num*) →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AinvBound<self::AinvBound::X*, self::AinvBound::Y*>*
+    ;
+}
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    ;
+}
+class AcovCyclicBound<X extends () →* self::AcovCyclicBound::Y* = () →* self::A<dynamic>*, Y extends self::A<self::AcovCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicBound<self::AcovCyclicBound::X*, self::AcovCyclicBound::Y*>*
+    ;
+}
+class AconCyclicBound<X extends (self::AconCyclicBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends self::A<self::AconCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AconCyclicBound<self::AconCyclicBound::X*, self::AconCyclicBound::Y*>*
+    ;
+}
+class AinvCyclicBound<X extends (self::AinvCyclicBound::Y*) →* self::AinvCyclicBound::Y* = (self::A<dynamic>*) →* self::A<dynamic>*, Y extends self::A<self::AinvCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicBound<self::AinvCyclicBound::X*, self::AinvCyclicBound::Y*>*
+    ;
+}
+class AcovCyclicCoBound<X extends () →* self::AcovCyclicCoBound::Y* = () →* (core::Null?) →* dynamic, Y extends (self::AcovCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicCoBound<self::AcovCyclicCoBound::X*, self::AcovCyclicCoBound::Y*>*
+    ;
+}
+class AconCyclicCoBound<X extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicCoBound<self::AconCyclicCoBound::X*, self::AconCyclicCoBound::Y*>*
+    ;
+}
+class AinvCyclicCoBound<X extends (self::AinvCyclicCoBound::Y*) →* self::AinvCyclicCoBound::Y* = ((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, Y extends (self::AinvCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicCoBound<self::AinvCyclicCoBound::X*, self::AinvCyclicCoBound::Y*>*
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  ;
+static method testTypeAliasAsTypeArgument() → void
+  ;
+static method testNested() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.strong.expect b/pkg/front_end/testcases/nested_variance_test.dart.strong.expect
new file mode 100644
index 0000000..44abf90
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.strong.expect
@@ -0,0 +1,161 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class Acov<X extends () →* self::Acov::Y* = () →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acov<self::Acov::X*, self::Acov::Y*>*
+    : super core::Object::•()
+    ;
+}
+class Acon<X extends (self::Acon::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acon<self::Acon::X*, self::Acon::Y*>*
+    : super core::Object::•()
+    ;
+}
+class Ainv<X extends (self::Ainv::Y*) →* self::Ainv::Y* = (dynamic) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ainv<self::Ainv::X*, self::Ainv::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AcovBound<X extends () →* self::AcovBound::Y* = () →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AcovBound<self::AcovBound::X*, self::AcovBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconBound<X extends (self::AconBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AconBound<self::AconBound::X*, self::AconBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvBound<X extends (self::AinvBound::Y*) →* self::AinvBound::Y* = (core::num*) →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AinvBound<self::AinvBound::X*, self::AinvBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicBound<X extends () →* self::AcovCyclicBound::Y* = () →* self::A<dynamic>*, Y extends self::A<self::AcovCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicBound<self::AcovCyclicBound::X*, self::AcovCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconCyclicBound<X extends (self::AconCyclicBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends self::A<self::AconCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AconCyclicBound<self::AconCyclicBound::X*, self::AconCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicBound<X extends (self::AinvCyclicBound::Y*) →* self::AinvCyclicBound::Y* = (self::A<dynamic>*) →* self::A<dynamic>*, Y extends self::A<self::AinvCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicBound<self::AinvCyclicBound::X*, self::AinvCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicCoBound<X extends () →* self::AcovCyclicCoBound::Y* = () →* (core::Null?) →* dynamic, Y extends (self::AcovCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicCoBound<self::AcovCyclicCoBound::X*, self::AcovCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconCyclicCoBound<X extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicCoBound<self::AconCyclicCoBound::X*, self::AconCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicCoBound<X extends (self::AinvCyclicCoBound::Y*) →* self::AinvCyclicCoBound::Y* = ((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, Y extends (self::AinvCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicCoBound<self::AinvCyclicCoBound::X*, self::AinvCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  return null;
+static method testTypeAliasAsTypeArgument() → void {
+  self::Acov<() →* dynamic, dynamic>* source1;
+  <Y extends self::Acov<() →* dynamic, dynamic>* = dynamic>() →* void fsource1 = self::toF<self::Acov<() →* dynamic, dynamic>*>(source1);
+  <Y extends self::Acov<() →* dynamic, dynamic>* = dynamic>() →* void target1 = fsource1;
+  self::Acon<(core::Null?) →* dynamic, dynamic>* source2;
+  <Y extends self::Acon<(core::Null?) →* dynamic, dynamic>* = dynamic>() →* void fsource2 = self::toF<self::Acon<(core::Null?) →* dynamic, dynamic>*>(source2);
+  <Y extends self::Acon<(core::Null*) →* dynamic, dynamic>* = dynamic>() →* void target2 = fsource2;
+  self::Ainv<(dynamic) →* dynamic, dynamic>* source3;
+  <Y extends self::Ainv<(dynamic) →* dynamic, dynamic>* = dynamic>() →* void fsource3 = self::toF<self::Ainv<(dynamic) →* dynamic, dynamic>*>(source3);
+  <Y extends self::Ainv<(dynamic) →* dynamic, dynamic>* = dynamic>() →* void target3 = fsource3;
+  self::AcovBound<() →* core::num*, core::num*>* source4;
+  <Y extends self::AcovBound<() →* core::num*, core::num*>* = dynamic>() →* void fsource4 = self::toF<self::AcovBound<() →* core::num*, core::num*>*>(source4);
+  <Y extends self::AcovBound<() →* core::num*, core::num*>* = dynamic>() →* void target4 = fsource4;
+  self::AconBound<(core::Null?) →* dynamic, core::num*>* source5;
+  <Y extends self::AconBound<(core::Null?) →* dynamic, core::num*>* = dynamic>() →* void fsource5 = self::toF<self::AconBound<(core::Null?) →* dynamic, core::num*>*>(source5);
+  <Y extends self::AconBound<(core::Null*) →* dynamic, core::num*>* = dynamic>() →* void target5 = fsource5;
+  self::AinvBound<(core::num*) →* core::num*, core::num*>* source6;
+  <Y extends self::AinvBound<(core::num*) →* core::num*, core::num*>* = dynamic>() →* void fsource6 = self::toF<self::AinvBound<(core::num*) →* core::num*, core::num*>*>(source6);
+  <Y extends self::AinvBound<(core::num*) →* core::num*, core::num*>* = dynamic>() →* void target6 = fsource6;
+  self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* source7;
+  <Y extends self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* = dynamic>() →* void fsource7 = self::toF<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>(source7);
+  <Y extends self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* = dynamic>() →* void target7 = fsource7;
+  self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>* source8;
+  <Y extends self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>* = dynamic>() →* void fsource8 = self::toF<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>(source8);
+  <Y extends self::AconCyclicBound<(core::Null*) →* dynamic, self::A<dynamic>*>* = dynamic>() →* void target8 = fsource8;
+  self::AinvCyclicBound<(self::A<dynamic>*) →* self::A<dynamic>*, self::A<dynamic>*>* source9;
+  self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* source10;
+  <Y extends self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* = dynamic>() →* void fsource10 = self::toF<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>(source10);
+  <Y extends self::AcovCyclicCoBound<() →* (core::Null*) →* dynamic, (core::Null*) →* dynamic>* = dynamic>() →* void target10 = fsource10;
+  self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>* source11;
+  <Y extends self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>* = dynamic>() →* void fsource11 = self::toF<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>(source11);
+  <Y extends self::AconCyclicCoBound<(core::Null*) →* dynamic, (core::Null*) →* dynamic>* = dynamic>() →* void target11 = fsource11;
+  self::AinvCyclicCoBound<((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* source12;
+}
+static method testNested() → void {
+  self::B<self::Acov<() →* dynamic, dynamic>*>* source1;
+  <Y extends self::B<self::Acov<() →* dynamic, dynamic>*>* = dynamic>() →* void fsource1 = self::toF<self::B<self::Acov<() →* dynamic, dynamic>*>*>(source1);
+  <Y extends self::B<self::Acov<() →* dynamic, dynamic>*>* = dynamic>() →* void target1 = fsource1;
+  self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>* source2;
+  <Y extends self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>* = dynamic>() →* void fsource2 = self::toF<self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>*>(source2);
+  <Y extends self::B<self::Acon<(core::Null*) →* dynamic, dynamic>*>* = dynamic>() →* void target2 = fsource2;
+  self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* source3;
+  <Y extends self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* = dynamic>() →* void fsource3 = self::toF<self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>*>(source3);
+  <Y extends self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* = dynamic>() →* void target3 = fsource3;
+  self::B<self::AcovBound<() →* core::num*, core::num*>*>* source4;
+  <Y extends self::B<self::AcovBound<() →* core::num*, core::num*>*>* = dynamic>() →* void fsource4 = self::toF<self::B<self::AcovBound<() →* core::num*, core::num*>*>*>(source4);
+  <Y extends self::B<self::AcovBound<() →* core::num*, core::num*>*>* = dynamic>() →* void target4 = fsource4;
+  self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>* source5;
+  <Y extends self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>* = dynamic>() →* void fsource5 = self::toF<self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>*>(source5);
+  <Y extends self::B<self::AconBound<(core::Null*) →* dynamic, core::num*>*>* = dynamic>() →* void target5 = fsource5;
+  self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* source6;
+  <Y extends self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* = dynamic>() →* void fsource6 = self::toF<self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>*>(source6);
+  <Y extends self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* = dynamic>() →* void target6 = fsource6;
+  self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* source7;
+  <Y extends self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* = dynamic>() →* void fsource7 = self::toF<self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>*>(source7);
+  <Y extends self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* = dynamic>() →* void target7 = fsource7;
+  self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>* source8;
+  <Y extends self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>* = dynamic>() →* void fsource8 = self::toF<self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>*>(source8);
+  <Y extends self::B<self::AconCyclicBound<(core::Null*) →* dynamic, self::A<dynamic>*>*>* = dynamic>() →* void target8 = fsource8;
+  self::B<self::AinvCyclicBound<(self::A<dynamic>*) →* self::A<dynamic>*, self::A<dynamic>*>*>* source9;
+  self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source10;
+  <Y extends self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* = dynamic>() →* void fsource10 = self::toF<self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>*>(source10);
+  <Y extends self::B<self::AcovCyclicCoBound<() →* (core::Null*) →* dynamic, (core::Null*) →* dynamic>*>* = dynamic>() →* void target10 = fsource10;
+  self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source11;
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* = dynamic>() →* void fsource11 = self::toF<self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>*>(source11);
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null*) →* dynamic, (core::Null*) →* dynamic>*>* = dynamic>() →* void target11 = fsource11;
+  self::B<self::AinvCyclicCoBound<((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source12;
+}
+static method main() → dynamic {
+  self::testTypeAliasAsTypeArgument();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.strong.transformed.expect b/pkg/front_end/testcases/nested_variance_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..44abf90
--- /dev/null
+++ b/pkg/front_end/testcases/nested_variance_test.dart.strong.transformed.expect
@@ -0,0 +1,161 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class Acov<X extends () →* self::Acov::Y* = () →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acov<self::Acov::X*, self::Acov::Y*>*
+    : super core::Object::•()
+    ;
+}
+class Acon<X extends (self::Acon::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Acon<self::Acon::X*, self::Acon::Y*>*
+    : super core::Object::•()
+    ;
+}
+class Ainv<X extends (self::Ainv::Y*) →* self::Ainv::Y* = (dynamic) →* dynamic, Y extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ainv<self::Ainv::X*, self::Ainv::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AcovBound<X extends () →* self::AcovBound::Y* = () →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AcovBound<self::AcovBound::X*, self::AcovBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconBound<X extends (self::AconBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AconBound<self::AconBound::X*, self::AconBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvBound<X extends (self::AinvBound::Y*) →* self::AinvBound::Y* = (core::num*) →* core::num*, Y extends core::num* = core::num*> extends core::Object {
+  synthetic constructor •() → self::AinvBound<self::AinvBound::X*, self::AinvBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicBound<X extends () →* self::AcovCyclicBound::Y* = () →* self::A<dynamic>*, Y extends self::A<self::AcovCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicBound<self::AcovCyclicBound::X*, self::AcovCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconCyclicBound<X extends (self::AconCyclicBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends self::A<self::AconCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AconCyclicBound<self::AconCyclicBound::X*, self::AconCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicBound<X extends (self::AinvCyclicBound::Y*) →* self::AinvCyclicBound::Y* = (self::A<dynamic>*) →* self::A<dynamic>*, Y extends self::A<self::AinvCyclicBound::Y*>* = self::A<dynamic>*> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicBound<self::AinvCyclicBound::X*, self::AinvCyclicBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AcovCyclicCoBound<X extends () →* self::AcovCyclicCoBound::Y* = () →* (core::Null?) →* dynamic, Y extends (self::AcovCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AcovCyclicCoBound<self::AcovCyclicCoBound::X*, self::AcovCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AconCyclicCoBound<X extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic, Y extends (self::AconCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AconCyclicCoBound<self::AconCyclicCoBound::X*, self::AconCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class AinvCyclicCoBound<X extends (self::AinvCyclicCoBound::Y*) →* self::AinvCyclicCoBound::Y* = ((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, Y extends (self::AinvCyclicCoBound::Y*) →* dynamic = (core::Null?) →* dynamic> extends core::Object {
+  synthetic constructor •() → self::AinvCyclicCoBound<self::AinvCyclicCoBound::X*, self::AinvCyclicCoBound::Y*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  return null;
+static method testTypeAliasAsTypeArgument() → void {
+  self::Acov<() →* dynamic, dynamic>* source1;
+  <Y extends self::Acov<() →* dynamic, dynamic>* = dynamic>() →* void fsource1 = self::toF<self::Acov<() →* dynamic, dynamic>*>(source1);
+  <Y extends self::Acov<() →* dynamic, dynamic>* = dynamic>() →* void target1 = fsource1;
+  self::Acon<(core::Null?) →* dynamic, dynamic>* source2;
+  <Y extends self::Acon<(core::Null?) →* dynamic, dynamic>* = dynamic>() →* void fsource2 = self::toF<self::Acon<(core::Null?) →* dynamic, dynamic>*>(source2);
+  <Y extends self::Acon<(core::Null*) →* dynamic, dynamic>* = dynamic>() →* void target2 = fsource2;
+  self::Ainv<(dynamic) →* dynamic, dynamic>* source3;
+  <Y extends self::Ainv<(dynamic) →* dynamic, dynamic>* = dynamic>() →* void fsource3 = self::toF<self::Ainv<(dynamic) →* dynamic, dynamic>*>(source3);
+  <Y extends self::Ainv<(dynamic) →* dynamic, dynamic>* = dynamic>() →* void target3 = fsource3;
+  self::AcovBound<() →* core::num*, core::num*>* source4;
+  <Y extends self::AcovBound<() →* core::num*, core::num*>* = dynamic>() →* void fsource4 = self::toF<self::AcovBound<() →* core::num*, core::num*>*>(source4);
+  <Y extends self::AcovBound<() →* core::num*, core::num*>* = dynamic>() →* void target4 = fsource4;
+  self::AconBound<(core::Null?) →* dynamic, core::num*>* source5;
+  <Y extends self::AconBound<(core::Null?) →* dynamic, core::num*>* = dynamic>() →* void fsource5 = self::toF<self::AconBound<(core::Null?) →* dynamic, core::num*>*>(source5);
+  <Y extends self::AconBound<(core::Null*) →* dynamic, core::num*>* = dynamic>() →* void target5 = fsource5;
+  self::AinvBound<(core::num*) →* core::num*, core::num*>* source6;
+  <Y extends self::AinvBound<(core::num*) →* core::num*, core::num*>* = dynamic>() →* void fsource6 = self::toF<self::AinvBound<(core::num*) →* core::num*, core::num*>*>(source6);
+  <Y extends self::AinvBound<(core::num*) →* core::num*, core::num*>* = dynamic>() →* void target6 = fsource6;
+  self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* source7;
+  <Y extends self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* = dynamic>() →* void fsource7 = self::toF<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>(source7);
+  <Y extends self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>* = dynamic>() →* void target7 = fsource7;
+  self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>* source8;
+  <Y extends self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>* = dynamic>() →* void fsource8 = self::toF<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>(source8);
+  <Y extends self::AconCyclicBound<(core::Null*) →* dynamic, self::A<dynamic>*>* = dynamic>() →* void target8 = fsource8;
+  self::AinvCyclicBound<(self::A<dynamic>*) →* self::A<dynamic>*, self::A<dynamic>*>* source9;
+  self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* source10;
+  <Y extends self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* = dynamic>() →* void fsource10 = self::toF<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>(source10);
+  <Y extends self::AcovCyclicCoBound<() →* (core::Null*) →* dynamic, (core::Null*) →* dynamic>* = dynamic>() →* void target10 = fsource10;
+  self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>* source11;
+  <Y extends self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>* = dynamic>() →* void fsource11 = self::toF<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>(source11);
+  <Y extends self::AconCyclicCoBound<(core::Null*) →* dynamic, (core::Null*) →* dynamic>* = dynamic>() →* void target11 = fsource11;
+  self::AinvCyclicCoBound<((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>* source12;
+}
+static method testNested() → void {
+  self::B<self::Acov<() →* dynamic, dynamic>*>* source1;
+  <Y extends self::B<self::Acov<() →* dynamic, dynamic>*>* = dynamic>() →* void fsource1 = self::toF<self::B<self::Acov<() →* dynamic, dynamic>*>*>(source1);
+  <Y extends self::B<self::Acov<() →* dynamic, dynamic>*>* = dynamic>() →* void target1 = fsource1;
+  self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>* source2;
+  <Y extends self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>* = dynamic>() →* void fsource2 = self::toF<self::B<self::Acon<(core::Null?) →* dynamic, dynamic>*>*>(source2);
+  <Y extends self::B<self::Acon<(core::Null*) →* dynamic, dynamic>*>* = dynamic>() →* void target2 = fsource2;
+  self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* source3;
+  <Y extends self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* = dynamic>() →* void fsource3 = self::toF<self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>*>(source3);
+  <Y extends self::B<self::Ainv<(dynamic) →* dynamic, dynamic>*>* = dynamic>() →* void target3 = fsource3;
+  self::B<self::AcovBound<() →* core::num*, core::num*>*>* source4;
+  <Y extends self::B<self::AcovBound<() →* core::num*, core::num*>*>* = dynamic>() →* void fsource4 = self::toF<self::B<self::AcovBound<() →* core::num*, core::num*>*>*>(source4);
+  <Y extends self::B<self::AcovBound<() →* core::num*, core::num*>*>* = dynamic>() →* void target4 = fsource4;
+  self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>* source5;
+  <Y extends self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>* = dynamic>() →* void fsource5 = self::toF<self::B<self::AconBound<(core::Null?) →* dynamic, core::num*>*>*>(source5);
+  <Y extends self::B<self::AconBound<(core::Null*) →* dynamic, core::num*>*>* = dynamic>() →* void target5 = fsource5;
+  self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* source6;
+  <Y extends self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* = dynamic>() →* void fsource6 = self::toF<self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>*>(source6);
+  <Y extends self::B<self::AinvBound<(core::num*) →* core::num*, core::num*>*>* = dynamic>() →* void target6 = fsource6;
+  self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* source7;
+  <Y extends self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* = dynamic>() →* void fsource7 = self::toF<self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>*>(source7);
+  <Y extends self::B<self::AcovCyclicBound<() →* self::A<dynamic>*, self::A<dynamic>*>*>* = dynamic>() →* void target7 = fsource7;
+  self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>* source8;
+  <Y extends self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>* = dynamic>() →* void fsource8 = self::toF<self::B<self::AconCyclicBound<(core::Null?) →* dynamic, self::A<dynamic>*>*>*>(source8);
+  <Y extends self::B<self::AconCyclicBound<(core::Null*) →* dynamic, self::A<dynamic>*>*>* = dynamic>() →* void target8 = fsource8;
+  self::B<self::AinvCyclicBound<(self::A<dynamic>*) →* self::A<dynamic>*, self::A<dynamic>*>*>* source9;
+  self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source10;
+  <Y extends self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* = dynamic>() →* void fsource10 = self::toF<self::B<self::AcovCyclicCoBound<() →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>*>(source10);
+  <Y extends self::B<self::AcovCyclicCoBound<() →* (core::Null*) →* dynamic, (core::Null*) →* dynamic>*>* = dynamic>() →* void target10 = fsource10;
+  self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source11;
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* = dynamic>() →* void fsource11 = self::toF<self::B<self::AconCyclicCoBound<(core::Null?) →* dynamic, (core::Null?) →* dynamic>*>*>(source11);
+  <Y extends self::B<self::AconCyclicCoBound<(core::Null*) →* dynamic, (core::Null*) →* dynamic>*>* = dynamic>() →* void target11 = fsource11;
+  self::B<self::AinvCyclicCoBound<((core::Null?) →* dynamic) →* (core::Null?) →* dynamic, (core::Null?) →* dynamic>*>* source12;
+}
+static method main() → dynamic {
+  self::testTypeAliasAsTypeArgument();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
index eb8a0fd..30f7d49 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F = () → void;
-class A<T extends core::Object* = dynamic> extends core::Object {
+class A<T extends core::Object? = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     ;
 }
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
index a1e7b4a..71aef3b 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F = () → void;
-class A<T extends core::Object* = dynamic> extends core::Object {
+class A<T extends core::Object? = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
index a1e7b4a..71aef3b 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F = () → void;
-class A<T extends core::Object* = dynamic> extends core::Object {
+class A<T extends core::Object? = dynamic> extends core::Object {
   synthetic constructor •() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart b/pkg/front_end/testcases/nnbd/null_check.dart
new file mode 100644
index 0000000..110d74f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_check.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 Class {
+  int? field;
+  int? method() => field;
+  Class operator +(Class other) => new Class();
+}
+
+main() {
+  Class? c = new Class();
+  c!;
+  c!.field;
+  c!.field = 42;
+  c!.method;
+  c!.method();
+  c!.field!.toString();
+  c!.method()!.toString();
+  c! + c;
+  c! + c!;
+  c + c!;
+  (c + c)!;
+
+  bool? o = true;
+  !o! ? !o! : !!o!!;
+  !(o!) ? (!o)! : (!(!o)!)!;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect
new file mode 100644
index 0000000..5dd134e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field core::int? field;
+  synthetic constructor •() → self::Class*
+    ;
+  method method() → core::int?
+    ;
+  operator +(self::Class other) → self::Class
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
new file mode 100644
index 0000000..d9dcefa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -0,0 +1,31 @@
+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::•()
+    ;
+  method method() → core::int?
+    return this.{self::Class::field};
+  operator +(self::Class other) → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {
+  self::Class? c = new self::Class::•();
+  c!;
+  c!.{self::Class::field};
+  c!.{self::Class::field} = 42;
+  c!.{self::Class::method};
+  c!.{self::Class::method}();
+  c!.{self::Class::field}!.{core::int::toString}();
+  c!.{self::Class::method}()!.{core::int::toString}();
+  c!.{self::Class::+}(c);
+  c!.{self::Class::+}(c!);
+  c.{self::Class::+}(c!);
+  c.{self::Class::+}(c)!;
+  core::bool? o = true;
+  !o! ?{core::bool} !o! : !!o!!;
+  !o! ?{core::bool} (!o)! : (!(!o)!)!;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
new file mode 100644
index 0000000..d9dcefa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+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::•()
+    ;
+  method method() → core::int?
+    return this.{self::Class::field};
+  operator +(self::Class other) → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {
+  self::Class? c = new self::Class::•();
+  c!;
+  c!.{self::Class::field};
+  c!.{self::Class::field} = 42;
+  c!.{self::Class::method};
+  c!.{self::Class::method}();
+  c!.{self::Class::field}!.{core::int::toString}();
+  c!.{self::Class::method}()!.{core::int::toString}();
+  c!.{self::Class::+}(c);
+  c!.{self::Class::+}(c!);
+  c.{self::Class::+}(c!);
+  c.{self::Class::+}(c)!;
+  core::bool? o = true;
+  !o! ?{core::bool} !o! : !!o!!;
+  !o! ?{core::bool} (!o)! : (!(!o)!)!;
+}
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 d0af2e7..610a9ee 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
@@ -33,7 +33,7 @@
   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 {
-  return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
+  return let final core::int #t1 = f.call() in #t1.{core::num::==}(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
 }
 
 constants  {
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 d0af2e7..610a9ee 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
@@ -33,7 +33,7 @@
   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 {
-  return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
+  return let final core::int #t1 = f.call() in #t1.{core::num::==}(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart b/pkg/front_end/testcases/nnbd/type_parameter_types.dart
new file mode 100644
index 0000000..67353a0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<X extends Object, Y extends Object?> {
+  X foo() => null;
+  X? bar() => null;
+  Y baz() => null;
+}
+
+class B<X extends List<Y>, Y extends Object?> {
+  foo(X x, Y y) {}
+}
+
+class C<X extends List<Y>?, Y extends List<X>?> {
+  foo(X x, Y y) {}
+}
+
+class D<X extends Y, Y extends Z, Z> {
+  foo(X x, Y y, Z z) {}
+}
+
+main() {
+  X fun1<X extends Object, Y extends Object?>() => null;
+  Y fun2<X extends Object, Y extends Object?>() => null;
+  X fun3<X extends List<Y>, Y extends Object?>() => null;
+  Y fun4<X extends List<Y>, Y extends Object?>() => null;
+  X fun5<X extends List<Y>?, Y extends List<X>?>() => null;
+  Y fun6<X extends List<Y>?, Y extends List<X>?>() => null;
+  X fun7<X extends Y, Y extends Z, Z>() => null;
+  Y fun8<X extends Y, Y extends Z, Z>() => null;
+  Z fun9<X extends Y, Y extends Z, Z>() => null;
+}
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
new file mode 100644
index 0000000..ce46e5f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+    ;
+  method foo() → self::A::X
+    ;
+  method bar() → self::A::X?
+    ;
+  method baz() → self::A::Y%
+    ;
+}
+class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+    ;
+  method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic
+    ;
+}
+class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+    ;
+  method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic
+    ;
+}
+class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+    ;
+  method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
new file mode 100644
index 0000000..83c7544
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
@@ -0,0 +1,53 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+    : super core::Object::•()
+    ;
+  method foo() → self::A::X
+    return null;
+  method bar() → self::A::X?
+    return null;
+  method baz() → self::A::Y%
+    return null;
+}
+class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic {}
+}
+class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic {}
+}
+class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic {}
+}
+static method main() → dynamic {
+  function fun1<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → X
+    return null;
+  function fun2<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → Y%
+    return null;
+  function fun3<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → X
+    return null;
+  function fun4<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → Y%
+    return null;
+  function fun5<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → X%
+    return null;
+  function fun6<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → Y%
+    return null;
+  function fun7<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → X%
+    return null;
+  function fun8<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Y%
+    return null;
+  function fun9<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Z%
+    return null;
+}
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..83c7544
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
@@ -0,0 +1,53 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+    : super core::Object::•()
+    ;
+  method foo() → self::A::X
+    return null;
+  method bar() → self::A::X?
+    return null;
+  method baz() → self::A::Y%
+    return null;
+}
+class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic {}
+}
+class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic {}
+}
+class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+    : super core::Object::•()
+    ;
+  method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic {}
+}
+static method main() → dynamic {
+  function fun1<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → X
+    return null;
+  function fun2<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → Y%
+    return null;
+  function fun3<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → X
+    return null;
+  function fun4<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → Y%
+    return null;
+  function fun5<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → X%
+    return null;
+  function fun6<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → Y%
+    return null;
+  function fun7<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → X%
+    return null;
+  function fun8<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Y%
+    return null;
+  function fun9<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Z%
+    return null;
+}
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill
new file mode 100644
index 0000000..95c4245
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
index c7e3f5b..c501ddc 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
@@ -48,10 +48,6 @@
 //   C notEvenAConstructor(a) = h;
 //                            ^
 //
-// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
-//   C notEvenAConstructor(a) = h;
-//                              ^
-//
 // pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/rasta/issue_000044.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
index 2430f63..54451d2 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
@@ -48,10 +48,6 @@
 //   C notEvenAConstructor(a) = h;
 //                            ^
 //
-// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
-//   C notEvenAConstructor(a) = h;
-//                              ^
-//
 // pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/rasta/issue_000044.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.
diff --git a/pkg/front_end/testcases/rasta/super.dart.strong.expect b/pkg/front_end/testcases/rasta/super.dart.strong.expect
index 7ac227e..ac97d8e 100644
--- a/pkg/front_end/testcases/rasta/super.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.strong.expect
@@ -589,12 +589,12 @@
     self::use(let final dynamic #t46 = super.{self::A::h} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t46);
     super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
     self::use(let final dynamic #t47 = super.{self::A::i} in #t47.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t47);
-    let final core::int* #t48 = 87 in super.{self::A::[]}(#t48).{core::Object::==}(null) ?{dynamic} let final core::int* #t49 = 42 in let final void #t50 = super.{self::A::[]=}(#t48, #t49) in #t49 : null;
-    self::use(let final core::int* #t51 = 87 in let final dynamic #t52 = super.{self::A::[]}(#t51) in #t52.{core::Object::==}(null) ?{dynamic} let final core::int* #t53 = 42 in let final void #t54 = super.{self::A::[]=}(#t51, #t53) in #t53 : #t52);
+    let final core::int* #t48 = 87 in super.{self::A::[]}(#t48).{core::Object::==}(null) ?{dynamic} super.{self::A::[]=}(#t48, 42) : null;
+    self::use(let final core::int* #t49 = 87 in let final dynamic #t50 = super.{self::A::[]}(#t49) in #t50.{core::Object::==}(null) ?{dynamic} let final core::int* #t51 = 42 in let final void #t52 = super.{self::A::[]=}(#t49, #t51) in #t51 : #t50);
     super.{self::A::m}.{core::Object::==}(null) ?{core::Object*} super.m = 42 : null;
-    self::use(let final () →* void #t55 = super.{self::A::m} in #t55.{core::Object::==}(null) ?{core::Object*} super.m = 42 : #t55);
+    self::use(let final () →* void #t53 = super.{self::A::m} in #t53.{core::Object::==}(null) ?{core::Object*} super.m = 42 : #t53);
     super.{self::A::n}.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : null;
-    self::use(let final () →* void #t56 = super.{self::A::n} in #t56.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : #t56);
+    self::use(let final () →* void #t54 = super.{self::A::n} in #t54.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : #t54);
     super.{self::A::a} = super.{self::A::a}.+(42);
     self::use(super.{self::A::a} = super.{self::A::a}.+(42));
     super.{self::A::b} = super.{self::B::b}.+(42);
@@ -613,8 +613,8 @@
     self::use(super.{self::A::h} = super.{self::A::h}.+(42));
     super.{self::B::i} = super.{self::A::i}.+(42);
     self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final core::int* #t57 = 87 in super.{self::A::[]=}(#t57, super.{self::A::[]}(#t57).+(42));
-    self::use(let final core::int* #t58 = 87 in let final dynamic #t59 = super.{self::A::[]}(#t58).+(42) in let final void #t60 = super.{self::A::[]=}(#t58, #t59) in #t59);
+    let final core::int* #t55 = 87 in super.{self::A::[]=}(#t55, super.{self::A::[]}(#t55).+(42));
+    self::use(let final core::int* #t56 = 87 in let final dynamic #t57 = super.{self::A::[]}(#t56).+(42) in let final void #t58 = super.{self::A::[]=}(#t56, #t57) in #t57);
     super.m = invalid-expression "pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class 'void Function()'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.m += 42;
@@ -649,8 +649,8 @@
     self::use(super.{self::A::h} = super.{self::A::h}.-(42));
     super.{self::B::i} = super.{self::A::i}.-(42);
     self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final core::int* #t61 = 87 in super.{self::A::[]=}(#t61, super.{self::A::[]}(#t61).-(42));
-    self::use(let final core::int* #t62 = 87 in let final dynamic #t63 = super.{self::A::[]}(#t62).-(42) in let final void #t64 = super.{self::A::[]=}(#t62, #t63) in #t63);
+    let final core::int* #t59 = 87 in super.{self::A::[]=}(#t59, super.{self::A::[]}(#t59).-(42));
+    self::use(let final core::int* #t60 = 87 in let final dynamic #t61 = super.{self::A::[]}(#t60).-(42) in let final void #t62 = super.{self::A::[]=}(#t60, #t61) in #t61);
     super.m = invalid-expression "pkg/front_end/testcases/rasta/super.dart:247:13: Error: The method '-' isn't defined for the class 'void Function()'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     super.m -= 42;
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
index 47838e6..76fc4ed 100644
--- a/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
@@ -343,172 +343,172 @@
     self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:36:9: Error: Setter not found: 'Func'.
     use(Func = 42);
         ^^^^");
-    let final dynamic #t1 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
     C++;
     ^";
-    self::use(let final dynamic #t2 = self::C<dynamic>* in let final dynamic #t3 = #t2 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
     use(C++);
-        ^" in #t3);
-    let final dynamic #t5 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
     dynamic++;
     ^^^^^^^";
-    self::use(let final dynamic #t6 = dynamic in let final dynamic #t7 = #t6 in let final dynamic #t8 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
     use(dynamic++);
-        ^^^^^^^" in #t7);
-    let final dynamic #t9 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
     T++;
     ^";
-    self::use(let final dynamic #t10 = self::C::T* in let final dynamic #t11 = #t10 in let final dynamic #t12 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
     use(T++);
-        ^" in #t11);
-    let final dynamic #t13 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
     Func++;
     ^^^^";
-    self::use(let final dynamic #t14 = () →* void in let final dynamic #t15 = #t14 in let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
     use(Func++);
-        ^^^^" in #t15);
-    let final dynamic #t17 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
     ++C;
       ^";
-    self::use(let final dynamic #t18 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
     use(++C);
           ^");
-    let final dynamic #t19 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
     ++dynamic;
       ^^^^^^^";
-    self::use(let final dynamic #t20 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
     use(++dynamic);
           ^^^^^^^");
-    let final dynamic #t21 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
     ++T;
       ^";
-    self::use(let final dynamic #t22 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
     use(++T);
           ^");
-    let final dynamic #t23 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
     ++Func;
       ^^^^";
-    self::use(let final dynamic #t24 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
     use(++Func);
           ^^^^");
-    let final dynamic #t25 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
     C--;
     ^";
-    self::use(let final dynamic #t26 = self::C<dynamic>* in let final dynamic #t27 = #t26 in let final dynamic #t28 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
     use(C--);
-        ^" in #t27);
-    let final dynamic #t29 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
     dynamic--;
     ^^^^^^^";
-    self::use(let final dynamic #t30 = dynamic in let final dynamic #t31 = #t30 in let final dynamic #t32 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
     use(dynamic--);
-        ^^^^^^^" in #t31);
-    let final dynamic #t33 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
     T--;
     ^";
-    self::use(let final dynamic #t34 = self::C::T* in let final dynamic #t35 = #t34 in let final dynamic #t36 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
     use(T--);
-        ^" in #t35);
-    let final dynamic #t37 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
     Func--;
     ^^^^";
-    self::use(let final dynamic #t38 = () →* void in let final dynamic #t39 = #t38 in let final dynamic #t40 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
     use(Func--);
-        ^^^^" in #t39);
-    let final dynamic #t41 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
     --C;
       ^";
-    self::use(let final dynamic #t42 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
     use(--C);
           ^");
-    let final dynamic #t43 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
     --dynamic;
       ^^^^^^^";
-    self::use(let final dynamic #t44 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
     use(--dynamic);
           ^^^^^^^");
-    let final dynamic #t45 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
     --T;
       ^";
-    self::use(let final dynamic #t46 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
     use(--T);
           ^");
-    let final dynamic #t47 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
     --Func;
       ^^^^";
-    self::use(let final dynamic #t48 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
     use(--Func);
           ^^^^");
-    let final dynamic #t49 = self::C<dynamic>* in #t49.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
+    self::C<dynamic>*.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
     C ??= 42;
     ^" : null;
-    self::use(let final dynamic #t50 = self::C<dynamic>* in let final dynamic #t51 = #t50 in #t51.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
+    self::use(let final core::Type* #t1 = self::C<dynamic>* in #t1.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
     use(C ??= 42);
-        ^" : #t51);
-    let final dynamic #t52 = dynamic in #t52.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
+        ^" : #t1);
+    dynamic.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
     dynamic ??= 42;
     ^^^^^^^" : null;
-    self::use(let final dynamic #t53 = dynamic in let final dynamic #t54 = #t53 in #t54.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
+    self::use(let final core::Type* #t2 = dynamic in #t2.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
     use(dynamic ??= 42);
-        ^^^^^^^" : #t54);
-    let final dynamic #t55 = self::C::T* in #t55.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
+        ^^^^^^^" : #t2);
+    self::C::T*.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
     T ??= 42;
     ^" : null;
-    self::use(let final dynamic #t56 = self::C::T* in let final dynamic #t57 = #t56 in #t57.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
+    self::use(let final core::Type* #t3 = self::C::T* in #t3.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
     use(T ??= 42);
-        ^" : #t57);
-    let final dynamic #t58 = () →* void in #t58.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
+        ^" : #t3);
+    () →* void.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
     Func ??= 42;
     ^^^^" : null;
-    self::use(let final dynamic #t59 = () →* void in let final dynamic #t60 = #t59 in #t60.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
+    self::use(let final core::Type* #t4 = () →* void in #t4.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
     use(Func ??= 42);
-        ^^^^" : #t60);
-    let final dynamic #t61 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
+        ^^^^" : #t4);
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
     C += 42;
     ^";
-    self::use(let final dynamic #t62 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
     use(C += 42);
         ^");
-    let final dynamic #t63 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
     dynamic += 42;
     ^^^^^^^";
-    self::use(let final dynamic #t64 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
     use(dynamic += 42);
         ^^^^^^^");
-    let final dynamic #t65 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
     T += 42;
     ^";
-    self::use(let final dynamic #t66 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
     use(T += 42);
         ^");
-    let final dynamic #t67 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
     Func += 42;
     ^^^^";
-    self::use(let final dynamic #t68 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
     use(Func += 42);
         ^^^^");
-    let final dynamic #t69 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
     C -= 42;
     ^";
-    self::use(let final dynamic #t70 = self::C<dynamic>* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
     use(C -= 42);
         ^");
-    let final dynamic #t71 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
     dynamic -= 42;
     ^^^^^^^";
-    self::use(let final dynamic #t72 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
     use(dynamic -= 42);
         ^^^^^^^");
-    let final dynamic #t73 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
     T -= 42;
     ^";
-    self::use(let final dynamic #t74 = self::C::T* in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
     use(T -= 42);
         ^");
-    let final dynamic #t75 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
     Func -= 42;
     ^^^^";
-    self::use(let final dynamic #t76 = () →* void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
     use(Func -= 42);
         ^^^^");
   }
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
new file mode 100644
index 0000000..76fc4ed
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
@@ -0,0 +1,522 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
+//     dynamic();
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:23:9: Error: Method not found: 'dynamic'.
+//     use(dynamic());
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:24:5: Error: Method not found: 'T'.
+//     T();
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:25:9: Error: Method not found: 'T'.
+//     use(T());
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:26:5: Error: Method not found: 'Func'.
+//     Func();
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:27:9: Error: Method not found: 'Func'.
+//     use(Func());
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:29:5: Error: Setter not found: 'C'.
+//     C = 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:30:9: Error: Setter not found: 'C'.
+//     use(C = 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:31:5: Error: Setter not found: 'dynamic'.
+//     dynamic = 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:32:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic = 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:33:5: Error: Setter not found: 'T'.
+//     T = 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:34:9: Error: Setter not found: 'T'.
+//     use(T = 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:35:5: Error: Setter not found: 'Func'.
+//     Func = 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:36:9: Error: Setter not found: 'Func'.
+//     use(Func = 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
+//     C++;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
+//     use(C++);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
+//     dynamic++;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic++);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
+//     T++;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
+//     use(T++);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
+//     Func++;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
+//     use(Func++);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
+//     ++C;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
+//     use(++C);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
+//     ++dynamic;
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
+//     use(++dynamic);
+//           ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
+//     ++T;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
+//     use(++T);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
+//     ++Func;
+//       ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
+//     use(++Func);
+//           ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
+//     C--;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
+//     use(C--);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
+//     dynamic--;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic--);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
+//     T--;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
+//     use(T--);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
+//     Func--;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
+//     use(Func--);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
+//     --C;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
+//     use(--C);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
+//     --dynamic;
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
+//     use(--dynamic);
+//           ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
+//     --T;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
+//     use(--T);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
+//     --Func;
+//       ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
+//     use(--Func);
+//           ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
+//     C ??= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
+//     use(C ??= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
+//     dynamic ??= 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic ??= 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
+//     T ??= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
+//     use(T ??= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
+//     Func ??= 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
+//     use(Func ??= 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
+//     C += 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
+//     use(C += 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
+//     dynamic += 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic += 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
+//     T += 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
+//     use(T += 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
+//     Func += 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
+//     use(Func += 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
+//     C -= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
+//     use(C -= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
+//     dynamic -= 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic -= 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
+//     T -= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
+//     use(T -= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
+//     Func -= 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
+//     use(Func -= 42);
+//         ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef Func = () →* void;
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  method test() → dynamic {
+    self::C<dynamic>*;
+    self::use(self::C<dynamic>*);
+    dynamic;
+    self::use(dynamic);
+    self::C::T*;
+    self::use(self::C::T*);
+    () →* void;
+    self::use(() →* void);
+    new self::C::•<dynamic>();
+    self::use(new self::C::•<dynamic>());
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
+    dynamic();
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:23:9: Error: Method not found: 'dynamic'.
+    use(dynamic());
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:24:5: Error: Method not found: 'T'.
+    T();
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:25:9: Error: Method not found: 'T'.
+    use(T());
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:26:5: Error: Method not found: 'Func'.
+    Func();
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:27:9: Error: Method not found: 'Func'.
+    use(Func());
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:29:5: Error: Setter not found: 'C'.
+    C = 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:30:9: Error: Setter not found: 'C'.
+    use(C = 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:31:5: Error: Setter not found: 'dynamic'.
+    dynamic = 42;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:32:9: Error: Setter not found: 'dynamic'.
+    use(dynamic = 42);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:33:5: Error: Setter not found: 'T'.
+    T = 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:34:9: Error: Setter not found: 'T'.
+    use(T = 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:35:5: Error: Setter not found: 'Func'.
+    Func = 42;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:36:9: Error: Setter not found: 'Func'.
+    use(Func = 42);
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
+    C++;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
+    use(C++);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
+    dynamic++;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
+    use(dynamic++);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
+    T++;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
+    use(T++);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
+    Func++;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
+    use(Func++);
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
+    ++C;
+      ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
+    use(++C);
+          ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
+    ++dynamic;
+      ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
+    use(++dynamic);
+          ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
+    ++T;
+      ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
+    use(++T);
+          ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
+    ++Func;
+      ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
+    use(++Func);
+          ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
+    C--;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
+    use(C--);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
+    dynamic--;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
+    use(dynamic--);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
+    T--;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
+    use(T--);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
+    Func--;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
+    use(Func--);
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
+    --C;
+      ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
+    use(--C);
+          ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
+    --dynamic;
+      ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
+    use(--dynamic);
+          ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
+    --T;
+      ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
+    use(--T);
+          ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
+    --Func;
+      ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
+    use(--Func);
+          ^^^^");
+    self::C<dynamic>*.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
+    C ??= 42;
+    ^" : null;
+    self::use(let final core::Type* #t1 = self::C<dynamic>* in #t1.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
+    use(C ??= 42);
+        ^" : #t1);
+    dynamic.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
+    dynamic ??= 42;
+    ^^^^^^^" : null;
+    self::use(let final core::Type* #t2 = dynamic in #t2.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
+    use(dynamic ??= 42);
+        ^^^^^^^" : #t2);
+    self::C::T*.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
+    T ??= 42;
+    ^" : null;
+    self::use(let final core::Type* #t3 = self::C::T* in #t3.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
+    use(T ??= 42);
+        ^" : #t3);
+    () →* void.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
+    Func ??= 42;
+    ^^^^" : null;
+    self::use(let final core::Type* #t4 = () →* void in #t4.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
+    use(Func ??= 42);
+        ^^^^" : #t4);
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
+    C += 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
+    use(C += 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
+    dynamic += 42;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
+    use(dynamic += 42);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
+    T += 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
+    use(T += 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
+    Func += 42;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
+    use(Func += 42);
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
+    C -= 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
+    use(C -= 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
+    dynamic -= 42;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
+    use(dynamic -= 42);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
+    T -= 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
+    use(T -= 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
+    Func -= 42;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
+    use(Func -= 42);
+        ^^^^");
+  }
+}
+static method use(dynamic x) → dynamic {
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+    throw "Shouldn't happen";
+}
+static method main() → dynamic {
+  new self::C::•<dynamic>().{self::C::test}();
+}
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
index 92d39b4..eccfc19 100644
--- a/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
@@ -23,7 +23,7 @@
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Setter not found: 'Foo'.
   Foo = null;
   ^^^";
-  let final dynamic #t1 = () →* void in #t1.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
+  () →* void.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
   Foo ??= null;
   ^^^" : null;
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
new file mode 100644
index 0000000..eccfc19
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Setter not found: 'Foo'.
+//   Foo = null;
+//   ^^^
+//
+// pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
+//   Foo ??= null;
+//   ^^^
+//
+// pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
+//   Foo();
+//   ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef Foo = () →* void;
+static method main() → dynamic {
+  core::print(() →* void);
+  invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Setter not found: 'Foo'.
+  Foo = null;
+  ^^^";
+  () →* void.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
+  Foo ??= null;
+  ^^^" : null;
+  invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
+  Foo();
+  ^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
index ad3c1dc..c41f760 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
@@ -2,14 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:12:13: Error: Getter not found: 'key'.
-//       print(key);
-//             ^^^
-//
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:11:10: Error: Setter not found: 'key'.
-//     for (key in x) {
-//          ^^^
-//
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Setter not found: 'Fisk'.
 //     for (Fisk in x) {
 //          ^^^^
@@ -30,10 +22,6 @@
 //     for (1 in x) {
 //          ^
 //
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:24:13: Error: Getter not found: 'key'.
-//       print(key);
-//             ^^^
-//
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
 //     for (1 in x) {
 //          ^
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
index ad3c1dc..c41f760 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
@@ -2,14 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:12:13: Error: Getter not found: 'key'.
-//       print(key);
-//             ^^^
-//
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:11:10: Error: Setter not found: 'key'.
-//     for (key in x) {
-//          ^^^
-//
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Setter not found: 'Fisk'.
 //     for (Fisk in x) {
 //          ^^^^
@@ -30,10 +22,6 @@
 //     for (1 in x) {
 //          ^
 //
-// pkg/front_end/testcases/rasta/unresolved_for_in.dart:24:13: Error: Getter not found: 'key'.
-//       print(key);
-//             ^^^
-//
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
 //     for (1 in x) {
 //          ^
diff --git a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
index ff2cc72..932bc89 100644
--- a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
@@ -6,18 +6,18 @@
 //     super[4] = 42;
 //          ^
 //
-// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]'.
-//     super[4] += 5;
-//          ^
-//
-// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
-//     super[4] += 5;
-//          ^
-//
 // pkg/front_end/testcases/rasta/unresolved_recovery.dart:9:17: Error: Superclass has no method named '[]'.
 //     return super[2];
 //                 ^
 //
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]'.
+//     super[4] += 5;
+//          ^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
+//     super[4] += 5;
+//          ^^^
+//
 // pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:3: Error: 'on' isn't a type.
 //   on Exception catch (e) { }
 //   ^^
@@ -51,7 +51,9 @@
     ;
   method foo() → dynamic {
     super.[]=(4, 42);
-    let final core::int* #t1 = 4 in super.[]=(#t1, super.[](#t1).+(5));
+    let final core::int* #t1 = 4 in invalid-expression "pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
+    super[4] += 5;
+         ^^^";
     return super.[](2);
   }
 }
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
index bff625e..91c2fcb 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Foo<T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
 static field <T extends core::Object* = dynamic>(T*) →* T* x;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
index c685791..34ce4a3b 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Foo<T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
 static field <T extends core::Object* = dynamic>(T*) →* T* x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
index c685791..34ce4a3b 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Foo<T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
 static field <T extends core::Object* = dynamic>(T*) →* T* x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
index cf09cb2..4723bc6 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
@@ -23,9 +23,9 @@
   self::i;
 }
 static method test2() → core::int* {
-  return (let final dynamic #t3 = self::i in let final dynamic #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
+  return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
   return (i) ++ (i);
-           ^" in #t4) as{TypeError} core::int*;
+           ^" as{TypeError} core::int*;
   self::i;
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
index 3d41703..4723bc6 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
@@ -23,9 +23,9 @@
   self::i;
 }
 static method test2() → core::int* {
-  return (let final core::int* #t3 = self::i in let final core::int* #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
+  return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
   return (i) ++ (i);
-           ^" in #t4) as{TypeError} core::int*;
+           ^" as{TypeError} core::int*;
   self::i;
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
index 52693de..a734b9c 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef C<A extends core::Object* = dynamic, K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
 static method producer<K extends core::Object* = dynamic>() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
index cc1d463..69a285c 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef C<A extends core::Object* = dynamic, K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
 static method producer<K extends core::Object* = dynamic>() → dynamic {
   return <A extends core::Object* = dynamic>(core::int* v1) → <B extends core::Object* = dynamic>(A*, self::producer::K*, B*) →* core::int* {
     return <B extends core::Object* = dynamic>(A* v2, self::producer::K* v3, B* v4) → core::int* => 0;
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
index cc1d463..69a285c 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef C<A extends core::Object* = dynamic, K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
 static method producer<K extends core::Object* = dynamic>() → dynamic {
   return <A extends core::Object* = dynamic>(core::int* v1) → <B extends core::Object* = dynamic>(A*, self::producer::K*, B*) →* core::int* {
     return <B extends core::Object* = dynamic>(A* v2, self::producer::K* v3, B* v4) → core::int* => 0;
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
index e4d2c10..f28e322 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Error: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y});
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Context: Both members are inherited by the non-abstract class 'E'.
-// class E extends D {
-//       ^
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Error: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
+// class C extends A implements B {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Context: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:10:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y}) => y;
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Context: Both members are inherited by the non-abstract class 'C'.
-// class C extends A implements B {
-//       ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
index 6827b4c..b9e0bd5 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Error: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y});
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Context: Both members are inherited by the non-abstract class 'E'.
-// class E extends D {
-//       ^
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Error: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
+// class C extends A implements B {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Context: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:10:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y}) => y;
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Context: Both members are inherited by the non-abstract class 'C'.
-// class C extends A implements B {
-//       ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
index 6827b4c..b9e0bd5 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Error: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y});
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Context: Both members are inherited by the non-abstract class 'E'.
-// class E extends D {
-//       ^
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Error: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
+// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
+// class C extends A implements B {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:6:3: Context: The method 'A.foo' has fewer named arguments than those of overridden method 'B.foo'.
 //   foo(int x) => x;
 //   ^
 // pkg/front_end/testcases/regress/issue_32660.dart:10:3: Context: This is the overridden method ('foo').
 //   foo(int x, {int y}) => y;
 //   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Context: Both members are inherited by the non-abstract class 'C'.
-// class C extends A implements B {
-//       ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.outline.expect
index e75c3f5..1e1f818 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.expect
index a570c3b..af9bd50 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.transformed.expect
index a570c3b..af9bd50 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.outline.expect
index e13202c..5c8b74d 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
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 ce550cf..e3448ed 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
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 ce550cf..e3448ed 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.outline.expect
index e0dbc15..1debb50 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.expect
index 45979f9..81ef72b 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
index 45979f9..81ef72b 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.outline.expect
index e0dbc15..1debb50 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
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 77140dc..75a8771 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
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 77140dc..75a8771 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
index 20694a1..3ab6c88 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void _x;
   constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
index 70de15e..b6cfaea 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void _x;
   constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
index 70de15e..b6cfaea 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void _x;
   constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.outline.expect
index 1a27346..3f570d1 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.expect
index 98d67c0..4fe5da3 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
index 98d67c0..4fe5da3 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void y = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.outline.expect
index a2ffb5b..7dbf41e 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.expect
index 20544dd..30b8696 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
index 20544dd..30b8696 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.outline.expect
index a2ffb5b..7dbf41e 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
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 b534829..2e4bee0 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
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 b534829..2e4bee0 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.outline.expect
index 0362716..97dc71c 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.expect
index 80bd16a..eb2c2fb 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.transformed.expect
index 80bd16a..eb2c2fb 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic> = (T*) →* U*;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.outline.expect
index bbf9deb..015b873 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.expect
index c335d83..db6c80a 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.transformed.expect
index c335d83..db6c80a 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C extends core::Object {
   synthetic constructor •() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.outline.expect
index 8f154d7..f94fe8d 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field self::C::T* x;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.expect
index 771601a..60677cd 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field self::C::T* x = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.transformed.expect
index 771601a..60677cd 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   generic-covariant-impl field self::C::T* x = null;
   synthetic constructor •() → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.outline.expect
index 44e4b15..a300d04 100644
--- a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.expect
index 1bbff9a..023e6058 100644
--- a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.transformed.expect
index 1bbff9a..023e6058 100644
--- a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* dynamic;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.outline.expect
index 3c7dca2..da8f309 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (dynamic) →* void> extends core::Object {
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (core::Null?) →* void> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*, self::B::U*>*
     ;
   operator +(dynamic other) → self::B<self::B::T*, (self::B::T*) →* void>*
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.expect
index 2eba38e..873a975 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (dynamic) →* void> extends core::Object {
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (core::Null?) →* void> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*, self::B::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
index 2eba38e..873a975 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
-class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (dynamic) →* void> extends core::Object {
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+class B<T extends core::Object* = dynamic, U extends (self::B::T*) →* void = (core::Null?) →* void> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*, self::B::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.outline.expect
index 49528d6..e778017 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect
index 4a65ddd..26a02ad 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
@@ -29,7 +29,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
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 4a65ddd..26a02ad 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
@@ -29,7 +29,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.outline.expect
index cc2df81..f87990c 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     ;
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 53d1c58..41e53d1 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
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 53d1c58..41e53d1 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
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class B<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::B<self::B::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.outline.expect
index 2a81a13..bf7f7d00 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.expect
index d4e90dc..a351f22 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.transformed.expect
index d4e90dc..a351f22 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef F<T extends core::Object* = dynamic> = (T*) →* void;
+typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   synthetic constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
index 45e4a38..f26c179 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
@@ -2,16 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The field 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden setter, 'I.y'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:51:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Context: The field 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden setter, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 //   int y;
 //       ^
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:43:12: Context: This is the overridden method ('y').
 //   void set y(covariant Object value);
 //            ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:51:7: Context: Override was introduced in the mixin application class 'C'.
-// class C = B with M implements I<int>;
-//       ^
 //
 import self as self;
 import "dart:core" as core;
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 9587cd5..5c70f1e 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
@@ -2,16 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The field 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden setter, 'I.y'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:51:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Context: The field 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden setter, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 //   int y;
 //       ^
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:43:12: Context: This is the overridden method ('y').
 //   void set y(covariant Object value);
 //            ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:51:7: Context: Override was introduced in the mixin application class 'C'.
-// class C = B with M implements I<int>;
-//       ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
index e7cad7c..f230923 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
@@ -2,7 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:58:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Context: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 // Change to a supertype of 'Object', or, for a covariant parameter, a subtype.
 //   void set y(int value) {
@@ -10,9 +13,6 @@
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:43:12: Context: This is the overridden method ('y').
 //   void set y(covariant Object value);
 //            ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:58:7: Context: Override was introduced in the mixin application class 'C'.
-// class C = B with M implements I<int>;
-//       ^
 //
 import self as self;
 import "dart:core" as core;
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 067ee48..96c8e8b 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
@@ -2,7 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:58:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Context: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 // Change to a supertype of 'Object', or, for a covariant parameter, a subtype.
 //   void set y(int value) {
@@ -10,9 +13,6 @@
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:43:12: Context: This is the overridden method ('y').
 //   void set y(covariant Object value);
 //            ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:58:7: Context: Override was introduced in the mixin application class 'C'.
-// class C = B with M implements I<int>;
-//       ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index c52e649..91148be 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -28,6 +28,8 @@
 general/error_locations/error_location_01: RuntimeError
 general/error_locations/error_location_02: RuntimeError
 general/error_locations/error_location_03: RuntimeError
+general/error_locations/error_location_05: RuntimeError
+general/error_locations/error_location_06: RuntimeError
 general/expressions: RuntimeError
 general/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
 general/fallthrough: ExpectationFileMismatch
@@ -92,7 +94,6 @@
 inference/mixin_inference_unification_1: TypeCheckError
 inference/mixin_inference_unification_2: TypeCheckError
 inference/override_equals: RuntimeError
-inference/unresolved_super: TypeCheckError
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: InstrumentationMismatch # Issue #25824
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: InstrumentationMismatch # Issue #25824
 inference_new/dependency_only_if_overloaded: TypeCheckError
@@ -146,8 +147,8 @@
 rasta/super_initializer: RuntimeError
 rasta/super_mixin: TypeCheckError
 rasta/super_operator: TypeCheckError
-rasta/type_literals: Crash
-rasta/typedef: Crash
+rasta/type_literals: RuntimeError
+rasta/typedef: RuntimeError
 rasta/unresolved: RuntimeError
 rasta/unresolved_constructor: RuntimeError
 rasta/unresolved_for_in: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 8d0e382..95610cc 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,19 +6,29 @@
 # the round trip for Kernel textual serialization where the initial binary
 # Kernel files are produced by compiling Dart code via Fasta.
 
+all_variances: TextSerializationFailure
 expression/eval: TextSerializationFailure # Was: Pass
 expression/main: TextSerializationFailure # Was: Pass
+extensions/annotations: TextSerializationFailure
 extensions/compounds: TextSerializationFailure
+extensions/conflicts: TextSerializationFailure
+extensions/default_values: TextSerializationFailure
 extensions/direct_instance_access: TextSerializationFailure
 extensions/direct_static_access: TextSerializationFailure
+extensions/dynamic_invoke: TextSerializationFailure
 extensions/explicit_extension_access: TextSerializationFailure
 extensions/explicit_extension_inference: TextSerializationFailure
 extensions/explicit_generic_extension_access: TextSerializationFailure
+extensions/explicit_invalid_access: TextSerializationFailure
 extensions/explicit_this: TextSerializationFailure
 extensions/extension_methods: TextSerializationFailure
+extensions/extension_setter: TextSerializationFailure
+extensions/getter_setter_conflict: TextSerializationFailure
+extensions/if_null: TextSerializationFailure
 extensions/implicit_extension_inference: TextSerializationFailure
 extensions/implicit_this: TextSerializationFailure
 extensions/index: TextSerializationFailure
+extensions/internal_resolution: TextSerializationFailure
 extensions/instance_access: TextSerializationFailure
 extensions/instance_access_of_static: TextSerializationFailure
 extensions/instance_members: TextSerializationFailure
@@ -26,6 +36,7 @@
 extensions/invalid_explicit_access: TextSerializationFailure
 extensions/nested_on_types: TextSerializationFailure
 extensions/null_aware: TextSerializationFailure
+extensions/on_function_type: TextSerializationFailure
 extensions/on_type_inference: TextSerializationFailure
 extensions/on_type_variable_inference: TextSerializationFailure
 extensions/operators: TextSerializationFailure
@@ -35,10 +46,7 @@
 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
-general/error_locations/error_location_03: TextSerializationFailure
-general/error_locations/error_location_04: TextSerializationFailure
+general/DeltaBlue: TextSerializationFailure # Was: Pass
 general/abstract_members: TypeCheckError
 general/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
 general/accessors: TextSerializationFailure # Was: RuntimeError
@@ -112,7 +120,6 @@
 general/default_values: TextSerializationFailure # Was: Pass
 general/deferred_lib: TextSerializationFailure # Was: Pass
 general/deferred_type_annotation: TextSerializationFailure # Was: Pass
-general/DeltaBlue: TextSerializationFailure # Was: Pass
 general/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
 general/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
 general/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
@@ -122,6 +129,12 @@
 general/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
 general/duplicated_named_args_3: TextSerializationFailure # Was: Pass
 general/dynamic_and_void: InstrumentationMismatch # Test assumes Dart 1.0 semantics
+general/error_locations/error_location_01: TextSerializationFailure
+general/error_locations/error_location_02: TextSerializationFailure
+general/error_locations/error_location_03: TextSerializationFailure
+general/error_locations/error_location_04: TextSerializationFailure
+general/error_locations/error_location_05: TextSerializationFailure
+general/error_locations/error_location_06: TextSerializationFailure
 general/escape: TextSerializationFailure # Was: Pass
 general/export_main: TextSerializationFailure # Was: Pass
 general/export_test: TextSerializationFailure # Was: Pass
@@ -194,6 +207,7 @@
 general/non_covariant_checks: TextSerializationFailure
 general/null_aware: TextSerializationFailure # Was: Pass
 general/null_aware_for_in: TextSerializationFailure
+general/null_aware_postfix: TextSerializationFailure
 general/operator_method_not_found: TextSerializationFailure
 general/operators: TextSerializationFailure # Was: Pass
 general/optional: TypeCheckError
@@ -254,9 +268,9 @@
 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_bound_access: TypeCheckError
 general/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
 general/type_variable_uses: TextSerializationFailure # Was: Pass
 general/typedef: TextSerializationFailure # Was: Pass
@@ -681,7 +695,7 @@
 inference/type_promotion_stopped_by_access_in_a_closure: TextSerializationFailure # Was: Pass
 inference/type_promotion_stopped_by_assignment_in_scope: TextSerializationFailure # Was: Pass
 inference/type_promotion_stopped_by_mutation_in_a_closure: TextSerializationFailure # Was: Pass
-inference/unresolved_super: TypeCheckError
+inference/unresolved_super: TextSerializationFailure
 inference/unsafe_block_closure_inference_closure_call: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_constructor_call_explicit_type_param: TextSerializationFailure # Was: Pass
@@ -835,11 +849,14 @@
 instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
+nested_variance_test: TextSerializationFailure
 new_const_insertion/simple: TextSerializationFailure # Was: Pass
 nnbd/function_types: TextSerializationFailure
 nnbd/late: TextSerializationFailure
+nnbd/null_check: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
 nnbd/required: TextSerializationFailure
+nnbd/type_parameter_types: TextSerializationFailure
 no_such_method_forwarders/abstract_accessors_from_field: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_accessors_from_field_one_defined: TextSerializationFailure # Was: Pass
@@ -939,9 +956,9 @@
 rasta/switch_fall_through: TextSerializationFailure # Was: Pass
 rasta/this_invoke: TextSerializationFailure # Was: Pass
 rasta/try_label: TextSerializationFailure
-rasta/type_literals: Crash
+rasta/type_literals: TextSerializationFailure
 rasta/type_with_parse_error: TextSerializationFailure # Was: Pass
-rasta/typedef: Crash
+rasta/typedef: TextSerializationFailure
 rasta/unresolved: TextSerializationFailure # Was: RuntimeError
 rasta/unresolved_constructor: TextSerializationFailure # Was: RuntimeError
 rasta/unresolved_for_in: TextSerializationFailure # Was: RuntimeError
@@ -1089,10 +1106,11 @@
 runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
 runtime_checks_new/stub_checked_via_target: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_contravariant_from_class: TextSerializationFailure # Was: Pass
-runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
-runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_class: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_interface: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_super: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantInterface_from_class: TextSerializationFailure # Was: Pass
+runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
+runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
 set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
+top_level_variance_test: TextSerializationFailure
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart b/pkg/front_end/testcases/top_level_variance_test.dart
new file mode 100644
index 0000000..ff36737
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Testing that instantiate-to-bound and super-bounded types take the
+// variance of formal type parameters into account when a type alias is
+// used as a raw type.
+
+// Standard type comparison support.
+
+typedef F<X> = void Function<Y extends X>();
+F<X> toF<X>(X x) => null;
+
+// Material specific to this test.
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+
+class A<X> {}
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+
+class B<X> {}
+
+void testTopLevel() {
+  // I2b initial value for a covariant type parameter w/o bound: dynamic.
+  Fcov source1;
+  var fsource1 = toF(source1);
+  F<Fcov<dynamic>> target1 = fsource1;
+
+  // I2b initial value for a contravariant type parameter w/o bound: dynamic.
+  Fcon source2;
+  var fsource2 = toF(source2);
+  F<Fcon<dynamic>> target2 = fsource2;
+
+  // I2b initial value for an invariant type parameter w/o bound: dynamic.
+  Finv source3;
+  var fsource3 = toF(source3);
+  F<Finv<dynamic>> target3 = fsource3;
+
+  // I2b initial value for a covariant type parameter: bound.
+  FcovBound source4;
+  var fsource4 = toF(source4);
+  F<FcovBound<num>> target4 = fsource4;
+
+  // I2b initial value for a contravariant type parameter: bound.
+  FconBound source5;
+  var fsource5 = toF(source5);
+  F<FconBound<num>> target5 = fsource5;
+
+  // I2b initial value for an invariant type parameter: bound.
+  FinvBound source6;
+  var fsource6 = toF(source6);
+  F<FinvBound<num>> target6 = fsource6;
+
+  // I2b for a covariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing covariant occurrence by `dynamic`. Resulting type
+  // is super-bounded: FcovCyclicBound<A<Null>> is regular-bounded.
+  FcovCyclicBound source7;
+  var fsource7 = toF(source7);
+  F<FcovCyclicBound<A<dynamic>>> target7 = fsource7;
+
+  // I2b for a contravariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing contravariant occurrence by `Null`. Resulting type
+  // is super-bounded: FconCyclicBound<A<Object>> is regular-bounded.
+  FconCyclicBound source8;
+  var fsource8 = toF(source8);
+  F<FconCyclicBound<A<Null>>> target8 = fsource8;
+
+  // I2b for an invariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing invariant occurrence by `dynamic`. Resulting type is
+  // _not_ super-bounded: FinvCyclicBound<A<dynamic>> not regular-bounded.
+  FinvCyclicBound source9; //# 01: compile-time error
+  // var fsource9 = toF(source9);
+  // F<FinvCyclicBound<A<dynamic>>> target9 = fsource9;
+
+  // I2b for a covariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing contravariant occurrence by `Null`. Resulting type
+  // is super-bounded: FcovCyclicBound<Function(Object)> is regular-bounded.
+  FcovCyclicCoBound source10;
+  var fsource10 = toF(source10);
+  F<FcovCyclicCoBound<Function(Null)>> target10 = fsource10;
+
+  // I2b for a contravariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing covariant occurrence by `dynamic`. Resulting type
+  // FconCyclicCoBound<Function(dynamic)> is regular-bounded.
+  FconCyclicCoBound source11;
+  var fsource11 = toF(source11);
+  F<FconCyclicCoBound<Function(dynamic)>> target11 = fsource11;
+
+  // I2b for an invariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing invariant occurrence by `dynamic`. Resulting type
+  // F<FinvCyclicCoBound<Function(dynamic)>> is regular-bounded.
+  FinvCyclicCoBound source12;
+  var fsource12 = toF(source12);
+  F<FinvCyclicCoBound<Function(dynamic)>> target12 = fsource12;
+}
+
+void testNested() {
+  // Everything gets the same treatment when the cases from
+  // `testTopLevel` are duplicated at the nested level.
+
+  B<Fcov> source1;
+  var fsource1 = toF(source1);
+  F<B<Fcov<dynamic>>> target1 = fsource1;
+
+  B<Fcon> source2;
+  var fsource2 = toF(source2);
+  F<B<Fcon<dynamic>>> target2 = fsource2;
+
+  B<Finv> source3;
+  var fsource3 = toF(source3);
+  F<B<Finv<dynamic>>> target3 = fsource3;
+
+  B<FcovBound> source4;
+  var fsource4 = toF(source4);
+  F<B<FcovBound<num>>> target4 = fsource4;
+
+  B<FconBound> source5;
+  var fsource5 = toF(source5);
+  F<B<FconBound<num>>> target5 = fsource5;
+
+  B<FinvBound> source6;
+  var fsource6 = toF(source6);
+  F<B<FinvBound<num>>> target6 = fsource6;
+
+  B<FcovCyclicBound> source7;
+  var fsource7 = toF(source7);
+  F<B<FcovCyclicBound<A<dynamic>>>> target7 = fsource7;
+
+  B<FconCyclicBound> source8;
+  var fsource8 = toF(source8);
+  F<B<FconCyclicBound<A<Null>>>> target8 = fsource8;
+
+  B<FinvCyclicBound> source9; //# 02: compile-time error
+  // var fsource9 = toF(source9);
+  // F<B<FinvCyclicBound<A<dynamic>>>> target9 = fsource9;
+
+  B<FcovCyclicCoBound> source10;
+  var fsource10 = toF(source10);
+  F<B<FcovCyclicCoBound<Function(Null)>>> target10 = fsource10;
+
+  B<FconCyclicCoBound> source11;
+  var fsource11 = toF(source11);
+  F<B<FconCyclicCoBound<Function(dynamic)>>> target11 = fsource11;
+
+  B<FinvCyclicCoBound> source12;
+  var fsource12 = toF(source12);
+  F<B<FinvCyclicCoBound<Function(dynamic)>>> target12 = fsource12;
+}
+
+main() {
+  testTopLevel();
+  testNested();
+}
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.hierarchy.expect b/pkg/front_end/testcases/top_level_variance_test.dart.hierarchy.expect
new file mode 100644
index 0000000..523e0f4
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.hierarchy.expect
@@ -0,0 +1,53 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.legacy.expect b/pkg/front_end/testcases/top_level_variance_test.dart.legacy.expect
new file mode 100644
index 0000000..32ef6e6
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.legacy.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object = dynamic> = <Y extends X = dynamic>() → void;
+typedef Fcov<X extends core::Object = dynamic> = () → X;
+typedef Fcon<contravariant X extends core::Object = dynamic> = (X) → dynamic;
+typedef Finv<invariant X extends core::Object = dynamic> = (X) → X;
+typedef FcovBound<X extends core::num = dynamic> = () → X;
+typedef FconBound<contravariant X extends core::num = dynamic> = (X) → dynamic;
+typedef FinvBound<invariant X extends core::num = dynamic> = (X) → X;
+typedef FcovCyclicBound<X extends self::A<X> = dynamic> = () → X;
+typedef FconCyclicBound<contravariant X extends self::A<X> = dynamic> = (X) → dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X> = dynamic> = (X) → X;
+typedef FcovCyclicCoBound<X extends (X) → dynamic = dynamic> = () → X;
+typedef FconCyclicCoBound<contravariant X extends (X) → dynamic = dynamic> = (X) → dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X) → dynamic = dynamic> = (X) → X;
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object = dynamic>(self::toF::X x) → <Y extends self::toF::X = dynamic>() → void
+  return null;
+static method testTopLevel() → void {
+  () → dynamic source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends () → dynamic = dynamic>() → void target1 = fsource1;
+  (dynamic) → dynamic source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends (dynamic) → dynamic = dynamic>() → void target2 = fsource2;
+  (dynamic) → dynamic source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends (dynamic) → dynamic = dynamic>() → void target3 = fsource3;
+  () → dynamic source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends () → core::num = dynamic>() → void target4 = fsource4;
+  (dynamic) → dynamic source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends (core::num) → dynamic = dynamic>() → void target5 = fsource5;
+  (dynamic) → dynamic source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends (core::num) → core::num = dynamic>() → void target6 = fsource6;
+  () → dynamic source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends () → self::A<dynamic> = dynamic>() → void target7 = fsource7;
+  (dynamic) → dynamic source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends (self::A<core::Null>) → dynamic = dynamic>() → void target8 = fsource8;
+  (dynamic) → dynamic source9;
+  () → dynamic source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends () → (core::Null) → dynamic = dynamic>() → void target10 = fsource10;
+  (dynamic) → dynamic source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends ((dynamic) → dynamic) → dynamic = dynamic>() → void target11 = fsource11;
+  (dynamic) → dynamic source12;
+  dynamic fsource12 = self::toF<dynamic>(source12);
+  <Y extends ((dynamic) → dynamic) → (dynamic) → dynamic = dynamic>() → void target12 = fsource12;
+}
+static method testNested() → void {
+  self::B<() → dynamic> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::B<() → dynamic> = dynamic>() → void target1 = fsource1;
+  self::B<(dynamic) → dynamic> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::B<(dynamic) → dynamic> = dynamic>() → void target2 = fsource2;
+  self::B<(dynamic) → dynamic> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::B<(dynamic) → dynamic> = dynamic>() → void target3 = fsource3;
+  self::B<() → dynamic> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::B<() → core::num> = dynamic>() → void target4 = fsource4;
+  self::B<(dynamic) → dynamic> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::B<(core::num) → dynamic> = dynamic>() → void target5 = fsource5;
+  self::B<(dynamic) → dynamic> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::B<(core::num) → core::num> = dynamic>() → void target6 = fsource6;
+  self::B<() → dynamic> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::B<() → self::A<dynamic>> = dynamic>() → void target7 = fsource7;
+  self::B<(dynamic) → dynamic> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::B<(self::A<core::Null>) → dynamic> = dynamic>() → void target8 = fsource8;
+  self::B<(dynamic) → dynamic> source9;
+  self::B<() → dynamic> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::B<() → (core::Null) → dynamic> = dynamic>() → void target10 = fsource10;
+  self::B<(dynamic) → dynamic> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::B<((dynamic) → dynamic) → dynamic> = dynamic>() → void target11 = fsource11;
+  self::B<(dynamic) → dynamic> source12;
+  dynamic fsource12 = self::toF<dynamic>(source12);
+  <Y extends self::B<((dynamic) → dynamic) → (dynamic) → dynamic> = dynamic>() → void target12 = fsource12;
+}
+static method main() → dynamic {
+  self::testTopLevel();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.legacy.transformed.expect b/pkg/front_end/testcases/top_level_variance_test.dart.legacy.transformed.expect
new file mode 100644
index 0000000..32ef6e6
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.legacy.transformed.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object = dynamic> = <Y extends X = dynamic>() → void;
+typedef Fcov<X extends core::Object = dynamic> = () → X;
+typedef Fcon<contravariant X extends core::Object = dynamic> = (X) → dynamic;
+typedef Finv<invariant X extends core::Object = dynamic> = (X) → X;
+typedef FcovBound<X extends core::num = dynamic> = () → X;
+typedef FconBound<contravariant X extends core::num = dynamic> = (X) → dynamic;
+typedef FinvBound<invariant X extends core::num = dynamic> = (X) → X;
+typedef FcovCyclicBound<X extends self::A<X> = dynamic> = () → X;
+typedef FconCyclicBound<contravariant X extends self::A<X> = dynamic> = (X) → dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X> = dynamic> = (X) → X;
+typedef FcovCyclicCoBound<X extends (X) → dynamic = dynamic> = () → X;
+typedef FconCyclicCoBound<contravariant X extends (X) → dynamic = dynamic> = (X) → dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X) → dynamic = dynamic> = (X) → X;
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object = dynamic>(self::toF::X x) → <Y extends self::toF::X = dynamic>() → void
+  return null;
+static method testTopLevel() → void {
+  () → dynamic source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends () → dynamic = dynamic>() → void target1 = fsource1;
+  (dynamic) → dynamic source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends (dynamic) → dynamic = dynamic>() → void target2 = fsource2;
+  (dynamic) → dynamic source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends (dynamic) → dynamic = dynamic>() → void target3 = fsource3;
+  () → dynamic source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends () → core::num = dynamic>() → void target4 = fsource4;
+  (dynamic) → dynamic source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends (core::num) → dynamic = dynamic>() → void target5 = fsource5;
+  (dynamic) → dynamic source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends (core::num) → core::num = dynamic>() → void target6 = fsource6;
+  () → dynamic source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends () → self::A<dynamic> = dynamic>() → void target7 = fsource7;
+  (dynamic) → dynamic source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends (self::A<core::Null>) → dynamic = dynamic>() → void target8 = fsource8;
+  (dynamic) → dynamic source9;
+  () → dynamic source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends () → (core::Null) → dynamic = dynamic>() → void target10 = fsource10;
+  (dynamic) → dynamic source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends ((dynamic) → dynamic) → dynamic = dynamic>() → void target11 = fsource11;
+  (dynamic) → dynamic source12;
+  dynamic fsource12 = self::toF<dynamic>(source12);
+  <Y extends ((dynamic) → dynamic) → (dynamic) → dynamic = dynamic>() → void target12 = fsource12;
+}
+static method testNested() → void {
+  self::B<() → dynamic> source1;
+  dynamic fsource1 = self::toF<dynamic>(source1);
+  <Y extends self::B<() → dynamic> = dynamic>() → void target1 = fsource1;
+  self::B<(dynamic) → dynamic> source2;
+  dynamic fsource2 = self::toF<dynamic>(source2);
+  <Y extends self::B<(dynamic) → dynamic> = dynamic>() → void target2 = fsource2;
+  self::B<(dynamic) → dynamic> source3;
+  dynamic fsource3 = self::toF<dynamic>(source3);
+  <Y extends self::B<(dynamic) → dynamic> = dynamic>() → void target3 = fsource3;
+  self::B<() → dynamic> source4;
+  dynamic fsource4 = self::toF<dynamic>(source4);
+  <Y extends self::B<() → core::num> = dynamic>() → void target4 = fsource4;
+  self::B<(dynamic) → dynamic> source5;
+  dynamic fsource5 = self::toF<dynamic>(source5);
+  <Y extends self::B<(core::num) → dynamic> = dynamic>() → void target5 = fsource5;
+  self::B<(dynamic) → dynamic> source6;
+  dynamic fsource6 = self::toF<dynamic>(source6);
+  <Y extends self::B<(core::num) → core::num> = dynamic>() → void target6 = fsource6;
+  self::B<() → dynamic> source7;
+  dynamic fsource7 = self::toF<dynamic>(source7);
+  <Y extends self::B<() → self::A<dynamic>> = dynamic>() → void target7 = fsource7;
+  self::B<(dynamic) → dynamic> source8;
+  dynamic fsource8 = self::toF<dynamic>(source8);
+  <Y extends self::B<(self::A<core::Null>) → dynamic> = dynamic>() → void target8 = fsource8;
+  self::B<(dynamic) → dynamic> source9;
+  self::B<() → dynamic> source10;
+  dynamic fsource10 = self::toF<dynamic>(source10);
+  <Y extends self::B<() → (core::Null) → dynamic> = dynamic>() → void target10 = fsource10;
+  self::B<(dynamic) → dynamic> source11;
+  dynamic fsource11 = self::toF<dynamic>(source11);
+  <Y extends self::B<((dynamic) → dynamic) → dynamic> = dynamic>() → void target11 = fsource11;
+  self::B<(dynamic) → dynamic> source12;
+  dynamic fsource12 = self::toF<dynamic>(source12);
+  <Y extends self::B<((dynamic) → dynamic) → (dynamic) → dynamic> = dynamic>() → void target12 = fsource12;
+}
+static method main() → dynamic {
+  self::testTopLevel();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.outline.expect b/pkg/front_end/testcases/top_level_variance_test.dart.outline.expect
new file mode 100644
index 0000000..e6c10ea
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.outline.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  ;
+static method testTopLevel() → void
+  ;
+static method testNested() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.strong.expect b/pkg/front_end/testcases/top_level_variance_test.dart.strong.expect
new file mode 100644
index 0000000..28ca428
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.strong.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  return null;
+static method testTopLevel() → void {
+  () →* dynamic source1;
+  <Y extends () →* dynamic = dynamic>() →* void fsource1 = self::toF<() →* dynamic>(source1);
+  <Y extends () →* dynamic = dynamic>() →* void target1 = fsource1;
+  (dynamic) →* dynamic source2;
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void fsource2 = self::toF<(dynamic) →* dynamic>(source2);
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void target2 = fsource2;
+  (dynamic) →* dynamic source3;
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void fsource3 = self::toF<(dynamic) →* dynamic>(source3);
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void target3 = fsource3;
+  () →* core::num* source4;
+  <Y extends () →* core::num* = dynamic>() →* void fsource4 = self::toF<() →* core::num*>(source4);
+  <Y extends () →* core::num* = dynamic>() →* void target4 = fsource4;
+  (core::num*) →* dynamic source5;
+  <Y extends (core::num*) →* dynamic = dynamic>() →* void fsource5 = self::toF<(core::num*) →* dynamic>(source5);
+  <Y extends (core::num*) →* dynamic = dynamic>() →* void target5 = fsource5;
+  (core::num*) →* core::num* source6;
+  <Y extends (core::num*) →* core::num* = dynamic>() →* void fsource6 = self::toF<(core::num*) →* core::num*>(source6);
+  <Y extends (core::num*) →* core::num* = dynamic>() →* void target6 = fsource6;
+  () →* self::A<dynamic>* source7;
+  <Y extends () →* self::A<dynamic>* = dynamic>() →* void fsource7 = self::toF<() →* self::A<dynamic>*>(source7);
+  <Y extends () →* self::A<dynamic>* = dynamic>() →* void target7 = fsource7;
+  (self::A<core::Null?>*) →* dynamic source8;
+  <Y extends (self::A<core::Null?>*) →* dynamic = dynamic>() →* void fsource8 = self::toF<(self::A<core::Null?>*) →* dynamic>(source8);
+  <Y extends (self::A<core::Null*>*) →* dynamic = dynamic>() →* void target8 = fsource8;
+  (self::A<dynamic>*) →* self::A<dynamic>* source9;
+  () →* (core::Null?) →* dynamic source10;
+  <Y extends () →* (core::Null?) →* dynamic = dynamic>() →* void fsource10 = self::toF<() →* (core::Null?) →* dynamic>(source10);
+  <Y extends () →* (core::Null*) →* dynamic = dynamic>() →* void target10 = fsource10;
+  ((dynamic) →* dynamic) →* dynamic source11;
+  <Y extends ((dynamic) →* dynamic) →* dynamic = dynamic>() →* void fsource11 = self::toF<((dynamic) →* dynamic) →* dynamic>(source11);
+  <Y extends ((dynamic) →* dynamic) →* dynamic = dynamic>() →* void target11 = fsource11;
+  ((dynamic) →* dynamic) →* (dynamic) →* dynamic source12;
+  <Y extends ((dynamic) →* dynamic) →* (dynamic) →* dynamic = dynamic>() →* void fsource12 = self::toF<((dynamic) →* dynamic) →* (dynamic) →* dynamic>(source12);
+  <Y extends ((dynamic) →* dynamic) →* (dynamic) →* dynamic = dynamic>() →* void target12 = fsource12;
+}
+static method testNested() → void {
+  self::B<() →* dynamic>* source1;
+  <Y extends self::B<() →* dynamic>* = dynamic>() →* void fsource1 = self::toF<self::B<() →* dynamic>*>(source1);
+  <Y extends self::B<() →* dynamic>* = dynamic>() →* void target1 = fsource1;
+  self::B<(dynamic) →* dynamic>* source2;
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void fsource2 = self::toF<self::B<(dynamic) →* dynamic>*>(source2);
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void target2 = fsource2;
+  self::B<(dynamic) →* dynamic>* source3;
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void fsource3 = self::toF<self::B<(dynamic) →* dynamic>*>(source3);
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void target3 = fsource3;
+  self::B<() →* core::num*>* source4;
+  <Y extends self::B<() →* core::num*>* = dynamic>() →* void fsource4 = self::toF<self::B<() →* core::num*>*>(source4);
+  <Y extends self::B<() →* core::num*>* = dynamic>() →* void target4 = fsource4;
+  self::B<(core::num*) →* dynamic>* source5;
+  <Y extends self::B<(core::num*) →* dynamic>* = dynamic>() →* void fsource5 = self::toF<self::B<(core::num*) →* dynamic>*>(source5);
+  <Y extends self::B<(core::num*) →* dynamic>* = dynamic>() →* void target5 = fsource5;
+  self::B<(core::num*) →* core::num*>* source6;
+  <Y extends self::B<(core::num*) →* core::num*>* = dynamic>() →* void fsource6 = self::toF<self::B<(core::num*) →* core::num*>*>(source6);
+  <Y extends self::B<(core::num*) →* core::num*>* = dynamic>() →* void target6 = fsource6;
+  self::B<() →* self::A<dynamic>*>* source7;
+  <Y extends self::B<() →* self::A<dynamic>*>* = dynamic>() →* void fsource7 = self::toF<self::B<() →* self::A<dynamic>*>*>(source7);
+  <Y extends self::B<() →* self::A<dynamic>*>* = dynamic>() →* void target7 = fsource7;
+  self::B<(self::A<core::Null?>*) →* dynamic>* source8;
+  <Y extends self::B<(self::A<core::Null?>*) →* dynamic>* = dynamic>() →* void fsource8 = self::toF<self::B<(self::A<core::Null?>*) →* dynamic>*>(source8);
+  <Y extends self::B<(self::A<core::Null*>*) →* dynamic>* = dynamic>() →* void target8 = fsource8;
+  self::B<(self::A<dynamic>*) →* self::A<dynamic>*>* source9;
+  self::B<() →* (core::Null?) →* dynamic>* source10;
+  <Y extends self::B<() →* (core::Null?) →* dynamic>* = dynamic>() →* void fsource10 = self::toF<self::B<() →* (core::Null?) →* dynamic>*>(source10);
+  <Y extends self::B<() →* (core::Null*) →* dynamic>* = dynamic>() →* void target10 = fsource10;
+  self::B<((dynamic) →* dynamic) →* dynamic>* source11;
+  <Y extends self::B<((dynamic) →* dynamic) →* dynamic>* = dynamic>() →* void fsource11 = self::toF<self::B<((dynamic) →* dynamic) →* dynamic>*>(source11);
+  <Y extends self::B<((dynamic) →* dynamic) →* dynamic>* = dynamic>() →* void target11 = fsource11;
+  self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* source12;
+  <Y extends self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* = dynamic>() →* void fsource12 = self::toF<self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>*>(source12);
+  <Y extends self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* = dynamic>() →* void target12 = fsource12;
+}
+static method main() → dynamic {
+  self::testTopLevel();
+  self::testNested();
+}
diff --git a/pkg/front_end/testcases/top_level_variance_test.dart.strong.transformed.expect b/pkg/front_end/testcases/top_level_variance_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..28ca428
--- /dev/null
+++ b/pkg/front_end/testcases/top_level_variance_test.dart.strong.transformed.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<invariant X extends core::Object* = dynamic> = <Y extends X* = dynamic>() →* void;
+typedef Fcov<X extends core::Object* = dynamic> = () →* X*;
+typedef Fcon<contravariant X extends core::Object* = dynamic> = (X*) →* dynamic;
+typedef Finv<invariant X extends core::Object* = dynamic> = (X*) →* X*;
+typedef FcovBound<X extends core::num* = core::num*> = () →* X*;
+typedef FconBound<contravariant X extends core::num* = core::num*> = (X*) →* dynamic;
+typedef FinvBound<invariant X extends core::num* = core::num*> = (X*) →* X*;
+typedef FcovCyclicBound<X extends self::A<X*>* = self::A<dynamic>*> = () →* X*;
+typedef FconCyclicBound<contravariant X extends self::A<X*>* = self::A<core::Null?>*> = (X*) →* dynamic;
+typedef FinvCyclicBound<invariant X extends self::A<X*>* = self::A<dynamic>*> = (X*) →* X*;
+typedef FcovCyclicCoBound<X extends (X*) →* dynamic = (core::Null?) →* dynamic> = () →* X*;
+typedef FconCyclicCoBound<contravariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* dynamic;
+typedef FinvCyclicCoBound<invariant X extends (X*) →* dynamic = (dynamic) →* dynamic> = (X*) →* X*;
+class A<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super core::Object::•()
+    ;
+}
+static method toF<X extends core::Object* = dynamic>(self::toF::X* x) → <Y extends self::toF::X* = dynamic>() →* void
+  return null;
+static method testTopLevel() → void {
+  () →* dynamic source1;
+  <Y extends () →* dynamic = dynamic>() →* void fsource1 = self::toF<() →* dynamic>(source1);
+  <Y extends () →* dynamic = dynamic>() →* void target1 = fsource1;
+  (dynamic) →* dynamic source2;
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void fsource2 = self::toF<(dynamic) →* dynamic>(source2);
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void target2 = fsource2;
+  (dynamic) →* dynamic source3;
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void fsource3 = self::toF<(dynamic) →* dynamic>(source3);
+  <Y extends (dynamic) →* dynamic = dynamic>() →* void target3 = fsource3;
+  () →* core::num* source4;
+  <Y extends () →* core::num* = dynamic>() →* void fsource4 = self::toF<() →* core::num*>(source4);
+  <Y extends () →* core::num* = dynamic>() →* void target4 = fsource4;
+  (core::num*) →* dynamic source5;
+  <Y extends (core::num*) →* dynamic = dynamic>() →* void fsource5 = self::toF<(core::num*) →* dynamic>(source5);
+  <Y extends (core::num*) →* dynamic = dynamic>() →* void target5 = fsource5;
+  (core::num*) →* core::num* source6;
+  <Y extends (core::num*) →* core::num* = dynamic>() →* void fsource6 = self::toF<(core::num*) →* core::num*>(source6);
+  <Y extends (core::num*) →* core::num* = dynamic>() →* void target6 = fsource6;
+  () →* self::A<dynamic>* source7;
+  <Y extends () →* self::A<dynamic>* = dynamic>() →* void fsource7 = self::toF<() →* self::A<dynamic>*>(source7);
+  <Y extends () →* self::A<dynamic>* = dynamic>() →* void target7 = fsource7;
+  (self::A<core::Null?>*) →* dynamic source8;
+  <Y extends (self::A<core::Null?>*) →* dynamic = dynamic>() →* void fsource8 = self::toF<(self::A<core::Null?>*) →* dynamic>(source8);
+  <Y extends (self::A<core::Null*>*) →* dynamic = dynamic>() →* void target8 = fsource8;
+  (self::A<dynamic>*) →* self::A<dynamic>* source9;
+  () →* (core::Null?) →* dynamic source10;
+  <Y extends () →* (core::Null?) →* dynamic = dynamic>() →* void fsource10 = self::toF<() →* (core::Null?) →* dynamic>(source10);
+  <Y extends () →* (core::Null*) →* dynamic = dynamic>() →* void target10 = fsource10;
+  ((dynamic) →* dynamic) →* dynamic source11;
+  <Y extends ((dynamic) →* dynamic) →* dynamic = dynamic>() →* void fsource11 = self::toF<((dynamic) →* dynamic) →* dynamic>(source11);
+  <Y extends ((dynamic) →* dynamic) →* dynamic = dynamic>() →* void target11 = fsource11;
+  ((dynamic) →* dynamic) →* (dynamic) →* dynamic source12;
+  <Y extends ((dynamic) →* dynamic) →* (dynamic) →* dynamic = dynamic>() →* void fsource12 = self::toF<((dynamic) →* dynamic) →* (dynamic) →* dynamic>(source12);
+  <Y extends ((dynamic) →* dynamic) →* (dynamic) →* dynamic = dynamic>() →* void target12 = fsource12;
+}
+static method testNested() → void {
+  self::B<() →* dynamic>* source1;
+  <Y extends self::B<() →* dynamic>* = dynamic>() →* void fsource1 = self::toF<self::B<() →* dynamic>*>(source1);
+  <Y extends self::B<() →* dynamic>* = dynamic>() →* void target1 = fsource1;
+  self::B<(dynamic) →* dynamic>* source2;
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void fsource2 = self::toF<self::B<(dynamic) →* dynamic>*>(source2);
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void target2 = fsource2;
+  self::B<(dynamic) →* dynamic>* source3;
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void fsource3 = self::toF<self::B<(dynamic) →* dynamic>*>(source3);
+  <Y extends self::B<(dynamic) →* dynamic>* = dynamic>() →* void target3 = fsource3;
+  self::B<() →* core::num*>* source4;
+  <Y extends self::B<() →* core::num*>* = dynamic>() →* void fsource4 = self::toF<self::B<() →* core::num*>*>(source4);
+  <Y extends self::B<() →* core::num*>* = dynamic>() →* void target4 = fsource4;
+  self::B<(core::num*) →* dynamic>* source5;
+  <Y extends self::B<(core::num*) →* dynamic>* = dynamic>() →* void fsource5 = self::toF<self::B<(core::num*) →* dynamic>*>(source5);
+  <Y extends self::B<(core::num*) →* dynamic>* = dynamic>() →* void target5 = fsource5;
+  self::B<(core::num*) →* core::num*>* source6;
+  <Y extends self::B<(core::num*) →* core::num*>* = dynamic>() →* void fsource6 = self::toF<self::B<(core::num*) →* core::num*>*>(source6);
+  <Y extends self::B<(core::num*) →* core::num*>* = dynamic>() →* void target6 = fsource6;
+  self::B<() →* self::A<dynamic>*>* source7;
+  <Y extends self::B<() →* self::A<dynamic>*>* = dynamic>() →* void fsource7 = self::toF<self::B<() →* self::A<dynamic>*>*>(source7);
+  <Y extends self::B<() →* self::A<dynamic>*>* = dynamic>() →* void target7 = fsource7;
+  self::B<(self::A<core::Null?>*) →* dynamic>* source8;
+  <Y extends self::B<(self::A<core::Null?>*) →* dynamic>* = dynamic>() →* void fsource8 = self::toF<self::B<(self::A<core::Null?>*) →* dynamic>*>(source8);
+  <Y extends self::B<(self::A<core::Null*>*) →* dynamic>* = dynamic>() →* void target8 = fsource8;
+  self::B<(self::A<dynamic>*) →* self::A<dynamic>*>* source9;
+  self::B<() →* (core::Null?) →* dynamic>* source10;
+  <Y extends self::B<() →* (core::Null?) →* dynamic>* = dynamic>() →* void fsource10 = self::toF<self::B<() →* (core::Null?) →* dynamic>*>(source10);
+  <Y extends self::B<() →* (core::Null*) →* dynamic>* = dynamic>() →* void target10 = fsource10;
+  self::B<((dynamic) →* dynamic) →* dynamic>* source11;
+  <Y extends self::B<((dynamic) →* dynamic) →* dynamic>* = dynamic>() →* void fsource11 = self::toF<self::B<((dynamic) →* dynamic) →* dynamic>*>(source11);
+  <Y extends self::B<((dynamic) →* dynamic) →* dynamic>* = dynamic>() →* void target11 = fsource11;
+  self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* source12;
+  <Y extends self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* = dynamic>() →* void fsource12 = self::toF<self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>*>(source12);
+  <Y extends self::B<((dynamic) →* dynamic) →* (dynamic) →* dynamic>* = dynamic>() →* void target12 = fsource12;
+}
+static method main() → dynamic {
+  self::testTopLevel();
+  self::testNested();
+}
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index f9178e3..4fb21cc 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -18,7 +18,9 @@
 
 import 'package:kernel/type_environment.dart' show SubtypeTester;
 
-import 'package:vm/bytecode/gen_bytecode.dart' show generateBytecode;
+import 'package:vm/bytecode/gen_bytecode.dart'
+    show createFreshComponentWithBytecode, generateBytecode;
+
 import 'package:vm/bytecode/options.dart' show BytecodeOptions;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
@@ -330,16 +332,18 @@
   new File.fromUri(outlineOutput).writeAsBytesSync(result.summary);
   c.options.ticker.logMs("Wrote outline to ${outlineOutput.toFilePath()}");
 
+  Component component = result.component;
   if (c.options.bytecode) {
-    generateBytecode(result.component,
+    generateBytecode(component,
         options: new BytecodeOptions(
             enableAsserts: true,
             emitSourceFiles: true,
             emitSourcePositions: true,
             environmentDefines: c.options.environmentDefines));
+    component = createFreshComponentWithBytecode(component);
   }
 
-  await writeComponentToFile(result.component, fullOutput,
+  await writeComponentToFile(component, fullOutput,
       filter: (lib) => !lib.isExternal);
 
   c.options.ticker.logMs("Wrote component to ${fullOutput.toFilePath()}");
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 337d47d..5152615 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 32;
+  UInt32 formatVersion = 33;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -703,6 +703,12 @@
   Expression operand;
 }
 
+type NullCheck extends Expression {
+  Byte tag = 117;
+  FileOffset fileOffset;
+  Expression operand;
+}
+
 /*
  enum LogicalOperator { &&, || }
 */
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index ae961e9..1f1835c 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2739,9 +2739,9 @@
     // Treat the properties of Object specially.
     String nameString = name.name;
     if (nameString == 'hashCode') {
-      return types.intType;
+      return types.coreTypes.intLegacyRawType;
     } else if (nameString == 'runtimeType') {
-      return types.typeType;
+      return types.coreTypes.typeLegacyRawType;
     }
     return const DynamicType();
   }
@@ -3257,7 +3257,7 @@
     }
     if (name.name == '==') {
       // We use this special case to simplify generation of '==' checks.
-      return types.boolType;
+      return types.coreTypes.boolLegacyRawType;
     }
     return const DynamicType();
   }
@@ -3497,7 +3497,8 @@
     operand?.parent = this;
   }
 
-  DartType getStaticType(TypeEnvironment types) => types.boolType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.boolLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitNot(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) => v.visitNot(this, arg);
@@ -3525,7 +3526,8 @@
     right?.parent = this;
   }
 
-  DartType getStaticType(TypeEnvironment types) => types.boolType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.boolLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitLogicalExpression(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3610,7 +3612,8 @@
     setParents(expressions, this);
   }
 
-  DartType getStaticType(TypeEnvironment types) => types.stringType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.stringLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitStringConcatenation(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3838,7 +3841,8 @@
     operand?.parent = this;
   }
 
-  DartType getStaticType(TypeEnvironment types) => types.boolType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.boolLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitIsExpression(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3901,6 +3905,37 @@
   }
 }
 
+/// Null check expression of form `x!`.
+///
+/// This expression was added as part of NNBD and is currently only created when
+/// the 'non-nullable' experimental feature is enabled.
+class NullCheck extends Expression {
+  Expression operand;
+
+  NullCheck(this.operand) {
+    operand?.parent = this;
+  }
+
+  DartType getStaticType(TypeEnvironment types) =>
+      // TODO(johnniwinther): Return `NonNull(operand.getStaticType(types))`.
+      operand.getStaticType(types);
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitNullCheck(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitNullCheck(this, arg);
+
+  visitChildren(Visitor v) {
+    operand?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (operand != null) {
+      operand = operand.accept<TreeNode>(v);
+      operand?.parent = this;
+    }
+  }
+}
+
 /// An integer, double, boolean, string, or null constant.
 abstract class BasicLiteral extends Expression {
   Object get value;
@@ -3914,7 +3949,8 @@
 
   StringLiteral(this.value);
 
-  DartType getStaticType(TypeEnvironment types) => types.stringType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.stringLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitStringLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3930,7 +3966,8 @@
 
   IntLiteral(this.value);
 
-  DartType getStaticType(TypeEnvironment types) => types.intType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.intLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitIntLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3942,7 +3979,8 @@
 
   DoubleLiteral(this.value);
 
-  DartType getStaticType(TypeEnvironment types) => types.doubleType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.doubleLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitDoubleLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3954,7 +3992,8 @@
 
   BoolLiteral(this.value);
 
-  DartType getStaticType(TypeEnvironment types) => types.boolType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.boolLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitBoolLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3976,7 +4015,8 @@
 
   SymbolLiteral(this.value);
 
-  DartType getStaticType(TypeEnvironment types) => types.symbolType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.symbolLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitSymbolLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3991,7 +4031,8 @@
 
   TypeLiteral(this.type);
 
-  DartType getStaticType(TypeEnvironment types) => types.typeType;
+  DartType getStaticType(TypeEnvironment types) =>
+      types.coreTypes.typeLegacyRawType;
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitTypeLiteral(this);
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4364,7 +4405,7 @@
   CheckLibraryIsLoaded(this.import);
 
   DartType getStaticType(TypeEnvironment types) {
-    return types.objectType;
+    return types.coreTypes.objectLegacyRawType;
   }
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitCheckLibraryIsLoaded(this);
@@ -5580,7 +5621,7 @@
     return new FunctionType(positionalParameters, returnType,
         requiredParameterCount: requiredParameterCount,
         namedParameters: namedParameters,
-        typedefType: typedefType);
+        typedefType: null);
   }
 
   /// Looks up the type of the named parameter with the given name.
@@ -5733,14 +5774,21 @@
 /// A type variable has an optional bound because type promotion can change the
 /// bound.  A bound of `null` indicates that the bound has not been promoted and
 /// is the same as the [TypeParameter]'s bound.  This allows one to detect
-/// whether the bound has been promoted.
+/// whether the bound has been promoted.  The case of promoted bound can be
+/// viewed as representing an intersection type between the type-parameter type
+/// and the promoted bound.
 class TypeParameterType extends DartType {
-  /// The nullability declared on the type.
+  /// Nullability of the type-parameter type or of its part of the intersection.
   ///
-  /// Declarations of type-parameter types can set it to [Nullability.nullable]
-  /// or [Nullability.legacy].  Otherwise, it's computed from the nullability
-  /// of the type parameter bound.
-  Nullability declaredNullability;
+  /// Declarations of type-parameter types can set the nullability of a
+  /// type-parameter type to [Nullability.nullable] (if the `?` marker is used)
+  /// or [Nullability.legacy] (if the type comes from a library opted out from
+  /// NNBD).  Otherwise, it's defined indirectly via the nullability of the
+  /// bound of [parameter].  In cases when the [TypeParameterType] represents an
+  /// intersection between a type-parameter type and [promotedBound],
+  /// [typeParameterTypeNullability] represents the nullability of the left-hand
+  /// side of the intersection.
+  Nullability typeParameterTypeNullability;
 
   TypeParameter parameter;
 
@@ -5751,7 +5799,8 @@
   DartType promotedBound;
 
   TypeParameterType(this.parameter,
-      [this.promotedBound, this.declaredNullability = Nullability.legacy]);
+      [this.promotedBound,
+      this.typeParameterTypeNullability = Nullability.legacy]);
 
   R accept<R>(DartTypeVisitor<R> v) => v.visitTypeParameterType(this);
   R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) =>
@@ -5768,97 +5817,108 @@
   /// Returns the bound of the type parameter, accounting for promotions.
   DartType get bound => promotedBound ?? parameter.bound;
 
-  /// Actual nullability of the type, calculated from its parts.
+  /// Nullability of the type, calculated from its parts.
   ///
-  /// [nullability] is calculated from [declaredNullability] and the
-  /// nullabilities of [promotedBound] and the bound of [parameter].
+  /// [nullability] is calculated from [typeParameterTypeNullability] and the
+  /// nullability of [promotedBound] if it's present.
   ///
-  /// For example, in the following program [declaredNullability] both `x` and
-  /// `y` is [Nullability.nullable], because it's copied from that of `bar`.
-  /// However, despite [nullability] of `x` is [Nullability.nullable],
-  /// [nullability] of `y` is [Nullability.nonNullable] because of its
-  /// [promotedBound].
+  /// For example, in the following program [typeParameterTypeNullability] of
+  /// both `x` and `y` is [Nullability.neither], because it's copied from that
+  /// of `bar` and T has a nullable type as its bound.  However, despite
+  /// [nullability] of `x` is [Nullability.neither], [nullability] of `y` is
+  /// [Nullability.nonNullable] because of its [promotedBound].
   ///
   ///     class A<T extends Object?> {
-  ///       foo(T? bar) {
+  ///       foo(T bar) {
   ///         var x = bar;
   ///         if (bar is int) {
   ///           var y = bar;
   ///         }
   ///       }
   ///     }
-  Nullability get nullability =>
-      getNullability(parameter, promotedBound, declaredNullability);
+  Nullability get nullability {
+    return getNullability(
+        typeParameterTypeNullability ?? computeNullabilityFromBound(parameter),
+        promotedBound);
+  }
 
+  /// Gets the nullability of a type-parameter type based on the bound.
+  ///
+  /// This is a helper function to be used when the bound of the type parameter
+  /// is changing or is being set for the first time, and the update on some
+  /// type-parameter types is required.
   static Nullability computeNullabilityFromBound(TypeParameter typeParameter) {
-    // If the bound is nullable, both nullable and non-nullable types can be
-    // passed in for the type parameter, making the corresponding type
-    // parameter types 'neither.'  Otherwise, the nullability matches that of
-    // the bound.
+    // If the bound is nullable or 'neither', both nullable and non-nullable
+    // types can be passed in for the type parameter, making the corresponding
+    // type parameter types 'neither.'  Otherwise, the nullability matches that
+    // of the bound.
     DartType bound = typeParameter.bound;
     if (bound == null) {
-      throw new StateError("Can't compute nullability from absent bound.");
+      throw new StateError("Can't compute nullability from an absent bound.");
     }
     Nullability boundNullability =
         bound is InvalidType ? Nullability.neither : bound.nullability;
-    return boundNullability == Nullability.nullable
+    return boundNullability == Nullability.nullable ||
+            boundNullability == Nullability.neither
         ? Nullability.neither
         : boundNullability;
   }
 
-  /// Get nullability of [TypeParameterType] from arguments to its constructor.
+  /// Gets nullability of [TypeParameterType] from arguments to its constructor.
   ///
-  /// This method is supposed to be used only in the constructor of
-  /// [TypeParameterType] to compute the value of
-  /// [TypeParameterType.nullability] from the arguments passed to the constructor.
-  static Nullability getNullability(TypeParameter parameter,
-      DartType promotedBound, Nullability declaredNullability) {
-    // If promotedBound is null, getNullability returns the nullability of
-    // either T or T? where T is parameter and the presence of '?' is determined
-    // by nullability.
-
-    // If promotedBound isn't null, getNullability returns the nullability of an
-    // intersection of the left-hand side (referred to as LHS below) and the
-    // right-hand side (referred to as RHS below).  LHS is parameter followed by
-    // nullability, and RHS is promotedBound.  That is, getNullability returns
-    // the nullability of either T & P or T? & P where T is parameter, P is
-    // promotedBound, and the presence of '?' is determined by nullability.
-    // Note that RHS is always a subtype of the bound of the type parameter.
-
-    Nullability lhsNullability;
-
-    // If the nullability is declared explicitly, use it as the nullability of
-    // the LHS of the intersection.  Otherwise, compute it from the bound.
-    if (declaredNullability != null) {
-      lhsNullability = declaredNullability;
-    } else {
-      lhsNullability = computeNullabilityFromBound(parameter);
-    }
+  /// The method combines [typeParameterTypeNullability] and the nullability of
+  /// [promotedBound] to yield the nullability of the intersection type.  If the
+  /// right-hand side of the intersection is absent (that is, if [promotedBound]
+  /// is null), the nullability of the intersection type is simply
+  /// [typeParameterTypeNullability].
+  static Nullability getNullability(
+      Nullability typeParameterTypeNullability, DartType promotedBound) {
+    // If promotedBound is null, getNullability simply returns the nullability
+    // of the type parameter type.
+    Nullability lhsNullability = typeParameterTypeNullability;
     if (promotedBound == null) {
       return lhsNullability;
     }
 
-    // In practice a type parameter of legacy type can only be used in type
-    // annotations within the corresponding class declaration.  If it's legacy,
-    // then the entire library containing the class is opt-out, and any RHS is
-    // deemed to be legacy too.  So, it's necessary to only check LHS for being
-    // legacy.
-    if (lhsNullability == Nullability.legacy) {
-      return Nullability.legacy;
-    }
+    // If promotedBound isn't null, getNullability returns the nullability of an
+    // intersection of the left-hand side (referred to as LHS below) and the
+    // right-hand side (referred to as RHS below).  Note that RHS is always a
+    // subtype of the bound of the type parameter.
 
-    // Intersection is non-nullable if and only if RHS is non-nullable.
+    // The code below implements the rule for the nullability of an intersection
+    // type as per the following table:
     //
-    // The proof is as follows.  Intersection is non-nullable if at least one of
-    // LHS or RHS is non-nullable.  The case of non-nullable RHS is trivial.  In
-    // the case of non-nullable LHS, its bound should be non-nullable.  RHS is
-    // known to always be a subtype of the bound of LHS; therefore, RHS is
-    // non-nullable.
+    // | LHS \ RHS |  !  |  ?  |  *  |  %  |
+    // |-----------|-----|-----|-----|-----|
+    // |     !     |  !  | N/A | N/A |  !  |
+    // |     ?     | N/A | N/A | N/A | N/A |
+    // |     *     | N/A | N/A |  *  | N/A |
+    // |     %     |  !  |  %  | N/A |  %  |
     //
-    // Note that it also follows from the above that non-nullable RHS implies
-    // non-nullable LHS, so the check below covers the case lhsNullability ==
-    // Nullability.nonNullable.
-    if (promotedBound.nullability == Nullability.nonNullable) {
+    // In the table, LHS corresponds to lhsNullability in the code below; RHS
+    // corresponds to promotedBound.nullability; !, ?, *, and % correspond to
+    // nonNullable, nullable, legacy, and neither values of the Nullability
+    // enum.
+    //
+    // Whenever there's N/A in the table, it means that the corresponding
+    // combination of the LHS and RHS nullability is not possible when compiling
+    // from Dart source files, so we can define it to be whatever is faster and
+    // more convenient to implement.  The verifier should check that the cases
+    // marked as N/A never occur in the output of the CFE.
+    //
+    // The code below uses the following extension of the table function:
+    //
+    // | LHS \ RHS |  !  |  ?  |  *  |  %  |
+    // |-----------|-----|-----|-----|-----|
+    // |     !     |  !  |  !  |  !  |  !  |
+    // |     ?     |  !  |  *  |  *  |  %  |
+    // |     *     |  !  |  *  |  *  |  %  |
+    // |     %     |  !  |  %  |  %  |  %  |
+
+    // Intersection with a non-nullable type always yields a non-nullable type,
+    // as it's the most restrictive kind of types.
+    if (lhsNullability == Nullability.nonNullable ||
+        promotedBound.nullability == Nullability.nonNullable) {
       return Nullability.nonNullable;
     }
 
@@ -5879,30 +5939,69 @@
     //         }
     //       }
     //     }
-    //
-    // Note that RHS can't be 'legacy' or non-nullable at this point due to the
-    // checks above.
-    if (lhsNullability == Nullability.neither) {
+    if (lhsNullability == Nullability.neither ||
+        promotedBound.nullability == Nullability.neither) {
       return Nullability.neither;
     }
 
-    // At this point the only possibility for LHS is to be nullable, and for RHS
-    // is to be either nullable or legacy.  Both combinations for LHS and RHS
-    // should yield the nullability of RHS as the nullability for the
-    // intersection.  Consider the following code for clarification:
-    //
-    //   class A<X extends Object?, Y extends X> {
-    //     foo(X? x) {
-    //       if (x is Y) {
-    //         x = null;     // Compile-time error.  Consider X = Y = int.
-    //         Object a = x; // Compile-time error.  Consider X = Y = int?.
-    //       }
-    //       if (x is int?) {
-    //         x = null;     // Ok.  Both X? and int? are nullable.
-    //       }
-    //     }
-    //   }
-    return promotedBound.nullability;
+    return Nullability.legacy;
+  }
+}
+
+/// Value set for variance of a type parameter X in a type term T.
+class Variance {
+  /// Used when X does not occur free in T.
+  static const int unrelated = 0;
+
+  /// Used when X occurs free in T, and U <: V implies [U/X]T <: [V/X]T.
+  static const int covariant = 1;
+
+  /// Used when X occurs free in T, and U <: V implies [V/X]T <: [U/X]T.
+  static const int contravariant = 2;
+
+  /// Used when there exists a pair U and V such that U <: V, but [U/X]T and
+  /// [V/X]T are incomparable.
+  static const int invariant = 3;
+
+  /// Variance values form a lattice where [unrelated] is the top, [invariant]
+  /// is the bottom, and [covariant] and [contravariant] are incomparable.
+  /// [meet] calculates the meet of two elements of such lattice.  It can be
+  /// used, for example, to calculate the variance of a typedef type parameter
+  /// if it's encountered on the r.h.s. of the typedef multiple times.
+  static int meet(int a, int b) => a | b;
+
+  /// Combines variances of X in T and Y in S into variance of X in [Y/T]S.
+  ///
+  /// Consider the following examples:
+  ///
+  /// * variance of X in Function(X) is [contravariant], variance of Y in
+  /// List<Y> is [covariant], so variance of X in List<Function(X)> is
+  /// [contravariant];
+  ///
+  /// * variance of X in List<X> is [covariant], variance of Y in Function(Y) is
+  /// [contravariant], so variance of X in Function(List<X>) is [contravariant];
+  ///
+  /// * variance of X in Function(X) is [contravariant], variance of Y in
+  /// Function(Y) is [contravariant], so variance of X in Function(Function(X))
+  /// is [covariant];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef F<Z> = Function();
+  ///
+  /// then variance of X in F<X> is [unrelated], variance of Y in List<Y> is
+  /// [covariant], so variance of X in List<F<X>> is [unrelated];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef G<Z> = Z Function(Z);
+  ///
+  /// then variance of X in List<X> is [covariant], variance of Y in G<Y> is
+  /// [invariant], so variance of `X` in `G<List<X>>` is [invariant].
+  static int combine(int a, int b) {
+    if (a == unrelated || b == unrelated) return unrelated;
+    if (a == invariant || b == invariant) return invariant;
+    return a == b ? covariant : contravariant;
   }
 }
 
@@ -5939,6 +6038,12 @@
   /// argument of a dynamic invocation of a generic function.
   DartType defaultType;
 
+  /// Describes variance of the type parameter w.r.t. declaration on which it is
+  /// defined.  It's always [Variance.covariant] for classes, and for typedefs
+  /// it's the variance of the type parameters in the type term on the r.h.s. of
+  /// the typedef.
+  int variance = Variance.covariant;
+
   TypeParameter([this.name, this.bound, this.defaultType]);
 
   // Must match serialized bit positions.
@@ -6095,7 +6200,7 @@
   R accept<R>(ConstantVisitor<R> v) => v.visitBoolConstant(this);
   R acceptReference<R>(Visitor<R> v) => v.visitBoolConstantReference(this);
 
-  DartType getType(TypeEnvironment types) => types.boolType;
+  DartType getType(TypeEnvironment types) => types.coreTypes.boolLegacyRawType;
 }
 
 /// An integer constant on a non-JS target.
@@ -6106,7 +6211,7 @@
   R accept<R>(ConstantVisitor<R> v) => v.visitIntConstant(this);
   R acceptReference<R>(Visitor<R> v) => v.visitIntConstantReference(this);
 
-  DartType getType(TypeEnvironment types) => types.intType;
+  DartType getType(TypeEnvironment types) => types.coreTypes.intLegacyRawType;
 }
 
 /// A double constant on a non-JS target or any numeric constant on a JS target.
@@ -6121,7 +6226,8 @@
   bool operator ==(Object other) =>
       other is DoubleConstant && identical(value, other.value);
 
-  DartType getType(TypeEnvironment types) => types.doubleType;
+  DartType getType(TypeEnvironment types) =>
+      types.coreTypes.doubleLegacyRawType;
 }
 
 class StringConstant extends PrimitiveConstant<String> {
@@ -6133,7 +6239,8 @@
   R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
   R acceptReference<R>(Visitor<R> v) => v.visitStringConstantReference(this);
 
-  DartType getType(TypeEnvironment types) => types.stringType;
+  DartType getType(TypeEnvironment types) =>
+      types.coreTypes.stringLegacyRawType;
 }
 
 class SymbolConstant extends Constant {
@@ -6161,7 +6268,8 @@
           other.name == name &&
           other.libraryReference == libraryReference);
 
-  DartType getType(TypeEnvironment types) => types.symbolType;
+  DartType getType(TypeEnvironment types) =>
+      types.coreTypes.symbolLegacyRawType;
 }
 
 class MapConstant extends Constant {
@@ -6435,7 +6543,7 @@
     return other is TypeLiteralConstant && other.type == type;
   }
 
-  DartType getType(TypeEnvironment types) => types.typeType;
+  DartType getType(TypeEnvironment types) => types.coreTypes.typeLegacyRawType;
 }
 
 class UnevaluatedConstant extends Constant {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 32f2210..f8585a5 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -8,6 +8,7 @@
 import 'dart:typed_data';
 
 import '../ast.dart';
+import '../src/bounds_checks.dart' show computeVariance;
 import '../transformations/flags.dart';
 import 'tag.dart';
 
@@ -642,7 +643,7 @@
 
     _byteOffset = index.binaryOffsetForSourceTable;
     Map<Uri, Source> uriToSource = readUriToSource();
-    component.uriToSource.addAll(uriToSource);
+    _mergeUriToSource(component.uriToSource, uriToSource);
 
     _byteOffset = _componentStartOffset + componentFileSize;
   }
@@ -683,7 +684,7 @@
 
     _byteOffset = index.binaryOffsetForSourceTable;
     Map<Uri, Source> uriToSource = readUriToSource();
-    component.uriToSource.addAll(uriToSource);
+    _mergeUriToSource(component.uriToSource, uriToSource);
 
     _byteOffset = index.binaryOffsetForConstantTable;
     readConstantTable();
@@ -751,6 +752,23 @@
     return uriToSource;
   }
 
+  // Add everything from [src] into [dst], but don't overwrite a non-empty
+  // source with an empty source. Empty sources may be introduced by
+  // synthetic, copy-down implementations such as mixin applications or
+  // noSuchMethod forwarders.
+  void _mergeUriToSource(Map<Uri, Source> dst, Map<Uri, Source> src) {
+    if (dst.isEmpty) {
+      // Fast path for the common case of one component per binary.
+      dst.addAll(src);
+    } else {
+      src.forEach((Uri key, Source value) {
+        if (value.source.isNotEmpty || !dst.containsKey(key)) {
+          dst[key] = value;
+        }
+      });
+    }
+  }
+
   CanonicalName readCanonicalNameReference() {
     var index = readUInt();
     if (index == 0) return null;
@@ -995,6 +1013,10 @@
     node.namedParameters.addAll(readAndPushVariableDeclarationList());
     typeParameterStack.length = 0;
     variableStack.length = 0;
+    for (int i = 0; i < node.typeParameters.length; ++i) {
+      node.typeParameters[i].variance =
+          computeVariance(node.typeParameters[i], type);
+    }
     if (shouldWriteData) {
       node.fileOffset = fileOffset;
       node.name = name;
@@ -1661,6 +1683,9 @@
           ..fileOffset = offset;
       case Tag.Not:
         return new Not(readExpression());
+      case Tag.NullCheck:
+        int offset = readOffset();
+        return new NullCheck(readExpression())..fileOffset = offset;
       case Tag.LogicalExpression:
         return new LogicalExpression(readExpression(),
             logicalOperatorToString(readByte()), readExpression());
@@ -2162,6 +2187,7 @@
     node.name = readStringOrNullIfEmpty();
     node.bound = readDartType();
     node.defaultType = readDartTypeOption();
+    node.variance = Variance.covariant;
   }
 
   Arguments readArguments() {
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index ac32edd..9e34e8c 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1495,6 +1495,13 @@
     writeNode(node.operand);
   }
 
+  @override
+  void visitNullCheck(NullCheck node) {
+    writeByte(Tag.NullCheck);
+    writeOffset(node.fileOffset);
+    writeNode(node.operand);
+  }
+
   int logicalOperatorIndex(String operator) {
     switch (operator) {
       case '&&':
@@ -2097,7 +2104,7 @@
   @override
   void visitTypeParameterType(TypeParameterType node) {
     writeByte(Tag.TypeParameterType);
-    writeByte(node.declaredNullability.index);
+    writeByte(node.typeParameterTypeNullability.index);
     writeUInt30(_typeParameterIndexer[node.parameter]);
     writeOptionalNode(node.promotedBound);
   }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 0645cb9..33091c0 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -48,6 +48,7 @@
   static const int ConstructorInvocation = 31;
   static const int ConstConstructorInvocation = 32;
   static const int Not = 33;
+  static const int NullCheck = 117;
   static const int LogicalExpression = 34;
   static const int ConditionalExpression = 35;
   static const int StringConcatenation = 36;
@@ -130,6 +131,7 @@
   /// 114 is occupied by [InstanceCreation] (expression).
   /// 115 is occupied by [Extension].
   /// 116 is occupied by [FileUriExpression] (expression).
+  /// 117 is occupied by [NullCheck] (expression).
 
   static const int SpecializedTagHighBit = 0x80; // 10000000
   static const int SpecializedTagMask = 0xF8; // 11111000
@@ -146,7 +148,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 = 32;
+  static const int BinaryFormatVersion = 33;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index f80716e..1f846ce 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -180,6 +180,10 @@
     return new Not(clone(node.operand));
   }
 
+  visitNullCheck(NullCheck node) {
+    return new NullCheck(clone(node.operand));
+  }
+
   visitLogicalExpression(LogicalExpression node) {
     return new LogicalExpression(
         clone(node.left), node.operator, clone(node.right));
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index 5924ca6..0e31d92 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -245,7 +245,7 @@
     }
 
     // Permit any invocation on Function type.
-    if (receiver == environment.rawFunctionType &&
+    if (receiver == environment.coreTypes.functionLegacyRawType &&
         where is MethodInvocation &&
         where.name.name == 'call') {
       return;
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 040d266..1e59288 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -15,6 +15,7 @@
         TypeParameter,
         TypeParameterType,
         TypedefType,
+        Variance,
         VoidType;
 
 import '../type_algebra.dart' show Substitution, substitute;
@@ -398,7 +399,7 @@
     return const BottomType();
   } else if ((type is BottomType || isNull(typeEnvironment, type)) &&
       !isCovariant) {
-    return typeEnvironment.objectType;
+    return typeEnvironment.coreTypes.objectLegacyRawType;
   } else if (type is InterfaceType && type.classNode.typeParameters != null) {
     List<DartType> replacedTypeArguments =
         new List<DartType>(type.typeArguments.length);
@@ -448,7 +449,7 @@
 
 bool isObject(TypeEnvironment typeEnvironment, DartType type) {
   return type is InterfaceType &&
-      type.classNode == typeEnvironment.objectType.classNode;
+      type.classNode == typeEnvironment.coreTypes.objectClass;
 }
 
 bool isNull(TypeEnvironment typeEnvironment, DartType type) {
@@ -456,58 +457,84 @@
       type.classNode == typeEnvironment.nullType.classNode;
 }
 
-// Value set for variance of a type parameter X in a type term T.
-class Variance {
-  // Used when X does not occur free in T.
-  static const int unrelated = 0;
+int computeVariance(TypeParameter typeParameter, DartType type) {
+  return type.accept(new VarianceCalculator(typeParameter));
+}
 
-  // Used when X occurs free in T, and U <: V implies [U/X]T <: [V/X]T.
-  static const int covariant = 1;
+class VarianceCalculator implements DartTypeVisitor<int> {
+  final TypeParameter typeParameter;
 
-  // Used when X occurs free in T, and U <: V implies [V/X]T <: [U/X]T.
-  static const int contravariant = 2;
+  VarianceCalculator(this.typeParameter);
 
-  // Used when there exists a pair U and V such that U <: V, but [U/X]T and
-  // [V/X]T are incomparable.
-  static const int invariant = 3;
+  @override
+  int defaultDartType(DartType node) => Variance.unrelated;
 
-  // Variance values form a lattice where [unrelated] is the top, [invariant]
-  // is the bottom, and [covariant] and [contravariant] are incomparable.
-  // [meet] calculates the meet of two elements of such lattice.  It can be
-  // used, for example, to calculate the variance of a typedef type parameter
-  // if it's encountered on the r.h.s. of the typedef multiple times.
-  static int meet(int a, int b) => a | b;
-
-  // Combines variances of X in T and Y in S into variance of X in [Y/T]S.
-  //
-  // Consider the following examples:
-  //
-  // * variance of X in Function(X) is [contravariant], variance of Y in List<Y>
-  // is [covariant], so variance of X in List<Function(X)> is [contravariant];
-  //
-  // * variance of X in List<X> is [covariant], variance of Y in Function(Y) is
-  // [contravariant], so variance of X in Function(List<X>) is [contravariant];
-  //
-  // * variance of X in Function(X) is [contravariant], variance of Y in
-  // Function(Y) is [contravariant], so variance of X in Function(Function(X))
-  // is [covariant];
-  //
-  // * let the following be declared:
-  //
-  //     typedef F<Z> = Function();
-  //
-  // then variance of X in F<X> is [unrelated], variance of Y in List<Y> is
-  // [covariant], so variance of X in List<F<X>> is [unrelated];
-  //
-  // * let the following be declared:
-  //
-  //     typedef G<Z> = Z Function(Z);
-  //
-  // then variance of X in List<X> is [covariant], variance of Y in G<Y> is
-  // [invariant], so variance of `X` in `G<List<X>>` is [invariant].
-  static int combine(int a, int b) {
-    if (a == unrelated || b == unrelated) return unrelated;
-    if (a == invariant || b == invariant) return invariant;
-    return a == b ? covariant : contravariant;
+  @override
+  int visitTypeParameterType(TypeParameterType node) {
+    if (node.parameter == typeParameter) return Variance.covariant;
+    return Variance.unrelated;
   }
+
+  @override
+  int visitInterfaceType(InterfaceType node) {
+    int result = Variance.unrelated;
+    for (DartType argument in node.typeArguments) {
+      result = Variance.meet(result, argument.accept(this));
+    }
+    return result;
+  }
+
+  @override
+  int visitTypedefType(TypedefType node) {
+    int result = Variance.unrelated;
+    for (int i = 0; i < node.typeArguments.length; ++i) {
+      result = Variance.meet(
+          result,
+          Variance.combine(
+              node.typeArguments[i].accept(this),
+              node.typedefNode.type.accept(
+                  new VarianceCalculator(node.typedefNode.typeParameters[i]))));
+    }
+    return result;
+  }
+
+  @override
+  int visitFunctionType(FunctionType node) {
+    int result = Variance.unrelated;
+    result = Variance.meet(result, node.returnType.accept(this));
+    for (TypeParameter functionTypeParameter in node.typeParameters) {
+      // If [typeParameter] is referenced in the bound at all, it makes the
+      // variance of [typeParameter] in the entire type invariant.  The
+      // invocation of the visitor below is made to simply figure out if
+      // [typeParameter] occurs in the bound.
+      if (functionTypeParameter.bound.accept(this) != Variance.unrelated) {
+        result = Variance.invariant;
+      }
+    }
+    for (DartType positionalType in node.positionalParameters) {
+      result = Variance.meet(
+          result,
+          Variance.combine(
+              Variance.contravariant, positionalType.accept(this)));
+    }
+    for (NamedType namedType in node.namedParameters) {
+      result = Variance.meet(
+          result,
+          Variance.combine(
+              Variance.contravariant, namedType.type.accept(this)));
+    }
+    return result;
+  }
+
+  @override
+  int visitBottomType(BottomType node) => defaultDartType(node);
+
+  @override
+  int visitVoidType(VoidType node) => defaultDartType(node);
+
+  @override
+  int visitDynamicType(DynamicType node) => defaultDartType(node);
+
+  @override
+  int visitInvalidType(InvalidType node) => defaultDartType(node);
 }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index ccff048..707b3a1 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1292,6 +1292,11 @@
     writeExpression(node.operand, Precedence.PREFIX);
   }
 
+  visitNullCheck(NullCheck node) {
+    writeExpression(node.operand, Precedence.POSTFIX);
+    writeSymbol('!');
+  }
+
   visitLogicalExpression(LogicalExpression node) {
     int precedence = Precedence.binaryPrecedence[node.operator];
     writeExpression(node.left, precedence);
@@ -2119,13 +2124,13 @@
 
   visitTypeParameterType(TypeParameterType node) {
     writeTypeParameterReference(node.parameter);
-    writeNullability(node.declaredNullability);
+    writeNullability(node.typeParameterTypeNullability);
     if (node.promotedBound != null) {
       writeSpaced('&');
       writeType(node.promotedBound);
 
       writeWord("/* '");
-      writeNullability(node.declaredNullability, inComment: true);
+      writeNullability(node.typeParameterTypeNullability, inComment: true);
       writeWord("' & '");
       writeDartTypeNullability(node.promotedBound, inComment: true);
       writeWord("' = '");
@@ -2137,6 +2142,14 @@
   visitTypeParameter(TypeParameter node) {
     writeModifier(node.isGenericCovariantImpl, 'generic-covariant-impl');
     writeAnnotationList(node.annotations, separateLines: false);
+    if (node.variance != Variance.covariant) {
+      writeWord(const <String>[
+        "unrelated",
+        "covariant",
+        "contravariant",
+        "invariant"
+      ][node.variance]);
+    }
     writeWord(getTypeParameterName(node));
     writeSpaced('extends');
     writeType(node.bound);
@@ -2329,6 +2342,7 @@
   int visitStaticInvocation(StaticInvocation node) => CALLEE;
   int visitConstructorInvocation(ConstructorInvocation node) => CALLEE;
   int visitNot(Not node) => PREFIX;
+  int visitNullCheck(NullCheck node) => PRIMARY;
   int visitLogicalExpression(LogicalExpression node) =>
       binaryPrecedence[node.operator];
   int visitConditionalExpression(ConditionalExpression node) => CONDITIONAL;
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index 18e2cd5..f381ec2 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -942,6 +942,12 @@
   }
 
   @override
+  void visitNullCheck(NullCheck node) {
+    storeLastSeenUriAndOffset(node);
+    makeExpressionRoundTrip(node);
+  }
+
+  @override
   void visitConstructorInvocation(ConstructorInvocation node) {
     storeLastSeenUriAndOffset(node);
     makeExpressionRoundTrip(node);
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 90fff29..a0f364a 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -406,13 +406,13 @@
 
   @override
   DartType visitBoolLiteral(BoolLiteral node) {
-    return environment.boolType;
+    return environment.coreTypes.boolLegacyRawType;
   }
 
   @override
   DartType visitConditionalExpression(ConditionalExpression node) {
-    node.condition =
-        checkAndDowncastExpression(node.condition, environment.boolType);
+    node.condition = checkAndDowncastExpression(
+        node.condition, environment.coreTypes.boolLegacyRawType);
     node.then = checkAndDowncastExpression(node.then, node.staticType);
     node.otherwise =
         checkAndDowncastExpression(node.otherwise, node.staticType);
@@ -452,7 +452,7 @@
 
   @override
   DartType visitDoubleLiteral(DoubleLiteral node) {
-    return environment.doubleType;
+    return environment.coreTypes.doubleLegacyRawType;
   }
 
   @override
@@ -463,7 +463,7 @@
 
   @override
   DartType visitIntLiteral(IntLiteral node) {
-    return environment.intType;
+    return environment.coreTypes.intLegacyRawType;
   }
 
   @override
@@ -474,7 +474,7 @@
   @override
   DartType visitIsExpression(IsExpression node) {
     visitExpression(node.operand);
-    return environment.boolType;
+    return environment.coreTypes.boolLegacyRawType;
   }
 
   @override
@@ -529,9 +529,11 @@
 
   @override
   DartType visitLogicalExpression(LogicalExpression node) {
-    node.left = checkAndDowncastExpression(node.left, environment.boolType);
-    node.right = checkAndDowncastExpression(node.right, environment.boolType);
-    return environment.boolType;
+    node.left = checkAndDowncastExpression(
+        node.left, environment.coreTypes.boolLegacyRawType);
+    node.right = checkAndDowncastExpression(
+        node.right, environment.coreTypes.boolLegacyRawType);
+    return environment.coreTypes.boolLegacyRawType;
   }
 
   @override
@@ -595,7 +597,7 @@
       var receiver = visitExpression(node.receiver);
       if (node.name.name == '==') {
         visitExpression(node.arguments.positional.single);
-        return environment.boolType;
+        return environment.coreTypes.boolLegacyRawType;
       }
       if (node.name.name == 'call' && receiver is FunctionType) {
         return handleFunctionCall(node, receiver, node.arguments);
@@ -646,7 +648,13 @@
   @override
   DartType visitNot(Not node) {
     visitExpression(node.operand);
-    return environment.boolType;
+    return environment.coreTypes.boolLegacyRawType;
+  }
+
+  @override
+  DartType visitNullCheck(NullCheck node) {
+    // TODO(johnniwinther): Return `NonNull(visitExpression(types))`.
+    return visitExpression(node.operand);
   }
 
   @override
@@ -679,7 +687,7 @@
   @override
   DartType visitStringConcatenation(StringConcatenation node) {
     node.expressions.forEach(visitExpression);
-    return environment.stringType;
+    return environment.coreTypes.stringLegacyRawType;
   }
 
   @override
@@ -731,7 +739,7 @@
 
   @override
   DartType visitStringLiteral(StringLiteral node) {
-    return environment.stringType;
+    return environment.coreTypes.stringLegacyRawType;
   }
 
   @override
@@ -774,7 +782,7 @@
 
   @override
   DartType visitSymbolLiteral(SymbolLiteral node) {
-    return environment.symbolType;
+    return environment.coreTypes.symbolLegacyRawType;
   }
 
   @override
@@ -790,7 +798,7 @@
 
   @override
   DartType visitTypeLiteral(TypeLiteral node) {
-    return environment.typeType;
+    return environment.coreTypes.typeLegacyRawType;
   }
 
   @override
@@ -812,7 +820,7 @@
 
   @override
   DartType visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
-    return environment.objectType;
+    return environment.coreTypes.objectLegacyRawType;
   }
 
   @override
@@ -847,8 +855,8 @@
   @override
   visitDoStatement(DoStatement node) {
     visitStatement(node.body);
-    node.condition =
-        checkAndDowncastExpression(node.condition, environment.boolType);
+    node.condition = checkAndDowncastExpression(
+        node.condition, environment.coreTypes.boolLegacyRawType);
   }
 
   @override
@@ -912,8 +920,8 @@
   visitForStatement(ForStatement node) {
     node.variables.forEach(visitVariableDeclaration);
     if (node.condition != null) {
-      node.condition =
-          checkAndDowncastExpression(node.condition, environment.boolType);
+      node.condition = checkAndDowncastExpression(
+          node.condition, environment.coreTypes.boolLegacyRawType);
     }
     node.updates.forEach(visitExpression);
     visitStatement(node.body);
@@ -926,8 +934,8 @@
 
   @override
   visitIfStatement(IfStatement node) {
-    node.condition =
-        checkAndDowncastExpression(node.condition, environment.boolType);
+    node.condition = checkAndDowncastExpression(
+        node.condition, environment.coreTypes.boolLegacyRawType);
     visitStatement(node.then);
     if (node.otherwise != null) {
       visitStatement(node.otherwise);
@@ -987,8 +995,8 @@
 
   @override
   visitWhileStatement(WhileStatement node) {
-    node.condition =
-        checkAndDowncastExpression(node.condition, environment.boolType);
+    node.condition = checkAndDowncastExpression(
+        node.condition, environment.coreTypes.boolLegacyRawType);
     visitStatement(node.body);
   }
 
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 98ef5f2..31518fa 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -32,23 +32,14 @@
     return new HierarchyBasedTypeEnvironment(coreTypes, hierarchy);
   }
 
-  // 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;
   Class get futureOrClass => coreTypes.futureOrClass;
 
+  InterfaceType get objectLegacyRawType => coreTypes.objectLegacyRawType;
+  InterfaceType get nullType => coreTypes.nullType;
+  InterfaceType get functionLegacyRawType => coreTypes.functionLegacyRawType;
+
   InterfaceType literalListType(DartType elementType) {
     return new InterfaceType(coreTypes.listClass, <DartType>[elementType]);
   }
@@ -144,8 +135,10 @@
   /// Otherwise `num` is returned.
   DartType getTypeOfOverloadedArithmetic(DartType type1, DartType type2) {
     if (type1 == type2) return type1;
-    if (type1 == doubleType || type2 == doubleType) return doubleType;
-    return numType;
+    if (type1 == coreTypes.doubleLegacyRawType ||
+        type2 == coreTypes.doubleLegacyRawType)
+      return coreTypes.doubleLegacyRawType;
+    return coreTypes.numLegacyRawType;
   }
 }
 
@@ -153,9 +146,9 @@
 ///
 /// This lives in a separate class so it can be tested independently of the SDK.
 abstract class SubtypeTester {
-  InterfaceType get objectType;
+  InterfaceType get objectLegacyRawType;
   InterfaceType get nullType;
-  InterfaceType get rawFunctionType;
+  InterfaceType get functionLegacyRawType;
   Class get futureOrClass;
   InterfaceType futureType(DartType type);
 
@@ -165,8 +158,11 @@
 
   /// Determines if the given type is at the top of the type hierarchy.  May be
   /// overridden in subclasses.
-  bool isTop(DartType type) =>
-      type is DynamicType || type is VoidType || type == objectType;
+  bool isTop(DartType type) {
+    return type is DynamicType ||
+        type is VoidType ||
+        type == objectLegacyRawType;
+  }
 
   /// Can be use to collect type checks. To use:
   /// 1. Rename `isSubtypeOf` to `_isSubtypeOf`.
@@ -251,7 +247,7 @@
       return isSubtypeOf(subtype.bound, supertype);
     }
     if (subtype is FunctionType) {
-      if (supertype == rawFunctionType) return true;
+      if (supertype == functionLegacyRawType) return true;
       if (supertype is FunctionType) {
         return _isFunctionSubtypeOf(subtype, supertype);
       }
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 4f95e65..b6007db 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -34,6 +34,7 @@
   R visitConstructorInvocation(ConstructorInvocation node) =>
       defaultExpression(node);
   R visitNot(Not node) => defaultExpression(node);
+  R visitNullCheck(NullCheck node) => defaultExpression(node);
   R visitLogicalExpression(LogicalExpression node) => defaultExpression(node);
   R visitConditionalExpression(ConditionalExpression node) =>
       defaultExpression(node);
@@ -162,6 +163,7 @@
   R visitConstructorInvocation(ConstructorInvocation node) =>
       defaultExpression(node);
   R visitNot(Not node) => defaultExpression(node);
+  R visitNullCheck(NullCheck node) => defaultExpression(node);
   R visitLogicalExpression(LogicalExpression node) => defaultExpression(node);
   R visitConditionalExpression(ConditionalExpression node) =>
       defaultExpression(node);
@@ -673,6 +675,7 @@
   R visitConstructorInvocation(ConstructorInvocation node, T arg) =>
       defaultExpression(node, arg);
   R visitNot(Not node, T arg) => defaultExpression(node, arg);
+  R visitNullCheck(NullCheck node, T arg) => defaultExpression(node, arg);
   R visitLogicalExpression(LogicalExpression node, T arg) =>
       defaultExpression(node, arg);
   R visitConditionalExpression(ConditionalExpression node, T arg) =>
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index b0b05b0..f190364 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.25
+version: 0.3.26
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
@@ -9,6 +9,7 @@
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
   args: '>=0.13.4 <2.0.0'
+  meta: ^1.0.0
 dev_dependencies:
   expect: any
   front_end: any
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 8bb4062..546590f 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -32,19 +32,12 @@
   /// A message used by dartfix to indicate a fix has been applied.
   final String appliedMessage;
 
-  /// An import needs to be added.
-  factory NullabilityFixDescription.addImport(String uri) =>
-      NullabilityFixDescription._(appliedMessage: 'Add import $uri');
-
-  /// A formal parameter needs to have a required modifier added.
+  /// A formal parameter needs to have a required keyword added.
   factory NullabilityFixDescription.addRequired(
           String className, String functionName, String paramName) =>
       NullabilityFixDescription._(
-          appliedMessage:
-              "Add 'required' modifier to parameter $paramName in " +
-                  (className == null
-                      ? functionName
-                      : '$className.$functionName'));
+          appliedMessage: "Add 'required' keyword to parameter $paramName in " +
+              (className == null ? functionName : '$className.$functionName'));
 
   /// An explicit type mentioned in the source program needs to be made
   /// nullable.
diff --git a/pkg/nnbd_migration/lib/src/potential_modification.dart b/pkg/nnbd_migration/lib/src/potential_modification.dart
index ac60b15..a36315d 100644
--- a/pkg/nnbd_migration/lib/src/potential_modification.dart
+++ b/pkg/nnbd_migration/lib/src/potential_modification.dart
@@ -93,54 +93,6 @@
   Iterable<FixReasonInfo> get reasons => discard.reasons;
 }
 
-/// Records information about the possible addition of an import to the source
-/// code.
-class PotentiallyAddImport extends PotentialModification {
-  final _usages = <PotentialModification>[];
-
-  final int _offset;
-  final String importPath;
-
-  PotentiallyAddImport(
-      AstNode beforeNode, String importPath, PotentialModification usage)
-      : this.forOffset(beforeNode.offset, importPath, usage);
-
-  PotentiallyAddImport.forOffset(
-      this._offset, this.importPath, PotentialModification usage) {
-    _usages.add(usage);
-  }
-
-  @override
-  NullabilityFixDescription get description =>
-      NullabilityFixDescription.addImport(importPath);
-
-  @override
-  bool get isEmpty {
-    for (PotentialModification usage in _usages) {
-      if (!usage.isEmpty) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // TODO(danrubel): change all of dartfix NNBD to use DartChangeBuilder
-  @override
-  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);
-  }
-}
-
 /// Records information about the possible addition of a `?` suffix to a type in
 /// the source code.
 class PotentiallyAddQuestionSuffix extends PotentialModification {
@@ -165,7 +117,7 @@
   Iterable<FixReasonInfo> get reasons => [node];
 }
 
-/// Records information about the possible addition of a `@required` annotation
+/// Records information about the possible addition of a `required` keyword
 /// to the source code.
 class PotentiallyAddRequired extends PotentialModification {
   final NullabilityNode _node;
@@ -197,7 +149,7 @@
 
   @override
   Iterable<SourceEdit> get modifications =>
-      isEmpty ? const [] : [SourceEdit(_offset, 0, '@required ')];
+      isEmpty ? const [] : [SourceEdit(_offset, 0, 'required ')];
 
   @override
   Iterable<FixReasonInfo> get reasons => [_node];
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 8406cd4..5266dec 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -173,53 +173,6 @@
       Source source, DefaultFormalParameter parameter, NullabilityNode node) {
     var modification = PotentiallyAddRequired(parameter, node);
     _addPotentialModification(source, modification);
-    _addPotentialImport(
-        source, parameter, modification, 'package:meta/meta.dart');
-  }
-
-  void _addPotentialImport(Source source, AstNode node,
-      PotentialModification usage, String importPath) {
-    // Get the compilation unit - assume not null
-    while (node is! CompilationUnit) {
-      node = node.parent;
-    }
-    var unit = node as CompilationUnit;
-
-    // Find an existing import
-    for (var directive in unit.directives) {
-      if (directive is ImportDirective) {
-        if (directive.uri.stringValue == importPath) {
-          return;
-        }
-      }
-    }
-
-    // Add the usage to an existing modification if possible
-    for (var modification in (_potentialModifications[source] ??= [])) {
-      if (modification is PotentiallyAddImport) {
-        if (modification.importPath == importPath) {
-          modification.addUsage(usage);
-          return;
-        }
-      }
-    }
-
-    // Create a new import modification
-    AstNode beforeNode;
-    for (var directive in unit.directives) {
-      if (directive is ImportDirective || directive is ExportDirective) {
-        beforeNode = directive;
-        break;
-      }
-    }
-    if (beforeNode == null) {
-      for (var declaration in unit.declarations) {
-        beforeNode = declaration;
-        break;
-      }
-    }
-    _addPotentialModification(
-        source, PotentiallyAddImport(beforeNode, importPath, usage));
   }
 
   void _addPotentialModification(
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 6b01783..c0d90a0 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -76,7 +76,6 @@
 
 /// 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;
@@ -1939,6 +1938,20 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_named_parameter_add_required() async {
+    var content = '''
+void f({String s}) {
+  assert(s != null);
+}
+''';
+    var expected = '''
+void f({required String s}) {
+  assert(s != null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_named_parameter_no_default_unused() async {
     var content = '''
 void f({String s}) {}
diff --git a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
index 39ba9f3..1ba7901 100644
--- a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
+++ b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/src/generated/timestamped_data.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:mockito/mockito.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/nullability_migration_impl.dart';
 import 'package:nnbd_migration/src/potential_modification.dart';
@@ -28,46 +29,46 @@
   }
 
   void test_modification_columnLineInfo() {
-    final innerModification = PotentialModificationMock();
-    final potentialModification =
-        PotentiallyAddImport.forOffset(10, 'foo', innerModification);
+    final text = 'void f() {}\nint g() => null;';
+    final offset = text.indexOf('int') + 3;
+    final potentialModification = _PotentialModificationMock(
+        _NullabilityFixDescriptionMock('Add ?'),
+        false,
+        [SourceEdit(offset, 0, '?')]);
     final listener = NullabilityMigrationListenerMock();
-    final source = SourceMock('0123456\n8910');
+    final source = SourceMock(text);
     when(variables.getPotentialModifications()).thenReturn({
       source: [potentialModification]
     });
 
-    when(innerModification.isEmpty).thenReturn(false);
-
     NullabilityMigrationImpl.broadcast(variables, listener, null);
 
     final fix = verify(listener.addFix(captureAny)).captured.single
         as SingleNullabilityFix;
-    expect(fix.description.appliedMessage, 'Add import foo');
+    expect(fix.description.appliedMessage, 'Add ?');
     expect(fix.source, source);
-    expect(fix.location.offset, 10);
+    expect(fix.location.offset, offset);
     expect(fix.location.length, 0);
     expect(fix.location.file, '/test.dart');
     expect(fix.location.startLine, 2);
-    expect(fix.location.startColumn, 3);
+    expect(fix.location.startColumn, 4);
     verifyNever(listener.reportException(any, any, any, any));
     final edit =
         verify(listener.addEdit(fix, captureAny)).captured.single as SourceEdit;
-    expect(edit.offset, 10);
+    expect(edit.offset, offset);
     expect(edit.length, 0);
-    expect(edit.replacement, "import 'foo';\n");
+    expect(edit.replacement, '?');
   }
 
   void test_noModifications_notReported() {
-    final potentialModification = PotentialModificationMock();
+    final potentialModification =
+        _PotentialModificationMock.empty(_NullabilityFixDescriptionMock('foo'));
     final listener = NullabilityMigrationListenerMock();
     final source = SourceMock('');
     when(variables.getPotentialModifications()).thenReturn({
       source: [potentialModification]
     });
 
-    when(potentialModification.modifications).thenReturn([]);
-
     NullabilityMigrationImpl.broadcast(variables, listener, null);
 
     verifyNever(listener.addFix(any));
@@ -91,8 +92,6 @@
 class NullabilityMigrationListenerMock extends Mock
     implements NullabilityMigrationListener {}
 
-class PotentialModificationMock extends Mock implements PotentialModification {}
-
 class SourceMock extends Mock implements Source {
   final String _contents;
 
@@ -102,3 +101,31 @@
 }
 
 class VariablesMock extends Mock implements Variables {}
+
+class _NullabilityFixDescriptionMock implements NullabilityFixDescription {
+  @override
+  final String appliedMessage;
+
+  _NullabilityFixDescriptionMock(this.appliedMessage);
+}
+
+class _PotentialModificationMock extends PotentialModification {
+  @override
+  final NullabilityFixDescription description;
+
+  @override
+  final bool isEmpty;
+
+  @override
+  final Iterable<SourceEdit> modifications;
+
+  _PotentialModificationMock(
+      this.description, this.isEmpty, this.modifications);
+
+  _PotentialModificationMock.empty(this.description)
+      : isEmpty = false,
+        modifications = [];
+
+  @override
+  Iterable<FixReasonInfo> get reasons => throw UnimplementedError();
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 47913ba..61c2e71 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -75,6 +75,7 @@
 dartfix/test/*: SkipByDesign # Only meant to run on vm
 front_end/test/*: SkipByDesign # Only meant to run on vm, most use dart:mirrors and dart:io
 front_end/tool/*: SkipByDesign # Only meant to run on vm
+modular_test/test/memory_pipeline_test: Slow
 nnbd_migration/test/*: SkipByDesign # Uses mirrors
 smith/test/*: SkipByDesign # Only meant to run on vm
 status_file/test/normalize_test: SkipByDesign # Uses dart:io
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 62629db..5ac46ed 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -586,8 +586,12 @@
 
   bool get _isArm => _configuration.architecture == Architecture.arm;
 
+  bool get _isSimArm => _configuration.architecture == Architecture.simarm;
+
   bool get _isArm64 => _configuration.architecture == Architecture.arm64;
 
+  bool get _isSimArm64 => _configuration.architecture == Architecture.simarm64;
+
   bool get _isX64 => _configuration.architecture == Architecture.x64;
 
   bool get _isIA32 => _configuration.architecture == Architecture.ia32;
@@ -701,12 +705,12 @@
   Command computeAssembleCommand(String tempDir, List arguments,
       Map<String, String> environmentOverrides) {
     String cc, shared, ldFlags;
-    if (_isAndroid) {
+    if (_isAndroid || _isSimArm || _isSimArm64) {
       var ndk = "third_party/android_tools/ndk";
       String triple;
-      if (_isArm) {
+      if (_isArm || _isSimArm) {
         triple = "arm-linux-androideabi";
-      } else if (_isArm64) {
+      } else if (_isArm64 || _isSimArm64) {
         triple = "aarch64-linux-android";
       }
       String host;
diff --git a/pkg/test_runner/lib/src/update_errors.dart b/pkg/test_runner/lib/src/update_errors.dart
index f0fa6e4..83ab3b3 100644
--- a/pkg/test_runner/lib/src/update_errors.dart
+++ b/pkg/test_runner/lib/src/update_errors.dart
@@ -96,8 +96,9 @@
 
       var comment = (" " * indent) + "//";
 
-      // If the error can't fit in a line comment, use an explicit location.
-      if (error.column <= 2) {
+      // If the error can't fit in a line comment, or no source location is
+      // sepcified, use an explicit location.
+      if (error.column <= 2 || error.length == 0) {
         if (error.length == null) {
           result.add("$comment [error line $codeLine, column "
               "${error.column}]");
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index 8338073..803f10f 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -21,15 +21,7 @@
 
 import 'error_handling.dart' show withErrorHandling;
 
-import 'log.dart'
-    show
-        logMessage,
-        logStepComplete,
-        logStepStart,
-        logSuiteComplete,
-        logTestComplete,
-        logUnexpectedResult,
-        splitLines;
+import 'log.dart' show Logger, StdoutLogger, splitLines;
 
 import 'multitest.dart' show MultitestTransformer, isError;
 
@@ -112,7 +104,9 @@
   ExpectationSet get expectationSet => ExpectationSet.Default;
 
   Future<Null> run(Chain suite, Set<String> selectors,
-      {int shards = 1, int shard = 0}) async {
+      {int shards = 1,
+      int shard = 0,
+      Logger logger: const StdoutLogger()}) async {
     assert(shards >= 1, "Invalid shards count: $shards");
     assert(0 <= shard && shard < shards,
         "Invalid shard index: $shard, not in range [0,$shards[.");
@@ -182,8 +176,8 @@
           Step step = iterator.current;
           lastStepRun = step;
           isAsync = step.isAsync;
-          logStepStart(completed, unexpectedResults.length, descriptions.length,
-              suite, description, step);
+          logger.logStepStart(completed, unexpectedResults.length,
+              descriptions.length, suite, description, step);
           // TODO(ahe): It's important to share the zone error reporting zone
           // between all the tasks. Otherwise, if a future completes with an
           // error in one zone, and gets stored, it becomes an uncaught error
@@ -201,7 +195,7 @@
         future = future.then((_currentResult) async {
           Result currentResult = _currentResult;
           if (currentResult != null) {
-            logStepComplete(completed, unexpectedResults.length,
+            logger.logStepComplete(completed, unexpectedResults.length,
                 descriptions.length, suite, description, lastStepRun);
             result = currentResult;
             if (currentResult.outcome == Expectation.Pass) {
@@ -217,12 +211,13 @@
             result.addLog("$sb");
             unexpectedResults[description] = result;
             unexpectedOutcomes[description] = expectedOutcomes;
-            logUnexpectedResult(suite, description, result, expectedOutcomes);
+            logger.logUnexpectedResult(
+                suite, description, result, expectedOutcomes);
             exitCode = 1;
           } else {
-            logMessage(sb);
+            logger.logMessage(sb);
           }
-          logTestComplete(++completed, unexpectedResults.length,
+          logger.logTestComplete(++completed, unexpectedResults.length,
               descriptions.length, suite, description);
         });
         if (isAsync) {
@@ -233,14 +228,16 @@
         }
       }
 
+      logger.logTestStart(completed, unexpectedResults.length,
+          descriptions.length, suite, description);
       // The input of the first step is [description].
       await doStep(description);
     }
     await Future.wait(futures);
-    logSuiteComplete();
+    logger.logSuiteComplete();
     if (unexpectedResults.isNotEmpty) {
       unexpectedResults.forEach((TestDescription description, Result result) {
-        logUnexpectedResult(
+        logger.logUnexpectedResult(
             suite, description, result, unexpectedOutcomes[description]);
       });
       print("${unexpectedResults.length} failed:");
diff --git a/pkg/testing/lib/src/log.dart b/pkg/testing/lib/src/log.dart
index edd36638..b15de14 100644
--- a/pkg/testing/lib/src/log.dart
+++ b/pkg/testing/lib/src/log.dart
@@ -38,106 +38,146 @@
   _isVerbose = true;
 }
 
-void logTestComplete(int completed, int failed, int total, Suite suite,
-    TestDescription description) {
-  String message = formatProgress(completed, failed, total);
-  if (suite != null) {
-    message += ": ${formatTestDescription(suite, description)}";
-  }
-  logProgress(message);
+abstract class Logger {
+  void logTestStart(int completed, int failed, int total, Suite suite,
+      TestDescription description);
+
+  void logTestComplete(int completed, int failed, int total, Suite suite,
+      TestDescription description);
+
+  void logStepStart(int completed, int failed, int total, Suite suite,
+      TestDescription description, Step step);
+
+  void logStepComplete(int completed, int failed, int total, Suite suite,
+      TestDescription description, Step step);
+
+  void logProgress(String message);
+
+  void logMessage(Object message);
+
+  void logNumberedLines(String text);
+
+  void logExpectedResult(Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes);
+
+  void logUnexpectedResult(Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes);
+
+  void logSuiteComplete();
+
+  void logUncaughtError(error, StackTrace stackTrace);
 }
 
-void logStepStart(int completed, int failed, int total, Suite suite,
-    TestDescription description, Step step) {
-  String message = formatProgress(completed, failed, total);
-  if (suite != null) {
-    message += ": ${formatTestDescription(suite, description)} ${step.name}";
-    if (step.isAsync) {
-      message += "...";
+class StdoutLogger implements Logger {
+  const StdoutLogger();
+
+  void logTestStart(int completed, int failed, int total, Suite suite,
+      TestDescription description) {}
+
+  void logTestComplete(int completed, int failed, int total, Suite suite,
+      TestDescription description) {
+    String message = formatProgress(completed, failed, total);
+    if (suite != null) {
+      message += ": ${formatTestDescription(suite, description)}";
     }
+    logProgress(message);
   }
-  logProgress(message);
-}
 
-void logStepComplete(int completed, int failed, int total, Suite suite,
-    TestDescription description, Step step) {
-  if (!step.isAsync) return;
-  String message = formatProgress(completed, failed, total);
-  if (suite != null) {
-    message += ": ${formatTestDescription(suite, description)} ${step.name}!";
+  void logStepStart(int completed, int failed, int total, Suite suite,
+      TestDescription description, Step step) {
+    String message = formatProgress(completed, failed, total);
+    if (suite != null) {
+      message += ": ${formatTestDescription(suite, description)} ${step.name}";
+      if (step.isAsync) {
+        message += "...";
+      }
+    }
+    logProgress(message);
   }
-  logProgress(message);
-}
 
-void logProgress(String message) {
-  if (isVerbose) {
-    print(message);
-  } else {
-    print("$eraseLine$message$cursorUp");
+  void logStepComplete(int completed, int failed, int total, Suite suite,
+      TestDescription description, Step step) {
+    if (!step.isAsync) return;
+    String message = formatProgress(completed, failed, total);
+    if (suite != null) {
+      message += ": ${formatTestDescription(suite, description)} ${step.name}!";
+    }
+    logProgress(message);
   }
-}
 
-String formatProgress(int completed, int failed, int total) {
-  Duration elapsed = wallclock.elapsed;
-  String percent = pad((completed / total * 100.0).toStringAsFixed(1), 5);
-  String good = pad(completed - failed, 5);
-  String bad = pad(failed, 5);
-  String minutes = pad(elapsed.inMinutes, 2, filler: "0");
-  String seconds = pad(elapsed.inSeconds % 60, 2, filler: "0");
-  return "[ $minutes:$seconds | $percent% | +$good | -$bad ]";
-}
-
-String formatTestDescription(Suite suite, TestDescription description) {
-  return "${suite.name}/${description.shortName}";
-}
-
-void logMessage(Object message) {
-  if (isVerbose) {
-    print("$message");
-  }
-}
-
-void logNumberedLines(String text) {
-  if (isVerbose) {
-    print(numberedLines(text));
-  }
-}
-
-void logUnexpectedResult(Suite suite, TestDescription description,
-    Result result, Set<Expectation> expectedOutcomes) {
-  print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
-  Uri statusFile = suite.statusFile;
-  if (statusFile != null) {
-    String path = statusFile.toFilePath();
-    if (result.outcome == Expectation.Pass) {
-      print("The test unexpectedly passed, please update $path.");
+  void logProgress(String message) {
+    if (isVerbose) {
+      print(message);
     } else {
-      print("The test had the outcome ${result.outcome}, but the status file "
-          "($path) allows these outcomes: ${expectedOutcomes.join(' ')}");
+      print("$eraseLine$message$cursorUp");
     }
   }
-  String log = result.log;
-  if (log.isNotEmpty) {
-    print(log);
+
+  String formatProgress(int completed, int failed, int total) {
+    Duration elapsed = wallclock.elapsed;
+    String percent = pad((completed / total * 100.0).toStringAsFixed(1), 5);
+    String good = pad(completed - failed, 5);
+    String bad = pad(failed, 5);
+    String minutes = pad(elapsed.inMinutes, 2, filler: "0");
+    String seconds = pad(elapsed.inSeconds % 60, 2, filler: "0");
+    return "[ $minutes:$seconds | $percent% | +$good | -$bad ]";
   }
-  if (result.error != null) {
-    print(result.error);
-    if (result.trace != null) {
-      print(result.trace);
+
+  String formatTestDescription(Suite suite, TestDescription description) {
+    return "${suite.name}/${description.shortName}";
+  }
+
+  void logMessage(Object message) {
+    if (isVerbose) {
+      print("$message");
     }
   }
-}
 
-void logSuiteComplete() {
-  if (!isVerbose) {
-    print("");
+  void logNumberedLines(String text) {
+    if (isVerbose) {
+      print(numberedLines(text));
+    }
   }
-}
 
-void logUncaughtError(error, StackTrace stackTrace) {
-  logMessage(error);
-  if (stackTrace != null) {
-    logMessage(stackTrace);
+  void logExpectedResult(Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes) {}
+
+  void logUnexpectedResult(Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes) {
+    print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
+    Uri statusFile = suite.statusFile;
+    if (statusFile != null) {
+      String path = statusFile.toFilePath();
+      if (result.outcome == Expectation.Pass) {
+        print("The test unexpectedly passed, please update $path.");
+      } else {
+        print("The test had the outcome ${result.outcome}, but the status file "
+            "($path) allows these outcomes: ${expectedOutcomes.join(' ')}");
+      }
+    }
+    String log = result.log;
+    if (log.isNotEmpty) {
+      print(log);
+    }
+    if (result.error != null) {
+      print(result.error);
+      if (result.trace != null) {
+        print(result.trace);
+      }
+    }
+  }
+
+  void logSuiteComplete() {
+    if (!isVerbose) {
+      print("");
+    }
+  }
+
+  void logUncaughtError(error, StackTrace stackTrace) {
+    logMessage(error);
+    if (stackTrace != null) {
+      logMessage(stackTrace);
+    }
   }
 }
 
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index d16cf30..12305ba 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -24,12 +24,7 @@
 import 'analyze.dart' show Analyze;
 
 import 'log.dart'
-    show
-        enableVerboseOutput,
-        isVerbose,
-        logMessage,
-        logNumberedLines,
-        splitLines;
+    show enableVerboseOutput, isVerbose, Logger, splitLines, StdoutLogger;
 
 import 'suite.dart' show Dart, Suite;
 
@@ -55,7 +50,11 @@
 /// `testing.json` isn't located in the current working directory and is a path
 /// relative to [me] which defaults to `Platform.script`.
 Future<Null> runMe(List<String> arguments, CreateContext f,
-    {String configurationPath, Uri me, int shards = 1, int shard = 0}) {
+    {String configurationPath,
+    Uri me,
+    int shards = 1,
+    int shard = 0,
+    Logger logger: const StdoutLogger()}) {
   me ??= Platform.script;
   return withErrorHandling(() async {
     TestRoot testRoot = await computeTestRoot(configurationPath, me);
@@ -66,7 +65,7 @@
         print("Running suite ${suite.name}...");
         ChainContext context = await f(suite, cl.environment);
         await context.run(suite, new Set<String>.from(cl.selectors),
-            shards: shards, shard: shard);
+            shards: shards, shard: shard, logger: logger);
       }
     }
   });
@@ -117,8 +116,8 @@
 }
 
 Future<Null> runProgram(String program, Uri packages) async {
-  logMessage("Running:");
-  logNumberedLines(program);
+  const StdoutLogger().logMessage("Running:");
+  const StdoutLogger().logNumberedLines(program);
   Uri dataUri = new Uri.dataFromString(program);
   ReceivePort exitPort = new ReceivePort();
   Isolate isolate = await Isolate.spawnUri(dataUri, <String>[], null,
diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart
index 5d6e27d..ecb28d4 100644
--- a/pkg/testing/lib/src/run_tests.dart
+++ b/pkg/testing/lib/src/run_tests.dart
@@ -18,13 +18,7 @@
 
 import 'zone_helper.dart' show runGuarded;
 
-import 'log.dart'
-    show
-        enableVerboseOutput,
-        isVerbose,
-        logMessage,
-        logSuiteComplete,
-        logTestComplete;
+import 'log.dart' show enableVerboseOutput, isVerbose, StdoutLogger;
 
 import 'run.dart' show SuiteRunner, runProgram;
 
@@ -115,7 +109,8 @@
         }
       }
     }
-    logMessage("Reading configuration file '$configurationPath'.");
+    const StdoutLogger()
+        .logMessage("Reading configuration file '$configurationPath'.");
     Uri configuration =
         await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
     if (configuration == null ||
@@ -177,18 +172,21 @@
     withErrorHandling<void>(() async {
       int completed = 0;
       for (String name in tests.keys) {
+        const StdoutLogger()
+            .logTestStart(completed, 0, tests.length, null, null);
         StringBuffer sb = new StringBuffer();
         try {
           await runGuarded(() {
             print("Running test $name");
             return tests[name]();
           }, printLineOnStdout: sb.writeln);
-          logMessage(sb);
+          const StdoutLogger().logMessage(sb);
         } catch (e) {
           print(sb);
           rethrow;
         }
-        logTestComplete(++completed, 0, tests.length, null, null);
+        const StdoutLogger()
+            .logTestComplete(++completed, 0, tests.length, null, null);
       }
-      logSuiteComplete();
+      const StdoutLogger().logSuiteComplete();
     });
diff --git a/pkg/testing/lib/src/zone_helper.dart b/pkg/testing/lib/src/zone_helper.dart
index 5359c2e..e2d106d 100644
--- a/pkg/testing/lib/src/zone_helper.dart
+++ b/pkg/testing/lib/src/zone_helper.dart
@@ -11,7 +11,7 @@
 
 import 'dart:isolate' show Capability, Isolate, ReceivePort;
 
-import 'log.dart' show logUncaughtError;
+import 'log.dart' show StdoutLogger;
 
 Future runGuarded(Future f(),
     {void printLineOnStdout(line),
@@ -26,7 +26,7 @@
   Completer completer = new Completer();
 
   handleUncaughtError(error, StackTrace stackTrace) {
-    logUncaughtError(error, stackTrace);
+    StdoutLogger().logUncaughtError(error, stackTrace);
     if (!completer.isCompleted) {
       completer.completeError(error, stackTrace);
     } else if (handleLateError != null) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index c14d3ab..5303161 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -19,6 +19,8 @@
 import 'package:kernel/external_name.dart'
     show getExternalName, getNativeExtensionUris;
 import 'package:kernel/library_index.dart' show LibraryIndex;
+import 'package:kernel/text/ast_to_text.dart'
+    show globalDebuggingNames, NameSystem;
 import 'package:kernel/type_algebra.dart'
     show Substitution, containsTypeVariable;
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
@@ -75,6 +77,16 @@
       onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
   final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
   libraries ??= component.libraries;
+
+  // Save/restore global NameSystem to avoid accumulating garbage.
+  // NameSystem holds the whole AST as it is strongly connected due to
+  // parent pointers. Objects are added to NameSystem when toString()
+  // is called from AST nodes.  Bytecode generator widely uses
+  // Expression.getStaticType, which calls Expression.getStaticTypeAsInstanceOf,
+  // which uses toString() when it crashes due to http://dartbug.com/34496.
+  final savedGlobalDebuggingNames = globalDebuggingNames;
+  globalDebuggingNames = new NameSystem();
+
   try {
     final bytecodeGenerator = new BytecodeGenerator(
         component, coreTypes, hierarchy, typeEnvironment, options);
@@ -85,6 +97,8 @@
     CompilerContext.current.options.report(
         templateIllegalRecursiveType.withArguments(e.type).withoutLocation(),
         Severity.error);
+  } finally {
+    globalDebuggingNames = savedGlobalDebuggingNames;
   }
 }
 
@@ -2125,7 +2139,8 @@
     asm.emitPushConstant(cp.addType(type));
     _genPushInstantiatorAndFunctionTypeArguments([type]);
     asm.emitPushConstant(cp.addString(name));
-    bool isIntOk = typeEnvironment.isSubtypeOf(typeEnvironment.intType, type);
+    bool isIntOk = typeEnvironment.isSubtypeOf(
+        typeEnvironment.coreTypes.intLegacyRawType, type);
     int subtypeTestCacheCpIndex = cp.addSubtypeTestCache();
     asm.emitAssertAssignable(isIntOk ? 1 : 0, subtypeTestCacheCpIndex);
   }
@@ -4167,7 +4182,7 @@
   final newRepository = new BytecodeMetadataRepository();
   newComponent.addMetadataRepository(newRepository);
 
-  final oldRepository = component.metadata[newRepository.tag];
+  final oldRepository = component.metadata.remove(newRepository.tag);
   final metadata = oldRepository.mapping[component];
   newRepository.mapping[newComponent] = metadata;
 
diff --git a/pkg/vm/lib/bytecode/recognized_methods.dart b/pkg/vm/lib/bytecode/recognized_methods.dart
index 6b776cc..73033b6 100644
--- a/pkg/vm/lib/bytecode/recognized_methods.dart
+++ b/pkg/vm/lib/bytecode/recognized_methods.dart
@@ -47,9 +47,9 @@
 
   DartType staticType(Expression expr) => getStaticType(expr, typeEnv);
 
-  bool isInt(DartType type) => type == typeEnv.intType;
+  bool isInt(DartType type) => type == typeEnv.coreTypes.intLegacyRawType;
 
-  bool isDouble(DartType type) => type == typeEnv.doubleType;
+  bool isDouble(DartType type) => type == typeEnv.coreTypes.doubleLegacyRawType;
 
   Opcode specializedBytecodeFor(MethodInvocation node) {
     final args = node.arguments;
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 13c4908..2b10f69 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -65,6 +65,11 @@
       }
     }
 
+    if (arguments.types.isNotEmpty &&
+        arguments.types.length != func.typeParameters.length) {
+      return false;
+    }
+
     return true;
   }
 
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index 6b47324..c4e6800 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -253,9 +253,9 @@
     if (nativeType is! InterfaceType) {
       return null;
     }
-    InterfaceType native = nativeType;
-    Class nativeClass = native.classNode;
-    NativeType nativeType_ = getType(nativeClass);
+    final InterfaceType native = nativeType;
+    final Class nativeClass = native.classNode;
+    final NativeType nativeType_ = getType(nativeClass);
 
     if (hierarchy.isSubclassOf(nativeClass, structClass)) {
       return allowStructs ? nativeType : null;
@@ -281,17 +281,17 @@
       return null;
     }
 
-    FunctionType fun = native.typeArguments[0];
+    final FunctionType fun = native.typeArguments[0];
     if (fun.namedParameters.isNotEmpty) return null;
     if (fun.positionalParameters.length != fun.requiredParameterCount) {
       return null;
     }
     if (fun.typeParameters.length != 0) return null;
     // TODO(36730): Structs cannot appear in native function signatures.
-    DartType returnType =
+    final DartType returnType =
         convertNativeTypeToDartType(fun.returnType, /*allowStructs=*/ false);
     if (returnType == null) return null;
-    List<DartType> argumentTypes = fun.positionalParameters
+    final List<DartType> argumentTypes = fun.positionalParameters
         .map((t) => convertNativeTypeToDartType(t, /*allowStructs=*/ false))
         .toList();
     if (argumentTypes.contains(null)) return null;
@@ -299,7 +299,7 @@
   }
 
   NativeType getType(Class c) {
-    int index = nativeTypesClasses.indexOf(c);
+    final int index = nativeTypesClasses.indexOf(c);
     if (index == -1) {
       return null;
     }
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index c82b64f..0765dd5 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -128,7 +128,7 @@
     }
 
     // A struct classes "C" must extend "Struct<C>".
-    DartType structTypeArg = node.supertype.typeArguments[0];
+    final DartType structTypeArg = node.supertype.typeArguments[0];
     if (structTypeArg != InterfaceType(node)) {
       diagnosticReporter.report(
           templateFfiWrongStructInheritance.withArguments(node.name),
@@ -147,7 +147,7 @@
 
   bool _checkFieldAnnotations(Class node) {
     bool success = true;
-    for (Field f in node.fields) {
+    for (final Field f in node.fields) {
       if (f.initializer is! NullLiteral) {
         diagnosticReporter.report(
             templateFfiFieldInitializer.withArguments(f.name.name),
@@ -197,8 +197,8 @@
 
     // Constructors cannot have initializers because initializers refer to
     // fields, and the fields were replaced with getter/setter pairs.
-    for (Constructor c in node.constructors) {
-      for (Initializer i in c.initializers) {
+    for (final Constructor c in node.constructors) {
+      for (final Initializer i in c.initializers) {
         if (i is FieldInitializer) {
           toRemove.add(i);
           diagnosticReporter.report(
@@ -210,7 +210,7 @@
       }
     }
     // Remove initializers referring to fields to prevent cascading errors.
-    for (Initializer i in toRemove) {
+    for (final Initializer i in toRemove) {
       i.remove();
     }
 
@@ -235,14 +235,14 @@
     final fields = <Field>[];
     final types = <NativeType>[];
 
-    for (Field f in node.fields) {
+    for (final Field f in node.fields) {
       if (_isPointerType(f)) {
         fields.add(f);
         types.add(NativeType.kPointer);
       } else {
         final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
         if (nativeTypeAnnos.length == 1) {
-          NativeType t = nativeTypeAnnos.first;
+          final NativeType t = nativeTypeAnnos.first;
           fields.add(f);
           types.add(t);
         }
@@ -250,7 +250,7 @@
     }
 
     final sizeAndOffsets = <Abi, SizeAndOffsets>{};
-    for (Abi abi in Abi.values) {
+    for (final Abi abi in Abi.values) {
       sizeAndOffsets[abi] = _calculateSizeAndOffsets(types, abi);
     }
 
@@ -262,7 +262,7 @@
       methods.forEach((p) => node.addMember(p));
     }
 
-    for (Field f in fields) {
+    for (final Field f in fields) {
       f.remove();
     }
 
@@ -391,7 +391,7 @@
   SizeAndOffsets _calculateSizeAndOffsets(List<NativeType> types, Abi abi) {
     int offset = 0;
     final offsets = <int>[];
-    for (NativeType t in types) {
+    for (final NativeType t in types) {
       final int size = _sizeInBytes(t, abi);
       final int alignment = _alignmentOf(t, abi);
       offset = _alignOffset(offset, alignment);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index d7cc4b5..0083c57 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -102,7 +102,7 @@
   visitPropertyGet(PropertyGet node) {
     super.visitPropertyGet(node);
 
-    Procedure replacedWith = replacedGetters[node.interfaceTarget];
+    final Procedure replacedWith = replacedGetters[node.interfaceTarget];
     if (replacedWith != null) {
       node = PropertyGet(node.receiver, replacedWith.name, replacedWith);
     }
@@ -114,7 +114,7 @@
   visitPropertySet(PropertySet node) {
     super.visitPropertySet(node);
 
-    Procedure replacedWith = replacedSetters[node.interfaceTarget];
+    final Procedure replacedWith = replacedSetters[node.interfaceTarget];
     if (replacedWith != null) {
       node = PropertySet(
           node.receiver, replacedWith.name, node.value, replacedWith);
@@ -127,7 +127,7 @@
   visitStaticInvocation(StaticInvocation node) {
     super.visitStaticInvocation(node);
 
-    Member target = node.target;
+    final Member target = node.target;
     try {
       if (target == fromFunctionMethod) {
         final DartType nativeType =
@@ -286,24 +286,24 @@
   visitMethodInvocation(MethodInvocation node) {
     super.visitMethodInvocation(node);
 
-    Member target = node.interfaceTarget;
+    final Member target = node.interfaceTarget;
     try {
       // We will not detect dynamic invocations of 'asFunction' and
       // 'lookupFunction' -- these are handled by the 'asFunctionInternal' stub
       // in 'dynamic_library_patch.dart'. Dynamic invocations of 'asFunction'
       // and 'lookupFunction' are not legal and throw a runtime exception.
       if (target == lookupFunctionMethod) {
-        DartType nativeType =
+        final DartType nativeType =
             InterfaceType(nativeFunctionClass, [node.arguments.types[0]]);
-        DartType dartType = node.arguments.types[1];
+        final DartType dartType = node.arguments.types[1];
 
         _ensureNativeTypeValid(nativeType, node);
         _ensureNativeTypeToDartType(nativeType, dartType, node);
         return _replaceLookupFunction(node);
       } else if (target == asFunctionMethod) {
-        DartType dartType = node.arguments.types[0];
-        DartType pointerType = node.receiver.getStaticType(env);
-        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+        final DartType dartType = node.arguments.types[0];
+        final DartType pointerType = node.receiver.getStaticType(env);
+        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
 
         _ensureNativeTypeValid(pointerType, node);
         _ensureNativeTypeValid(nativeType, node);
@@ -316,9 +316,9 @@
       } else if (target == loadMethod) {
         // TODO(dacoharkes): should load and store be generic?
         // https://github.com/dart-lang/sdk/issues/35902
-        DartType dartType = node.arguments.types[0];
-        DartType pointerType = node.receiver.getStaticType(env);
-        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+        final DartType dartType = node.arguments.types[0];
+        final DartType pointerType = node.receiver.getStaticType(env);
+        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
 
         _ensureNativeTypeValid(pointerType, node);
         _ensureNativeTypeValid(nativeType, node, allowStructs: true);
@@ -328,9 +328,10 @@
       } else if (target == storeMethod) {
         // TODO(dacoharkes): should load and store permitted to be generic?
         // https://github.com/dart-lang/sdk/issues/35902
-        DartType dartType = node.arguments.positional[0].getStaticType(env);
-        DartType pointerType = node.receiver.getStaticType(env);
-        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+        final DartType dartType =
+            node.arguments.positional[0].getStaticType(env);
+        final DartType pointerType = node.receiver.getStaticType(env);
+        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
 
         // TODO(36730): Allow storing an entire struct to memory.
         // TODO(36780): Emit a better error message for the struct case.
@@ -407,7 +408,7 @@
     if (nativeType is! InterfaceType) {
       return false;
     }
-    Class nativeClass = (nativeType as InterfaceType).classNode;
+    final Class nativeClass = (nativeType as InterfaceType).classNode;
     if (env.isSubtypeOf(
         InterfaceType(nativeClass), InterfaceType(pointerClass))) {
       return true;
@@ -415,7 +416,7 @@
     if (hierarchy.isSubclassOf(nativeClass, structClass)) {
       return true;
     }
-    NativeType nativeType_ = getType(nativeClass);
+    final NativeType nativeType_ = getType(nativeClass);
     if (nativeType_ == null) {
       return false;
     }
@@ -465,7 +466,7 @@
   }
 
   void _ensureNotExtendsOrImplementsSealedClass(Class klass) {
-    Class extended = _extendsOrImplementsSealedClass(klass);
+    final Class extended = _extendsOrImplementsSealedClass(klass);
     if (extended != null) {
       diagnosticReporter.report(
           templateFfiExtendsOrImplementsSealedClass
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 75a8332..285b3ac 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -1093,10 +1093,10 @@
 
     // TODO(alexmarkov): handle function types properly
     if (subType is FunctionType) {
-      subType = _typeFlowAnalysis.environment.rawFunctionType;
+      subType = _typeFlowAnalysis.environment.functionLegacyRawType;
     }
     if (superType is FunctionType) {
-      superType = _typeFlowAnalysis.environment.rawFunctionType;
+      superType = _typeFlowAnalysis.environment.functionLegacyRawType;
     }
     // TODO(alexmarkov): handle generic types properly.
     assertx(subType is! TypeParameterType);
@@ -1140,7 +1140,7 @@
 
     // TODO(alexmarkov): handle function types properly
     if (base is FunctionType) {
-      base = _typeFlowAnalysis.environment.rawFunctionType;
+      base = _typeFlowAnalysis.environment.functionLegacyRawType;
     }
 
     if (base is TypeParameterType) {
@@ -1156,7 +1156,7 @@
     // subtypes is too large
 
     if (base == const DynamicType() ||
-        base == _typeFlowAnalysis.environment.objectType ||
+        base == _typeFlowAnalysis.environment.coreTypes.objectLegacyRawType ||
         // TODO(alexmarkov): handle FutureOr more precisely (requires generics).
         baseClass == _typeFlowAnalysis.environment.futureOrClass) {
       return const AnyType();
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index a5d3532..b3e7028 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -710,23 +710,24 @@
       new Type.fromStatic(_staticDartType(node));
 
   Type _cachedBoolType;
-  Type get _boolType =>
-      _cachedBoolType ??= new Type.cone(_environment.boolType);
+  Type get _boolType => _cachedBoolType ??=
+      new Type.cone(_environment.coreTypes.boolLegacyRawType);
 
   Type _cachedDoubleType;
-  Type get _doubleType =>
-      _cachedDoubleType ??= new Type.cone(_environment.doubleType);
+  Type get _doubleType => _cachedDoubleType ??=
+      new Type.cone(_environment.coreTypes.doubleLegacyRawType);
 
   Type _cachedIntType;
-  Type get _intType => _cachedIntType ??= new Type.cone(_environment.intType);
+  Type get _intType =>
+      _cachedIntType ??= new Type.cone(_environment.coreTypes.intLegacyRawType);
 
   Type _cachedStringType;
-  Type get _stringType =>
-      _cachedStringType ??= new Type.cone(_environment.stringType);
+  Type get _stringType => _cachedStringType ??=
+      new Type.cone(_environment.coreTypes.stringLegacyRawType);
 
   Type _cachedSymbolType;
-  Type get _symbolType =>
-      _cachedSymbolType ??= new Type.cone(_environment.symbolType);
+  Type get _symbolType => _cachedSymbolType ??=
+      new Type.cone(_environment.coreTypes.symbolLegacyRawType);
 
   Type _cachedNullType;
   Type get _nullType => _cachedNullType ??= new Type.nullable(new Type.empty());
@@ -968,7 +969,7 @@
       if (node.name.name == 'call') {
         final recvType = _staticDartType(node.receiver);
         if ((recvType is FunctionType) ||
-            (recvType == _environment.rawFunctionType)) {
+            (recvType == _environment.functionLegacyRawType)) {
           // Call to a Function.
           return _staticType(node);
         }
@@ -1192,7 +1193,7 @@
 
   @override
   TypeExpr visitTypeLiteral(TypeLiteral node) {
-    return new Type.cone(_environment.typeType);
+    return new Type.cone(_environment.coreTypes.typeLegacyRawType);
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index a33eb29..f634d26 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -130,7 +130,7 @@
         _unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
         _procedureAttributesMetadata =
             new ProcedureAttributesMetadataRepository(),
-        _intType = _typeFlowAnalysis.environment.intType {
+        _intType = _typeFlowAnalysis.environment.coreTypes.intLegacyRawType {
     component.addMetadataRepository(_inferredTypeMetadata);
     component.addMetadataRepository(_unreachableNodeMetadata);
     component.addMetadataRepository(_procedureAttributesMetadata);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index b679db8..6dc134a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C5
-typedef SomeType<T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
+typedef SomeType<unrelated T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
 abstract class ClassAnnotation2 extends core::Object {
 }
 abstract class MethodAnnotation extends core::Object {
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index 5f9d198..b5f4f08 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -16,6 +16,7 @@
 src/org/dartlang/vm/service/consumer/ReloadReportConsumer.java
 src/org/dartlang/vm/service/consumer/RetainingPathConsumer.java
 src/org/dartlang/vm/service/consumer/ScriptListConsumer.java
+src/org/dartlang/vm/service/consumer/SetFlagConsumer.java
 src/org/dartlang/vm/service/consumer/SourceReportConsumer.java
 src/org/dartlang/vm/service/consumer/StackConsumer.java
 src/org/dartlang/vm/service/consumer/SuccessConsumer.java
diff --git a/pkg/vm_service/lib/vm_service.dart b/pkg/vm_service/lib/vm_service.dart
index 2850348..63ab8a8 100644
--- a/pkg/vm_service/lib/vm_service.dart
+++ b/pkg/vm_service/lib/vm_service.dart
@@ -197,7 +197,7 @@
   'requestHeapSnapshot': const ['Success'],
   'resume': const ['Success'],
   'setExceptionPauseMode': const ['Success'],
-  'setFlag': const ['Success'],
+  'setFlag': const ['Success', 'Error'],
   'setLibraryDebuggable': const ['Success'],
   'setName': const ['Success'],
   'setVMName': const ['Success'],
@@ -767,7 +767,9 @@
   /// value is of the wrong type for the flag.
   ///
   /// The following flags may be set at runtime:
-  Future<Success> setFlag(String name, String value);
+  ///
+  /// The return value can be one of [Success] or [Error].
+  Future<dynamic> setFlag(String name, String value);
 
   /// The `setLibraryDebuggable` RPC is used to enable or disable whether
   /// breakpoints and stepping work for a given library.
@@ -1616,7 +1618,7 @@
   }
 
   @override
-  Future<Success> setFlag(String name, String value) {
+  Future<dynamic> setFlag(String name, String value) {
     return _call('setFlag', {'name': name, 'value': value});
   }
 
diff --git a/pkg/vm_service/test/get_allocation_profile_rpc_test.dart b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
new file mode 100644
index 0000000..4366092
--- /dev/null
+++ b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+import 'common/test_helper.dart';
+
+Future<void> sleep(int milliseconds) =>
+    Future.delayed(Duration(milliseconds: milliseconds));
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolate) async {
+    AllocationProfile result = await service.getAllocationProfile(isolate.id);
+    expect(result.dateLastAccumulatorReset, isNull);
+    expect(result.dateLastServiceGC, isNull);
+    expect(result.members.length, isPositive);
+
+    ClassHeapStats member = result.members[0];
+    expect(member.instancesAccumulated, isNotNull);
+    expect(member.instancesCurrent, isNotNull);
+    expect(member.bytesCurrent, isNotNull);
+    expect(member.accumulatedSize, isNotNull);
+
+    // reset.
+    result = await service.getAllocationProfile(isolate.id, reset: true);
+    final firstReset = result.dateLastAccumulatorReset;
+    expect(firstReset, isNotNull);
+    expect(result.dateLastServiceGC, isNull);
+    expect(result.members.length, isPositive);
+
+    member = result.members[0];
+    expect(member.instancesAccumulated, isNotNull);
+    expect(member.instancesCurrent, isNotNull);
+    expect(member.bytesCurrent, isNotNull);
+    expect(member.accumulatedSize, isNotNull);
+
+    await sleep(1000);
+
+    result = await service.getAllocationProfile(isolate.id, reset: true);
+    final secondReset = result.dateLastAccumulatorReset;
+    expect(secondReset, isNot(firstReset));
+
+    // gc.
+    result = await service.getAllocationProfile(isolate.id, gc: true);
+    expect(result.dateLastAccumulatorReset, secondReset);
+    final firstGC = result.dateLastServiceGC;
+    expect(firstGC, isNotNull);
+    expect(result.members.length, isPositive);
+
+    member = result.members[0];
+    expect(member.instancesAccumulated, isNotNull);
+    expect(member.instancesCurrent, isNotNull);
+    expect(member.bytesCurrent, isNotNull);
+    expect(member.accumulatedSize, isNotNull);
+
+    await sleep(1000);
+
+    result = await service.getAllocationProfile(isolate.id, gc: true);
+    final secondGC = result.dateLastAccumulatorReset;
+    expect(secondGC, isNot(firstGC));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/pkg/vm_service/test/get_flag_list_rpc_test.dart b/pkg/vm_service/test/get_flag_list_rpc_test.dart
new file mode 100644
index 0000000..ada2cfa
--- /dev/null
+++ b/pkg/vm_service/test/get_flag_list_rpc_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+Future getFlagValue(VmService service, String flagName) async {
+  final result = await service.getFlagList();
+  final flags = result.flags;
+  for (final flag in flags) {
+    if (flag.name == flagName) {
+      return flag.valueAsString;
+    }
+  }
+}
+
+var tests = <VMTest>[
+  // Modify a flag which does not exist.
+  (VmService service) async {
+    final result = await service.setFlag('does_not_exist', 'true');
+    expect(result, TypeMatcher<Error>());
+    expect(result.message, 'Cannot set flag: flag not found');
+  },
+
+  // Modify a flag with the wrong value type.
+  (VmService service) async {
+    final result =
+        await service.setFlag('pause_isolates_on_start', 'not-boolean');
+    expect(result, TypeMatcher<Error>());
+    expect(result.message, equals('Cannot set flag: invalid value'));
+  },
+
+  // Modify a flag with the right value type.
+  (VmService service) async {
+    final result = await service.setFlag('pause_isolates_on_start', 'false');
+    expect(result, TypeMatcher<Success>());
+  },
+
+  // Modify a flag which cannot be set at runtime.
+  (VmService service) async {
+    final result = await service.setFlag('random_seed', '42');
+    expect(result, TypeMatcher<Error>());
+    expect(result.message, 'Cannot set flag: cannot change at runtime');
+  },
+
+  // Modify the profile_period at runtime.
+  (VmService service) async {
+    final kProfilePeriod = 'profile_period';
+    final kValue = 100;
+    expect(await getFlagValue(service, kProfilePeriod), '1000');
+    final completer = Completer();
+    final stream = await service.onVMEvent;
+    var subscription;
+    subscription = stream.listen((Event event) {
+      print(event);
+      if (event.kind == EventKind.kVMFlagUpdate) {
+        expect(event.flag, kProfilePeriod);
+        expect(event.newValue, kValue.toString());
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    await service.streamListen(EventStreams.kVM);
+    final result = await service.setFlag(kProfilePeriod, kValue.toString());
+    expect(result, TypeMatcher<Success>());
+    await completer.future;
+    expect(await getFlagValue(service, kProfilePeriod), kValue.toString());
+    await service.streamCancel(EventStreams.kVM);
+  }
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/pkg/vm_service/test/get_memory_usage.dart b/pkg/vm_service/test/get_memory_usage.dart
new file mode 100644
index 0000000..76cac44
--- /dev/null
+++ b/pkg/vm_service/test/get_memory_usage.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+var tests = <VMTest>[
+  (VmService service) async {
+    final vm = await service.getVM();
+    final result = await service.getMemoryUsage(vm.isolates.first.id);
+    expect(result.heapUsage, isPositive);
+    expect(result.heapCapacity, isPositive);
+    expect(result.externalUsage, isPositive);
+  },
+  (VmService service) async {
+    bool caughtException;
+    try {
+      await service.getMemoryUsage('badid');
+      fail('Unreachable');
+    } on RPCError catch (e) {
+      caughtException = true;
+      expect(e.details,
+          contains("getMemoryUsage: invalid 'isolateId' parameter: badid"));
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 4f60c40..6570f8b 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -117,6 +117,23 @@
   }
 }
 
+static_library("elf_loader") {
+  configs += [
+    "..:dart_arch_config",
+    "..:dart_config",
+    "..:dart_product_config",
+    "..:dart_os_fuchsia_config",
+  ]
+  include_dirs = [ ".." ]
+  sources = [
+    "elf_loader.cc",
+    "elf_loader.h",
+  ]
+  deps = [
+    ":libdart_builtin",
+  ]
+}
+
 template("build_gen_snapshot") {
   extra_configs = []
   if (defined(invoker.extra_configs)) {
@@ -841,6 +858,9 @@
     "main.cc",
     "snapshot_empty.cc",
   ]
+
+  extra_deps += [ ":elf_loader" ]
+
   if (dart_runtime_mode == "release") {
     extra_sources += [ "observatory_assets_empty.cc" ]
   }
@@ -862,6 +882,8 @@
     "observatory_assets_empty.cc",
     "snapshot_empty.cc",
   ]
+
+  extra_deps += [ ":elf_loader" ]
 }
 
 executable("process_test") {
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
new file mode 100644
index 0000000..9672dbe
--- /dev/null
+++ b/runtime/bin/elf_loader.cc
@@ -0,0 +1,391 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <bin/elf_loader.h>
+#include <bin/file.h>
+#include <platform/elf.h>
+#include <platform/globals.h>
+#include <vm/cpu.h>
+#include <vm/virtual_memory.h>
+
+#include <memory>
+
+namespace dart {
+namespace bin {
+
+namespace elf {
+
+/// A loader for a subset of ELF which may be used to load objects produced by
+/// Dart_CreateAppAOTSnapshotAsElf.
+class LoadedElf {
+ public:
+  explicit LoadedElf(const char* filename)
+      : filename_(strdup(filename), std::free) {}
+  ~LoadedElf();
+
+  /// Loads the ELF object into memory. Returns whether the load was successful.
+  /// On failure, the error may be retrieved by 'error()'.
+  bool Load();
+
+  /// Reads Dart-specific symbols from the loaded ELF.
+  ///
+  /// Stores the address of the corresponding symbol in each non-null output
+  /// parameter.
+  ///
+  /// Fails if any output parameter is non-null but points to null and the
+  /// corresponding symbol was not found, or if the dynamic symbol table could
+  /// not be decoded.
+  ///
+  /// On failure, the error may be retrieved by 'error()'.
+  bool ResolveSymbols(const uint8_t** vm_data,
+                      const uint8_t** vm_instrs,
+                      const uint8_t** isolate_data,
+                      const uint8_t** isolate_instrs);
+
+  const char* error() { return error_; }
+
+ private:
+  bool ReadHeader();
+  bool ReadProgramTable();
+  bool LoadSegments();
+  bool ReadSectionTable();
+  bool ReadSectionStringTable();
+  bool ReadSections();
+
+  static uword PageSize() { return VirtualMemory::PageSize(); }
+
+  // Unlike File::Map, allows non-aligned 'start' and 'length'.
+  MappedMemory* MapFilePiece(uword start,
+                             uword length,
+                             const void** mapping_start);
+
+  std::unique_ptr<char, decltype(std::free)*> filename_;
+
+  // Initialized on a successful Load().
+  File* file_;
+
+  // Initialized on error.
+  const char* error_ = nullptr;
+
+  // Initialized by ReadHeader().
+  dart::elf::ElfHeader header_;
+
+  // Initialized by ReadProgramTable().
+  std::unique_ptr<MappedMemory> program_table_mapping_;
+  const dart::elf::ProgramHeader* program_table_ = nullptr;
+
+  // Initialized by LoadSegments().
+  std::unique_ptr<VirtualMemory> base_;
+
+  // Initialized by ReadSectionTable().
+  std::unique_ptr<MappedMemory> section_table_mapping_;
+  const dart::elf::SectionHeader* section_table_ = nullptr;
+
+  // Initialized by ReadSectionStringTable().
+  std::unique_ptr<MappedMemory> section_string_table_mapping_;
+  const char* section_string_table_ = nullptr;
+
+  // Initialized by ReadSections().
+  const char* dynamic_string_table_ = nullptr;
+  const dart::elf::Symbol* dynamic_symbol_table_ = nullptr;
+  uword dynamic_symbol_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(LoadedElf);
+};
+
+#define CHECK(value)                                                           \
+  if (!(value)) {                                                              \
+    ASSERT(error_ != nullptr);                                                 \
+    return false;                                                              \
+  }
+
+#define ERROR(message)                                                         \
+  {                                                                            \
+    error_ = (message);                                                        \
+    return false;                                                              \
+  }
+
+#define CHECK_ERROR(value, message)                                            \
+  if (!(value)) {                                                              \
+    error_ = (message);                                                        \
+    return false;                                                              \
+  }
+
+bool LoadedElf::Load() {
+  VirtualMemory::Init();
+
+  if (error_ != nullptr) {
+    return false;
+  }
+
+  file_ = File::Open(/*namespc=*/nullptr, filename_.get(),
+                     bin::File::FileOpenMode::kRead);
+  CHECK_ERROR(file_ != nullptr, "Cannot open ELF object file.");
+
+  CHECK(ReadHeader());
+  CHECK(ReadProgramTable());
+  CHECK(LoadSegments());
+  CHECK(ReadSectionTable());
+  CHECK(ReadSectionStringTable());
+  CHECK(ReadSections());
+
+  return true;
+}
+
+LoadedElf::~LoadedElf() {
+  // Unmap the image.
+  base_.reset();
+
+  // Explicitly destroy all the mappings before closing the file.
+  program_table_mapping_.reset();
+  section_table_mapping_.reset();
+  section_string_table_mapping_.reset();
+
+  if (file_ != nullptr) {
+    file_->Close();
+    file_->Release();
+  }
+}
+
+bool LoadedElf::ReadHeader() {
+  CHECK_ERROR(file_->ReadFully(&header_, sizeof(dart::elf::ElfHeader)),
+              "Could not read ELF file.");
+
+  CHECK_ERROR(header_.ident[dart::elf::EI_DATA] == dart::elf::ELFDATA2LSB,
+              "Expected little-endian ELF object.");
+
+  CHECK_ERROR(header_.type == dart::elf::ET_DYN,
+              "Can only load dynamic libraries.");
+
+#if defined(TARGET_ARCH_IA32)
+  CHECK_ERROR(header_.machine == dart::elf::EM_386, "Architecture mismatch.");
+#elif defined(TARGET_ARCH_X64)
+  CHECK_ERROR(header_.machine == dart::elf::EM_X86_64,
+              "Architecture mismatch.");
+#elif defined(TARGET_ARCH_ARM)
+  CHECK_ERROR(header_.machine == dart::elf::EM_ARM, "Architecture mismatch.");
+#elif defined(TARGET_ARCH_ARM64)
+  CHECK_ERROR(header_.machine == dart::elf::EM_AARCH64,
+              "Architecture mismatch.");
+#else
+#error Unsupported architecture architecture.
+#endif
+
+  CHECK_ERROR(header_.version == dart::elf::EV_CURRENT,
+              "Unexpected ELF version.");
+  CHECK_ERROR(header_.header_size == sizeof(dart::elf::ElfHeader),
+              "Unexpected header size.");
+  CHECK_ERROR(
+      header_.program_table_entry_size == sizeof(dart::elf::ProgramHeader),
+      "Unexpected program header size.");
+  CHECK_ERROR(
+      header_.section_table_entry_size == sizeof(dart::elf::SectionHeader),
+      "Unexpected section header size.");
+
+  return true;
+}
+
+bool LoadedElf::ReadProgramTable() {
+  const uword file_start = header_.program_table_offset;
+  const uword file_length =
+      header_.num_program_headers * sizeof(dart::elf::ProgramHeader);
+  program_table_mapping_.reset(
+      MapFilePiece(file_start, file_length,
+                   reinterpret_cast<const void**>(&program_table_)));
+  CHECK_ERROR(program_table_mapping_ != nullptr,
+              "Could not mmap the program table.");
+  return true;
+}
+
+bool LoadedElf::ReadSectionTable() {
+  const uword file_start = header_.section_table_offset;
+  const uword file_length =
+      header_.num_section_headers * sizeof(dart::elf::SectionHeader);
+  section_table_mapping_.reset(
+      MapFilePiece(file_start, file_length,
+                   reinterpret_cast<const void**>(&section_table_)));
+  CHECK_ERROR(section_table_mapping_ != nullptr,
+              "Could not mmap the section table.");
+  return true;
+}
+
+bool LoadedElf::ReadSectionStringTable() {
+  const dart::elf::SectionHeader header =
+      section_table_[header_.shstrtab_section_index];
+  section_string_table_mapping_.reset(
+      MapFilePiece(header.file_offset, header.file_size,
+                   reinterpret_cast<const void**>(&section_string_table_)));
+  CHECK_ERROR(section_string_table_mapping_ != nullptr,
+              "Could not mmap the section string table.");
+  return true;
+}
+
+bool LoadedElf::LoadSegments() {
+  // Calculate the total amount of virtual memory needed.
+  uword total_memory = 0;
+  for (uword i = 0; i < header_.num_program_headers; ++i) {
+    const dart::elf::ProgramHeader header = program_table_[i];
+
+    // Only PT_LOAD segments need to be loaded.
+    if (header.type != dart::elf::ProgramHeaderType::PT_LOAD) continue;
+
+    total_memory = Utils::Maximum(
+        static_cast<uword>(header.memory_offset + header.memory_size),
+        total_memory);
+    CHECK_ERROR(Utils::IsPowerOfTwo(header.alignment),
+                "Alignment must be a power of two.");
+    CHECK_ERROR(header.alignment <= PageSize(),
+                "Cannot align greater than page size.")
+  }
+  total_memory = Utils::RoundUp(total_memory, PageSize());
+
+  base_.reset(VirtualMemory::AllocateAligned(
+      total_memory, /*alignment=*/PageSize(),
+      /*is_executable=*/false, /*mapping name=*/filename_.get()));
+  CHECK_ERROR(base_ != nullptr, "Could not reserve virtual memory.");
+
+  for (uword i = 0; i < header_.num_program_headers; ++i) {
+    const dart::elf::ProgramHeader header = program_table_[i];
+
+    // Only PT_LOAD segments need to be loaded.
+    if (header.type != dart::elf::ProgramHeaderType::PT_LOAD) continue;
+
+    const uword memory_offset = header.memory_offset,
+                file_offset = header.file_offset;
+    CHECK_ERROR(
+        (memory_offset % PageSize()) == (file_offset % PageSize()),
+        "Difference between file and memory offset must be page-aligned.");
+
+    const intptr_t adjustment = header.memory_offset % PageSize();
+
+    void* const memory_start =
+        static_cast<char*>(base_->address()) + memory_offset - adjustment;
+    const uword file_start = file_offset - adjustment;
+    const uword length = header.memory_size + adjustment;
+
+    File::MapType map_type = File::kReadOnly;
+    if (header.flags == (dart::elf::PF_R | dart::elf::PF_W)) {
+      map_type = File::kReadWrite;
+    } else if (header.flags == (dart::elf::PF_R | dart::elf::PF_X)) {
+      map_type = File::kReadExecute;
+    } else if (header.flags == dart::elf::PF_R) {
+      map_type = File::kReadOnly;
+    } else {
+      ERROR("Unsupported segment flag set.");
+    }
+
+    std::unique_ptr<MappedMemory> memory(
+        file_->Map(map_type, file_start, length, memory_start));
+    CHECK_ERROR(memory != nullptr, "Could not map segment.");
+    CHECK_ERROR(memory->address() == memory_start,
+                "Mapping not at requested address.");
+  }
+
+  return true;
+}
+
+bool LoadedElf::ReadSections() {
+  for (uword i = 0; i < header_.num_section_headers; ++i) {
+    const dart::elf::SectionHeader header = section_table_[i];
+    const char* const name = section_string_table_ + header.name;
+    if (strcmp(name, ".dynstr") == 0) {
+      CHECK_ERROR(header.memory_offset != 0, ".dynstr must be loaded.");
+      dynamic_string_table_ =
+          static_cast<const char*>(base_->address()) + header.memory_offset;
+    } else if (strcmp(name, ".dynsym") == 0) {
+      CHECK_ERROR(header.memory_offset != 0, ".dynsym must be loaded.");
+      dynamic_symbol_table_ = reinterpret_cast<const dart::elf::Symbol*>(
+          base_->start() + header.memory_offset);
+      dynamic_symbol_count_ = header.file_size / sizeof(dart::elf::Symbol);
+    }
+  }
+
+  CHECK_ERROR(dynamic_string_table_ != nullptr, "Couldn't find .dynstr.");
+  CHECK_ERROR(dynamic_symbol_table_ != nullptr, "Couldn't find .dynsym.");
+  return true;
+}
+
+bool LoadedElf::ResolveSymbols(const uint8_t** vm_data,
+                               const uint8_t** vm_instrs,
+                               const uint8_t** isolate_data,
+                               const uint8_t** isolate_instrs) {
+  if (error_ != nullptr) {
+    return false;
+  }
+
+  // The first entry of the symbol table is reserved.
+  for (uword i = 1; i < dynamic_symbol_count_; ++i) {
+    const dart::elf::Symbol sym = dynamic_symbol_table_[i];
+    const char* name = dynamic_string_table_ + sym.name;
+    const uint8_t** output = nullptr;
+
+    if (strcmp(name, kVmSnapshotDataSymbolName) == 0) {
+      output = vm_data;
+    } else if (strcmp(name, kVmSnapshotInstructionsSymbolName) == 0) {
+      output = vm_instrs;
+    } else if (strcmp(name, kIsolateSnapshotDataSymbolName) == 0) {
+      output = isolate_data;
+    } else if (strcmp(name, kIsolateSnapshotInstructionsSymbolName) == 0) {
+      output = isolate_instrs;
+    }
+
+    if (output != nullptr) {
+      *output = reinterpret_cast<const uint8_t*>(base_->start() + sym.value);
+    }
+  }
+
+  CHECK_ERROR(vm_data == nullptr || *vm_data != nullptr,
+              "Could not find VM snapshot data.");
+  CHECK_ERROR(vm_instrs == nullptr || *vm_instrs != nullptr,
+              "Could not find VM snapshot instructions.");
+  CHECK_ERROR(isolate_data == nullptr || *isolate_data != nullptr,
+              "Could not find isolate snapshot data.");
+  CHECK_ERROR(isolate_instrs == nullptr || *isolate_instrs != nullptr,
+              "Could not find isolate instructions.");
+  return true;
+}
+
+MappedMemory* LoadedElf::MapFilePiece(uword file_start,
+                                      uword file_length,
+                                      const void** mem_start) {
+  const uword mapping_offset = Utils::RoundDown(file_start, PageSize());
+  const uword mapping_length =
+      Utils::RoundUp(file_length + file_start % PageSize(), PageSize());
+  MappedMemory* const mapping =
+      file_->Map(bin::File::kReadOnly, mapping_offset, mapping_length);
+
+  if (mapping != nullptr) {
+    *mem_start = reinterpret_cast<uint8_t*>(mapping->start() +
+                                            (file_start % PageSize()));
+  }
+
+  return mapping;
+}
+
+}  // namespace elf
+}  // namespace bin
+}  // namespace dart
+
+DART_EXPORT void* Dart_LoadELF(const char* filename,
+                               const char** error,
+                               const uint8_t** vm_snapshot_data,
+                               const uint8_t** vm_snapshot_instrs,
+                               const uint8_t** vm_isolate_data,
+                               const uint8_t** vm_isolate_instrs) {
+  std::unique_ptr<dart::bin::elf::LoadedElf> elf(
+      new dart::bin::elf::LoadedElf(filename));
+
+  if (!elf->Load() ||
+      !elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
+                           vm_isolate_data, vm_isolate_instrs)) {
+    *error = elf->error();
+    return nullptr;
+  }
+
+  return elf.release();
+}
+
+DART_EXPORT void Dart_UnloadELF(void* loaded) {
+  delete reinterpret_cast<dart::bin::elf::LoadedElf*>(loaded);
+}
diff --git a/runtime/bin/elf_loader.h b/runtime/bin/elf_loader.h
new file mode 100644
index 0000000..b604ee6
--- /dev/null
+++ b/runtime/bin/elf_loader.h
@@ -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.
+
+#ifndef RUNTIME_BIN_ELF_LOADER_H_
+#define RUNTIME_BIN_ELF_LOADER_H_
+
+#include <include/dart_api.h>
+
+typedef void* LoadedElfLibrary;
+
+/// Loads an ELF object in 'filename'.
+///
+/// On success, returns a handle to the library which may be used to close it
+/// in Dart_UnloadELF. On error, returns 'nullptr' and sets 'error'. The error
+/// string should not be 'free'-d.
+///
+/// Looks up the Dart snapshot symbols "_kVmSnapshotData",
+/// "_kVmSnapshotInstructions", "_kVmIsoalteData" and "_kVmIsolateInstructions"
+/// into the respectively named out-parameters.
+DART_EXPORT LoadedElfLibrary Dart_LoadELF(const char* filename,
+                                          const char** error,
+                                          const uint8_t** vm_snapshot_data,
+                                          const uint8_t** vm_snapshot_instrs,
+                                          const uint8_t** vm_isolate_data,
+                                          const uint8_t** vm_isolate_instrs);
+
+DART_EXPORT void Dart_UnloadELF(LoadedElfLibrary loaded);
+
+#endif  // RUNTIME_BIN_ELF_LOADER_H_
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index 1b2f363..32c32a7 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -13,12 +13,6 @@
 namespace dart {
 namespace bin {
 
-const char* kVmSnapshotDataSymbolName = "_kDartVmSnapshotData";
-const char* kVmSnapshotInstructionsSymbolName = "_kDartVmSnapshotInstructions";
-const char* kIsolateSnapshotDataSymbolName = "_kDartIsolateSnapshotData";
-const char* kIsolateSnapshotInstructionsSymbolName =
-    "_kDartIsolateSnapshotInstructions";
-
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
 }
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
index 64df6b6..de71763 100644
--- a/runtime/bin/extensions_fuchsia.cc
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -17,12 +17,6 @@
 namespace dart {
 namespace bin {
 
-const char* kVmSnapshotDataSymbolName = "_kDartVmSnapshotData";
-const char* kVmSnapshotInstructionsSymbolName = "_kDartVmSnapshotInstructions";
-const char* kIsolateSnapshotDataSymbolName = "_kDartIsolateSnapshotData";
-const char* kIsolateSnapshotInstructionsSymbolName =
-    "_kDartIsolateSnapshotInstructions";
-
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
 }
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index d8972a7..e2359d0 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -13,12 +13,6 @@
 namespace dart {
 namespace bin {
 
-const char* kVmSnapshotDataSymbolName = "_kDartVmSnapshotData";
-const char* kVmSnapshotInstructionsSymbolName = "_kDartVmSnapshotInstructions";
-const char* kIsolateSnapshotDataSymbolName = "_kDartIsolateSnapshotData";
-const char* kIsolateSnapshotInstructionsSymbolName =
-    "_kDartIsolateSnapshotInstructions";
-
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
 }
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index 7007f4a..f5436a0 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -13,12 +13,6 @@
 namespace dart {
 namespace bin {
 
-const char* kVmSnapshotDataSymbolName = "kDartVmSnapshotData";
-const char* kVmSnapshotInstructionsSymbolName = "kDartVmSnapshotInstructions";
-const char* kIsolateSnapshotDataSymbolName = "kDartIsolateSnapshotData";
-const char* kIsolateSnapshotInstructionsSymbolName =
-    "kDartIsolateSnapshotInstructions";
-
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
 }
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index 8baf714..d9fecd5 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -13,12 +13,6 @@
 namespace dart {
 namespace bin {
 
-const char* kVmSnapshotDataSymbolName = "_kDartVmSnapshotData";
-const char* kVmSnapshotInstructionsSymbolName = "_kDartVmSnapshotInstructions";
-const char* kIsolateSnapshotDataSymbolName = "_kDartIsolateSnapshotData";
-const char* kIsolateSnapshotInstructionsSymbolName =
-    "_kDartIsolateSnapshotInstructions";
-
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   SetLastError(0);
 
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 928fbdd..eacd0ca 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -24,15 +24,23 @@
 
 class MappedMemory {
  public:
-  MappedMemory(void* address, intptr_t size) : address_(address), size_(size) {}
-  ~MappedMemory() { Unmap(); }
+  MappedMemory(void* address, intptr_t size, bool should_unmap = true)
+      : should_unmap_(should_unmap), address_(address), size_(size) {}
+  ~MappedMemory() {
+    if (should_unmap_) Unmap();
+  }
 
   void* address() const { return address_; }
   intptr_t size() const { return size_; }
+  uword start() const { return reinterpret_cast<uword>(address()); }
 
  private:
   void Unmap();
 
+  // False for mappings which reside inside another, and will be removed when
+  // the outer mapping is removed.
+  bool should_unmap_;
+
   void* address_;
   intptr_t size_;
 
@@ -100,8 +108,30 @@
   enum MapType {
     kReadOnly = 0,
     kReadExecute = 1,
+    kReadWrite = 2,
   };
-  MappedMemory* Map(MapType type, int64_t position, int64_t length);
+
+  /// Maps or copies the file into memory.
+  ///
+  /// 'position' and 'length' should be page-aligned.
+  ///
+  /// If 'start' is zero, allocates virtual memory for the mapping. When the
+  /// returned 'MappedMemory' is destroyed, the mapping is removed.
+  ///
+  /// If 'start' is non-zero, it must point within a suitably sized existing
+  /// mapping. The returned 'MappedMemory' will not remove the mapping when it
+  /// is destroyed; rather, the mapping will be removed when the enclosing
+  /// mapping is removed. This mode is not supported on Fuchsia.
+  ///
+  /// If 'type' is 'kReadWrite', writes to the mapping are *not* copied back to
+  /// the file.
+  ///
+  /// 'position' + 'length' may be larger than the file size. In this case, the
+  /// extra memory is zero-filled.
+  MappedMemory* Map(MapType type,
+                    int64_t position,
+                    int64_t length,
+                    void* start = nullptr);
 
   // Read/Write attempt to transfer num_bytes to/from buffer. It returns
   // the number of bytes read/written.
@@ -172,7 +202,7 @@
   // reading. If mode contains kWrite the file is opened for both
   // reading and writing. If mode contains kWrite and the file does
   // not exist the file is created. The file is truncated to length 0 if
-  // mode contains kTruncate. Assumes we are in an API scope.
+  // mode contains kTruncate.
   static File* Open(Namespace* namespc, const char* path, FileOpenMode mode);
 
   // Same as [File::Open], but attempts to convert uri to path before opening
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index c634b0d..6fa50ad 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -76,7 +76,10 @@
   return handle_->fd() == kClosedFd;
 }
 
-MappedMemory* File::Map(MapType type, int64_t position, int64_t length) {
+MappedMemory* File::Map(MapType type,
+                        int64_t position,
+                        int64_t length,
+                        void* start) {
   ASSERT(handle_->fd() >= 0);
   ASSERT(length > 0);
   int prot = PROT_NONE;
@@ -87,14 +90,16 @@
     case kReadExecute:
       prot = PROT_READ | PROT_EXEC;
       break;
-    default:
-      return NULL;
+    case kReadWrite:
+      prot = PROT_READ | PROT_WRITE;
+      break;
   }
-  void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position);
+  const int flags = MAP_PRIVATE | (start != nullptr ? MAP_FIXED : 0);
+  void* addr = mmap(start, length, prot, flags, handle_->fd(), position);
   if (addr == MAP_FAILED) {
     return NULL;
   }
-  return new MappedMemory(addr, length);
+  return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
 }
 
 void MappedMemory::Unmap() {
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 74e3c50..64cc848 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -75,7 +75,10 @@
   return handle_->fd() == kClosedFd;
 }
 
-MappedMemory* File::Map(MapType type, int64_t position, int64_t length) {
+MappedMemory* File::Map(MapType type,
+                        int64_t position,
+                        int64_t length,
+                        void* start) {
   ASSERT(handle_->fd() >= 0);
   ASSERT(length > 0);
   int prot = PROT_NONE;
@@ -86,14 +89,16 @@
     case kReadExecute:
       prot = PROT_READ | PROT_EXEC;
       break;
-    default:
-      return NULL;
+    case kReadWrite:
+      prot = PROT_READ | PROT_WRITE;
+      break;
   }
-  void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position);
+  const int flags = MAP_PRIVATE | (start != nullptr ? MAP_FIXED : 0);
+  void* addr = mmap(start, length, prot, flags, handle_->fd(), position);
   if (addr == MAP_FAILED) {
     return NULL;
   }
-  return new MappedMemory(addr, length);
+  return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
 }
 
 void MappedMemory::Unmap() {
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index e6db3ad..190b195 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -75,7 +75,10 @@
   return handle_->fd() == kClosedFd;
 }
 
-MappedMemory* File::Map(MapType type, int64_t position, int64_t length) {
+MappedMemory* File::Map(MapType type,
+                        int64_t position,
+                        int64_t length,
+                        void* start) {
   ASSERT(handle_->fd() >= 0);
   ASSERT(length > 0);
   int prot = PROT_NONE;
@@ -86,14 +89,16 @@
     case kReadExecute:
       prot = PROT_READ | PROT_EXEC;
       break;
-    default:
-      return NULL;
+    case kReadWrite:
+      prot = PROT_READ | PROT_WRITE;
+      break;
   }
-  void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position);
+  const int flags = MAP_PRIVATE | (start != nullptr ? MAP_FIXED : 0);
+  void* addr = mmap(start, length, prot, flags, handle_->fd(), position);
   if (addr == MAP_FAILED) {
     return NULL;
   }
-  return new MappedMemory(addr, length);
+  return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
 }
 
 void MappedMemory::Unmap() {
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 7315cfe..2e13282 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -76,7 +76,10 @@
   return handle_->fd() == kClosedFd;
 }
 
-MappedMemory* File::Map(MapType type, int64_t position, int64_t length) {
+MappedMemory* File::Map(MapType type,
+                        int64_t position,
+                        int64_t length,
+                        void* start) {
   ASSERT(handle_->fd() >= 0);
   ASSERT(length > 0);
   int prot = PROT_NONE;
@@ -91,34 +94,58 @@
         map_flags |= (MAP_JIT | MAP_ANONYMOUS);
       }
       break;
-    default:
-      return NULL;
+    case kReadWrite:
+      prot = PROT_READ | PROT_WRITE;
+      break;
   }
-  void* addr = NULL;
+  if (start != nullptr) {
+    map_flags |= MAP_FIXED;
+  }
+  void* addr = start;
   if ((type == kReadExecute) && IsAtLeastOS10_14()) {
-    addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), map_flags, -1, 0);
-    if (addr == MAP_FAILED) {
-      Syslog::PrintErr("mmap failed %s\n", strerror(errno));
-      return NULL;
+    // Due to codesigning restrictions, we cannot map the file as executable
+    // directly. We must first copy it into an anonymous mapping and then mark
+    // the mapping as executable.
+    if (addr == nullptr) {
+      addr = mmap(nullptr, length, (PROT_READ | PROT_WRITE), map_flags, -1, 0);
+      if (addr == MAP_FAILED) {
+        Syslog::PrintErr("mmap failed %s\n", strerror(errno));
+        return nullptr;
+      }
     }
+
+    const int64_t remaining_length = Length() - position;
     SetPosition(position);
-    if (!ReadFully(addr, length)) {
+    if (!ReadFully(addr, Utils::Minimum(length, remaining_length))) {
       Syslog::PrintErr("ReadFully failed\n");
-      munmap(addr, length);
-      return NULL;
+      if (start == nullptr) {
+        munmap(addr, length);
+      }
+      return nullptr;
     }
+
+    // If the requested mapping is larger than the file size, we should fill the
+    // extra memory with zeros.
+    if (length > remaining_length) {
+      memset(reinterpret_cast<uint8_t*>(addr) + remaining_length, 0,
+             length - remaining_length);
+    }
+
     if (mprotect(addr, length, prot) != 0) {
       Syslog::PrintErr("mprotect failed %s\n", strerror(errno));
-      munmap(addr, length);
-      return NULL;
+      if (start == nullptr) {
+        munmap(addr, length);
+      }
+      return nullptr;
     }
   } else {
-    addr = mmap(NULL, length, prot, map_flags, handle_->fd(), position);
+    addr = mmap(addr, length, prot, map_flags, handle_->fd(), position);
+    if (addr == MAP_FAILED) {
+      Syslog::PrintErr("mmap failed %s\n", strerror(errno));
+      return nullptr;
+    }
   }
-  if (addr == MAP_FAILED) {
-    return NULL;
-  }
-  return new MappedMemory(addr, length);
+  return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
 }
 
 void MappedMemory::Unmap() {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index d0011be..f5c6010 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -73,7 +73,10 @@
   return handle_->fd() == kClosedFd;
 }
 
-MappedMemory* File::Map(File::MapType type, int64_t position, int64_t length) {
+MappedMemory* File::Map(File::MapType type,
+                        int64_t position,
+                        int64_t length,
+                        void* start) {
   DWORD prot_alloc;
   DWORD prot_final;
   switch (type) {
@@ -85,31 +88,48 @@
       prot_alloc = PAGE_EXECUTE_READWRITE;
       prot_final = PAGE_EXECUTE_READ;
       break;
-    default:
-      return NULL;
+    case File::kReadWrite:
+      prot_alloc = PAGE_READWRITE;
+      prot_final = PAGE_READWRITE;
+      break;
   }
 
-  void* addr = VirtualAlloc(NULL, length, MEM_COMMIT | MEM_RESERVE, prot_alloc);
-  if (addr == NULL) {
-    Syslog::PrintErr("VirtualAlloc failed %d\n", GetLastError());
-    return NULL;
+  void* addr = start;
+  if (addr == nullptr) {
+    addr = VirtualAlloc(nullptr, length, MEM_COMMIT | MEM_RESERVE, prot_alloc);
+    if (addr == nullptr) {
+      Syslog::PrintErr("VirtualAlloc failed %d\n", GetLastError());
+      return nullptr;
+    }
   }
 
+  const int64_t remaining_length = Length() - position;
   SetPosition(position);
-  if (!ReadFully(addr, length)) {
+  if (!ReadFully(addr, Utils::Minimum(length, remaining_length))) {
     Syslog::PrintErr("ReadFully failed %d\n", GetLastError());
-    VirtualFree(addr, 0, MEM_RELEASE);
-    return NULL;
+    if (start == nullptr) {
+      VirtualFree(addr, 0, MEM_RELEASE);
+    }
+    return nullptr;
+  }
+
+  // If the requested mapping is larger than the file size, we should fill the
+  // extra memory with zeros.
+  if (length > remaining_length) {
+    memset(reinterpret_cast<uint8_t*>(addr) + remaining_length, 0,
+           length - remaining_length);
   }
 
   DWORD old_prot;
   bool result = VirtualProtect(addr, length, prot_final, &old_prot);
   if (!result) {
     Syslog::PrintErr("VirtualProtect failed %d\n", GetLastError());
-    VirtualFree(addr, 0, MEM_RELEASE);
-    return NULL;
+    if (start == nullptr) {
+      VirtualFree(addr, 0, MEM_RELEASE);
+    }
+    return nullptr;
   }
-  return new MappedMemory(addr, length);
+  return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
 }
 
 void MappedMemory::Unmap() {
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 673e556..aceba6c 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -8,6 +8,7 @@
 
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
+#include "bin/elf_loader.h"
 #include "bin/error_exit.h"
 #include "bin/extensions.h"
 #include "bin/file.h"
@@ -20,11 +21,6 @@
 namespace dart {
 namespace bin {
 
-extern const char* kVmSnapshotDataSymbolName;
-extern const char* kVmSnapshotInstructionsSymbolName;
-extern const char* kIsolateSnapshotDataSymbolName;
-extern const char* kIsolateSnapshotInstructionsSymbolName;
-
 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
 static const int64_t kAppSnapshotPageSize = 4 * KB;
 
@@ -179,9 +175,12 @@
   if (!file->ReadFully(&appended_header, sizeof(appended_header))) {
     return nullptr;
   }
+  // Length is always encoded as Little Endian.
+  const uint64_t appended_length =
+      Utils::LittleEndianToHost64(appended_header[0]);
   if (memcmp(&appended_header[1], appjit_magic_number.bytes,
              appjit_magic_number.length) != 0 ||
-      appended_header[0] <= 0 || !file->SetPosition(appended_header[0])) {
+      appended_length <= 0 || !file->SetPosition(appended_length)) {
     return nullptr;
   }
 
@@ -189,6 +188,42 @@
 }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
+
+#if defined(TARGET_OS_WINDOWS) || defined(USING_SIMULATOR)
+class ElfAppSnapshot : public AppSnapshot {
+ public:
+  ElfAppSnapshot(LoadedElfLibrary elf,
+                 const uint8_t* vm_snapshot_data,
+                 const uint8_t* vm_snapshot_instructions,
+                 const uint8_t* isolate_snapshot_data,
+                 const uint8_t* isolate_snapshot_instructions)
+      : elf_(elf),
+        vm_snapshot_data_(vm_snapshot_data),
+        vm_snapshot_instructions_(vm_snapshot_instructions),
+        isolate_snapshot_data_(isolate_snapshot_data),
+        isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
+
+  virtual ~ElfAppSnapshot() { Dart_UnloadELF(elf_); }
+
+  void SetBuffers(const uint8_t** vm_data_buffer,
+                  const uint8_t** vm_instructions_buffer,
+                  const uint8_t** isolate_data_buffer,
+                  const uint8_t** isolate_instructions_buffer) {
+    *vm_data_buffer = vm_snapshot_data_;
+    *vm_instructions_buffer = vm_snapshot_instructions_;
+    *isolate_data_buffer = isolate_snapshot_data_;
+    *isolate_instructions_buffer = isolate_snapshot_instructions_;
+  }
+
+ private:
+  LoadedElfLibrary elf_;
+  const uint8_t* vm_snapshot_data_;
+  const uint8_t* vm_snapshot_instructions_;
+  const uint8_t* isolate_snapshot_data_;
+  const uint8_t* isolate_snapshot_instructions_;
+};
+#endif  // defined(TARGET_OS_WINDOWS) || defined(USING_SIMULATOR)
+
 class DylibAppSnapshot : public AppSnapshot {
  public:
   DylibAppSnapshot(void* library,
@@ -258,17 +293,37 @@
   return new DylibAppSnapshot(library, vm_data_buffer, vm_instructions_buffer,
                               isolate_data_buffer, isolate_instructions_buffer);
 }
+
+static AppSnapshot* TryReadAppSnapshotElf(const char* script_name) {
+#if defined(TARGET_OS_WINDOWS) || defined(USING_SIMULATOR)
+  const char* error = nullptr;
+  const uint8_t *vm_data_buffer = nullptr, *vm_instructions_buffer = nullptr,
+                *isolate_data_buffer = nullptr,
+                *isolate_instructions_buffer = nullptr;
+  void* handle = Dart_LoadELF(script_name, &error, &vm_data_buffer,
+                              &vm_instructions_buffer, &isolate_data_buffer,
+                              &isolate_instructions_buffer);
+  if (handle == nullptr) {
+    Syslog::PrintErr("Loading failed: %s\n", error);
+    return nullptr;
+  }
+  return new ElfAppSnapshot(handle, vm_data_buffer, vm_instructions_buffer,
+                            isolate_data_buffer, isolate_instructions_buffer);
+#else
+  return nullptr;
+#endif
+}
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
 AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_name) {
-  if (File::GetType(NULL, script_name, true) != File::kIsFile) {
+  if (File::GetType(nullptr, script_name, true) != File::kIsFile) {
     // If 'script_name' refers to a pipe, don't read to check for an app
     // snapshot since we cannot rewind if it isn't (and couldn't mmap it in
     // anyway if it was).
-    return NULL;
+    return nullptr;
   }
   AppSnapshot* snapshot = TryReadAppSnapshotBlobs(script_name);
-  if (snapshot != NULL) {
+  if (snapshot != nullptr) {
     return snapshot;
   }
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -284,12 +339,16 @@
 #endif
 
   snapshot = TryReadAppSnapshotDynamicLibrary(script_name);
+  if (snapshot != nullptr) {
+    return snapshot;
+  }
 
-  if (snapshot != NULL) {
+  snapshot = TryReadAppSnapshotElf(script_name);
+  if (snapshot != nullptr) {
     return snapshot;
   }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
-  return NULL;
+  return nullptr;
 }
 
 #if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) && !defined(TESTING)
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 3d060be..d6d34c6 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1113,7 +1113,8 @@
  * the vm isolate on startup and fast initialization of an isolate.
  * A Snapshot of the heap is created before any dart code has executed.
  *
- * Requires there to be a current isolate.
+ * Requires there to be a current isolate. Not available in the precompiled
+ * runtime (check Dart_IsPrecompiledRuntime).
  *
  * \param buffer Returns a pointer to a buffer containing the
  *   snapshot. This buffer is scope allocated and is only valid
@@ -3283,8 +3284,7 @@
  * \return Returns true if the profile is successfully written and false
  *         otherwise.
  */
-DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port,
-                                             char** error);
+DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port, char** error);
 
 /*
  * ====================
@@ -3360,16 +3360,30 @@
                                             const uint8_t* buffer,
                                             intptr_t size);
 
+#if defined(__APPLE__)
+#define kVmSnapshotDataSymbolName "kDartVmSnapshotData"
+#define kVmSnapshotInstructionsSymbolName "kDartVmSnapshotInstructions"
+#define kIsolateSnapshotDataSymbolName "kDartIsolateSnapshotData"
+#define kIsolateSnapshotInstructionsSymbolName                                 \
+  "kDartIsolateSnapshotInstructions"
+#else
+#define kVmSnapshotDataSymbolName "_kDartVmSnapshotData"
+#define kVmSnapshotInstructionsSymbolName "_kDartVmSnapshotInstructions"
+#define kIsolateSnapshotDataSymbolName "_kDartIsolateSnapshotData"
+#define kIsolateSnapshotInstructionsSymbolName                                 \
+  "_kDartIsolateSnapshotInstructions"
+#endif
+
 /**
  *  Creates a precompiled snapshot.
  *   - A root library must have been loaded.
  *   - Dart_Precompile must have been called.
  *
  *  Outputs an assembly file defining the symbols
- *   - kDartVmSnapshotData
- *   - kDartVmSnapshotInstructions
- *   - kDartIsolateSnapshotData
- *   - kDartIsolateSnapshotInstructions
+ *   - _kDartVmSnapshotData
+ *   - _kDartVmSnapshotInstructions
+ *   - _kDartIsolateSnapshotData
+ *   - _kDartIsolateSnapshotInstructions
  *
  *  The assembly should be compiled as a static or shared library and linked or
  *  loaded by the embedder.
@@ -3392,10 +3406,10 @@
  *   - Dart_Precompile must have been called.
  *
  *  Outputs an ELF shared library defining the symbols
- *   - kDartVmSnapshotData
- *   - kDartVmSnapshotInstructions
- *   - kDartIsolateSnapshotData
- *   - kDartIsolateSnapshotInstructions
+ *   - _kDartVmSnapshotData
+ *   - _kDartVmSnapshotInstructions
+ *   - _kDartIsolateSnapshotData
+ *   - _kDartIsolateSnapshotInstructions
  *
  *  The shared library should be dynamically loaded by the embedder.
  *  Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index deec036..24b65e3 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -46,7 +46,7 @@
 
   virtual void VisitIsolate(Isolate* isolate) {
     ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
-    if (IsVMInternalIsolate(isolate)) {
+    if (!FLAG_show_invisible_isolates && IsVMInternalIsolate(isolate)) {
       // We do not register the service (and descendants), the vm-isolate, or
       // the kernel isolate.
       return;
diff --git a/runtime/lib/wasm.cc b/runtime/lib/wasm.cc
index d4f315d..a94aac9 100644
--- a/runtime/lib/wasm.cc
+++ b/runtime/lib/wasm.cc
@@ -17,7 +17,6 @@
 namespace dart {
 
 static void ThrowWasmerError() {
-  TransitionNativeToVM transition(Thread::Current());
   String& error = String::Handle();
   {
     int len = wasmer_last_error_length();
@@ -27,6 +26,7 @@
     error = String::NewFormatted("Wasmer error: %s", raw_error.get());
   }
   Exceptions::ThrowArgumentError(error);
+  UNREACHABLE();
 }
 
 template <typename T>
@@ -107,6 +107,57 @@
   return ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, data, size);
 }
 
+std::ostream& operator<<(std::ostream& o, const wasmer_byte_array& str) {
+  for (uint32_t i = 0; i < str.bytes_len; ++i) {
+    o << str.bytes[i];
+  }
+  return o;
+}
+
+std::ostream& operator<<(std::ostream& o, const wasmer_import_export_kind& io) {
+  switch (io) {
+    case wasmer_import_export_kind::WASM_FUNCTION:
+      return o << "WASM_FUNCTION";
+    case wasmer_import_export_kind::WASM_GLOBAL:
+      return o << "WASM_GLOBAL";
+    case wasmer_import_export_kind::WASM_MEMORY:
+      return o << "WASM_MEMORY";
+    case wasmer_import_export_kind::WASM_TABLE:
+      return o << "WASM_TABLE";
+  }
+}
+
+RawString* DescribeModule(const wasmer_module_t* module) {
+  std::stringstream desc;
+
+  desc << "Imports:\n";
+  wasmer_import_descriptors_t* imports;
+  wasmer_import_descriptors(module, &imports);
+  unsigned num_imports = wasmer_import_descriptors_len(imports);
+  for (unsigned i = 0; i < num_imports; ++i) {
+    wasmer_import_descriptor_t* imp = wasmer_import_descriptors_get(imports, i);
+    desc << "\t" << wasmer_import_descriptor_module_name(imp);
+    desc << "\t" << wasmer_import_descriptor_name(imp);
+    desc << "\t" << wasmer_import_descriptor_kind(imp);
+    desc << "\n";
+  }
+  wasmer_import_descriptors_destroy(imports);
+
+  desc << "\nExports:\n";
+  wasmer_export_descriptors_t* exports;
+  wasmer_export_descriptors(module, &exports);
+  unsigned num_exports = wasmer_export_descriptors_len(exports);
+  for (unsigned i = 0; i < num_exports; ++i) {
+    wasmer_export_descriptor_t* exp = wasmer_export_descriptors_get(exports, i);
+    desc << "\t" << wasmer_export_descriptor_name(exp);
+    desc << "\t" << wasmer_export_descriptor_kind(exp);
+    desc << "\n";
+  }
+  wasmer_export_descriptors_destroy(exports);
+
+  return String::New(desc.str().c_str());
+}
+
 class WasmImports {
  public:
   explicit WasmImports(std::unique_ptr<char[]> module_name)
@@ -183,10 +234,9 @@
     return dart_ret == _ret;
   }
 
-  bool Call(const wasmer_value_t* params, wasmer_value_t* result) {
+  wasmer_result_t 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;
+                                   IsVoid() ? 0 : 1);
   }
 
   void Print(std::ostream& o, const char* name) const {
@@ -380,13 +430,15 @@
   }
 
   wasmer_module_t* module;
+  wasmer_result_t result;
   {
     TransitionVMToNative transition(thread);
-    if (wasmer_compile(&module, data_copy.get(), len) !=
-        wasmer_result_t::WASMER_OK) {
-      data_copy.reset();
-      ThrowWasmerError();
-    }
+    result = wasmer_compile(&module, data_copy.get(), len);
+  }
+  if (result != wasmer_result_t::WASMER_OK) {
+    data_copy.reset();
+    ThrowWasmerError();
+    UNREACHABLE();
   }
 
   mod_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(module));
@@ -396,6 +448,17 @@
   return Object::null();
 }
 
+DEFINE_NATIVE_ENTRY(Wasm_describeModule, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mod_wrap, arguments->NativeArgAt(0));
+
+  ASSERT(mod_wrap.NumNativeFields() == 1);
+
+  wasmer_module_t* module =
+      reinterpret_cast<wasmer_module_t*>(mod_wrap.GetNativeField(0));
+
+  return DescribeModule(module);
+}
+
 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));
@@ -444,6 +507,7 @@
   if (!ToWasmValue(value, type.type_class_id(), &wasm_value)) {
     Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
         "Can't convert dart value to WASM global variable")));
+    UNREACHABLE();
   }
 
   imports->AddGlobal(ToUTF8(name), wasm_value, mutable_.value());
@@ -458,19 +522,19 @@
 
   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) {
+  if (max.IsNull()) {
     descriptor.max.has_some = false;
   } else {
     descriptor.max.has_some = true;
-    descriptor.max.some = max_size;
+    descriptor.max.some = max.AsInt64Value();
   }
   if (wasmer_memory_new(&memory, descriptor) != wasmer_result_t::WASMER_OK) {
     ThrowWasmerError();
+    UNREACHABLE();
   }
   mem_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(memory));
   FinalizablePersistentHandle::New(thread->isolate(), mem_wrap, memory,
@@ -489,6 +553,7 @@
   if (wasmer_memory_grow(memory, delta.AsInt64Value()) !=
       wasmer_result_t::WASMER_OK) {
     ThrowWasmerError();
+    UNREACHABLE();
   }
   return WasmMemoryToExternalTypedData(memory);
 }
@@ -518,6 +583,7 @@
   }
   if (inst == nullptr) {
     ThrowWasmerError();
+    UNREACHABLE();
   }
 
   inst_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(inst));
@@ -560,6 +626,7 @@
 
   if (fn == nullptr) {
     Exceptions::ThrowArgumentError(error);
+    UNREACHABLE();
   }
 
   fn_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(fn));
@@ -579,6 +646,7 @@
     Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
         "Wrong number of args. Expected %" Pu " but found %" Pd ".",
         fn->args().length(), args.Length())));
+    UNREACHABLE();
   }
   auto params = std::unique_ptr<wasmer_value_t[]>(
       new wasmer_value_t[fn->args().length()]);
@@ -588,16 +656,20 @@
       params.reset();
       Exceptions::ThrowArgumentError(String::Handle(
           String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
+      UNREACHABLE();
     }
   }
 
   wasmer_value_t ret;
+  wasmer_result_t result;
   {
     TransitionVMToNative transition(thread);
-    if (!fn->Call(params.get(), &ret)) {
-      params.reset();
-      ThrowWasmerError();
-    }
+    result = fn->Call(params.get(), &ret);
+  }
+  if (result != wasmer_result_t::WASMER_OK) {
+    params.reset();
+    ThrowWasmerError();
+    UNREACHABLE();
   }
   return fn->IsVoid() ? Object::null() : ToDartObject(ret);
 }
@@ -617,6 +689,11 @@
   return nullptr;
 }
 
+DEFINE_NATIVE_ENTRY(Wasm_describeModule, 0, 1) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
 DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
   Exceptions::ThrowUnsupportedError("WASM is disabled");
   return nullptr;
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index fffb41c..e173438 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -2222,8 +2222,8 @@
     if (map['flag'] != null) {
       flag = map['flag'];
     }
-    if (map['new_value'] != null) {
-      newValue = map['new_value'];
+    if (map['newValue'] != null) {
+      newValue = map['newValue'];
     }
   }
 
diff --git a/runtime/observatory/tests/service/breakpoint_non_debuggable_library_test.dart b/runtime/observatory/tests/service/breakpoint_non_debuggable_library_test.dart
new file mode 100644
index 0000000..7656a7b
--- /dev/null
+++ b/runtime/observatory/tests/service/breakpoint_non_debuggable_library_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:path/path.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const String file = 'package:path/path.dart';
+// At join() function
+const int LINE_A = 259;
+// At current getter function
+const int LINE_B = 84;
+
+testMain() {
+  print(join('test', 'test'));
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    // Mark 'package:path/path.dart' as not debuggable.
+    await isolate.reload();
+    Library path =
+        isolate.libraries.firstWhere((Library library) => library.uri == file);
+    await path.load();
+    expect(path.debuggable, true);
+
+    // SetBreakpoint before setting library to non-debuggable.
+    // Breakpoints are allowed to be set (before marking library as non-debuggable) but are not hit when running (after marking library as non-debuggable).
+    Script script = path.scripts.single;
+    Breakpoint bpt = await isolate.addBreakpoint(script, LINE_A);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+
+    // Set breakpoint and check later that this breakpoint won't be added if library is non-debuggable.
+    bpt = await isolate.addBreakpoint(script, LINE_B);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+    await script.reload();
+    // Remove breakpoint.
+    var res = await isolate.removeBreakpoint(bpt);
+    expect(res.type, 'Success');
+
+    var setDebugParams = {
+      'libraryId': path.id,
+      'isDebuggable': false,
+    };
+    Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade(
+        'setLibraryDebuggable', setDebugParams);
+    expect(result['type'], 'Success');
+    await path.reload();
+    expect(path.debuggable, false);
+    print('$path is debuggable: ${path.debuggable}');
+
+    // Breakpoints are not allowed to set on non-debuggable libraries.
+    try {
+      await isolate.addBreakpoint(script, LINE_B);
+    } catch (e) {
+      expect(e is ServerRpcException, true);
+      expect(e.code == ServerRpcException.kCannotAddBreakpoint, true);
+      print("Set Breakpoint to non-debuggable library is not allowed");
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtExit,
+  resumeIsolate
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true, pause_on_exit: true);
diff --git a/runtime/platform/elf.h b/runtime/platform/elf.h
new file mode 100644
index 0000000..729ac7d
--- /dev/null
+++ b/runtime/platform/elf.h
@@ -0,0 +1,170 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_PLATFORM_ELF_H_
+#define RUNTIME_PLATFORM_ELF_H_
+
+#include "platform/globals.h"
+
+namespace dart {
+namespace elf {
+
+#pragma pack(push, 1)
+
+struct ElfHeader {
+  uint8_t ident[16];
+  uint16_t type;
+  uint16_t machine;
+  uint32_t version;
+#if defined(TARGET_ARCH_IS_32_BIT)
+  uint32_t entry_point;
+  uint32_t program_table_offset;
+  uint32_t section_table_offset;
+#else
+  uint64_t entry_point;
+  uint64_t program_table_offset;
+  uint64_t section_table_offset;
+#endif
+  uint32_t flags;
+  uint16_t header_size;
+  uint16_t program_table_entry_size;
+  uint16_t num_program_headers;
+  uint16_t section_table_entry_size;
+  uint16_t num_section_headers;
+  uint16_t shstrtab_section_index;
+};
+
+enum class ProgramHeaderType : uint32_t {
+  PT_LOAD = 1,
+  PT_DYNAMIC = 2,
+  PT_PHDR = 6,
+};
+
+struct ProgramHeader {
+#if defined(TARGET_ARCH_IS_32_BIT)
+  ProgramHeaderType type;
+  uint32_t file_offset;
+  uint32_t memory_offset;
+  uint32_t physical_memory_offset;
+  uint32_t file_size;
+  uint32_t memory_size;
+  uint32_t flags;
+  uint32_t alignment;
+#else
+  ProgramHeaderType type;
+  uint32_t flags;
+  uint64_t file_offset;
+  uint64_t memory_offset;
+  uint64_t physical_memory_offset;
+  uint64_t file_size;
+  uint64_t memory_size;
+  uint64_t alignment;
+#endif
+};
+
+struct SectionHeader {
+#if defined(TARGET_ARCH_IS_32_BIT)
+  uint32_t name;
+  uint32_t type;
+  uint32_t flags;
+  uint32_t memory_offset;
+  uint32_t file_offset;
+  uint32_t file_size;
+  uint32_t link;
+  uint32_t info;
+  uint32_t alignment;
+  uint32_t entry_size;
+#else
+  uint32_t name;
+  uint32_t type;
+  uint64_t flags;
+  uint64_t memory_offset;
+  uint64_t file_offset;
+  uint64_t file_size;
+  uint32_t link;
+  uint32_t info;
+  uint64_t alignment;
+  uint64_t entry_size;
+#endif
+};
+
+struct Symbol {
+#if defined(TARGET_ARCH_IS_32_BIT)
+  uint32_t name;
+  uint32_t value;
+  uint32_t size;
+  uint8_t info;
+  uint8_t other;  // Reserved by ELF.
+  uint16_t section;
+#else
+  uint32_t name;
+  uint8_t info;
+  uint8_t other;  // Reserved by ELF.
+  uint16_t section;
+  uint64_t value;
+  uint64_t size;
+#endif
+};
+
+#pragma pack(pop)
+
+static constexpr intptr_t ELFCLASS32 = 1;
+static constexpr intptr_t ELFCLASS64 = 2;
+
+static const intptr_t EI_DATA = 5;
+static const intptr_t ELFDATA2LSB = 1;
+
+static const intptr_t ELFOSABI_SYSV = 0;
+
+static const intptr_t ET_DYN = 3;
+
+static constexpr intptr_t EF_ARM_ABI_FLOAT_HARD = 0x00000400;
+static constexpr intptr_t EF_ARM_ABI_FLOAT_SOFT = 0x00000200;
+static constexpr intptr_t EF_ARM_ABI = 0x05000000;
+
+static constexpr intptr_t EM_386 = 3;
+static constexpr intptr_t EM_ARM = 40;
+static constexpr intptr_t EM_X86_64 = 62;
+static constexpr intptr_t EM_AARCH64 = 183;
+
+static const intptr_t EV_CURRENT = 1;
+
+static const intptr_t PF_X = 1;
+static const intptr_t PF_W = 2;
+static const intptr_t PF_R = 4;
+
+static const intptr_t SHT_PROGBITS = 1;
+static const intptr_t SHT_STRTAB = 3;
+static const intptr_t SHT_HASH = 5;
+static const intptr_t SHT_DYNSYM = 11;
+static const intptr_t SHT_DYNAMIC = 6;
+
+static const intptr_t SHF_WRITE = 0x1;
+static const intptr_t SHF_ALLOC = 0x2;
+static const intptr_t SHF_EXECINSTR = 0x4;
+
+static const intptr_t SHN_UNDEF = 0;
+
+static const intptr_t STN_UNDEF = 0;
+
+static const intptr_t PT_LOAD = 1;
+static const intptr_t PT_DYNAMIC = 2;
+static const intptr_t PT_PHDR = 6;
+
+static const intptr_t STB_GLOBAL = 1;
+
+static const intptr_t STT_OBJECT = 1;  // I.e., data.
+static const intptr_t STT_FUNC = 2;
+
+static const intptr_t DT_NULL = 0;
+static const intptr_t DT_HASH = 4;
+static const intptr_t DT_STRTAB = 5;
+static const intptr_t DT_SYMTAB = 6;
+static const intptr_t DT_STRSZ = 10;
+static const intptr_t DT_SYMENT = 11;
+
+}  // namespace elf
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_ELF_H_
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 7e7aabe..e0d145b 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -299,11 +299,14 @@
   static uint32_t HostToLittleEndian32(uint32_t host_value);
   static uint64_t HostToLittleEndian64(uint64_t host_value);
 
-  static uint32_t BigEndianToHost32(uint32_t be_value) {
-    // Going between Host <-> BE is the same operation for all practical
-    // purposes.
+  // Going between Host <-> LE/BE is the same operation for all practical
+  // purposes.
+  static inline uint32_t BigEndianToHost32(uint32_t be_value) {
     return HostToBigEndian32(be_value);
   }
+  static inline uint64_t LittleEndianToHost64(uint64_t le_value) {
+    return HostToLittleEndian64(le_value);
+  }
 
   static bool DoublesBitEqual(const double a, const double b) {
     return bit_cast<int64_t, double>(a) == bit_cast<int64_t, double>(b);
diff --git a/runtime/platform/utils_win.h b/runtime/platform/utils_win.h
index ba5c9cc..9df3f6d 100644
--- a/runtime/platform/utils_win.h
+++ b/runtime/platform/utils_win.h
@@ -38,6 +38,8 @@
   return static_cast<int>(result);
 }
 
+// WARNING: The below functions assume host is always Little Endian!
+
 inline uint16_t Utils::HostToBigEndian16(uint16_t value) {
   return _byteswap_ushort(value);
 }
diff --git a/runtime/tests/vm/dart/base_il_serialization_test.dart b/runtime/tests/vm/dart/base_il_serialization_test.dart
index f59b383..569b661 100644
--- a/runtime/tests/vm/dart/base_il_serialization_test.dart
+++ b/runtime/tests/vm/dart/base_il_serialization_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--serialize_flow_graphs_to=il_tmp.txt
+// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --populate_llvm_constant_pool
 // VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types
 // VMOptions=--serialize_flow_graphs_to=il_tmp.txt --verbose_flow_graph_serialization
 // VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types --verbose_flow_graph_serialization
diff --git a/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart b/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart
index b0b2736..1594605 100644
--- a/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart
+++ b/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart
@@ -2,73 +2,57 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:async";
-import "dart:io";
+import 'dart:async';
+import 'dart:io';
 import 'dart:typed_data';
 
-import "package:path/path.dart" as path;
+import 'package:dart2native/dart2native.dart';
+import 'package:path/path.dart' as path;
+import 'package:expect/expect.dart';
 
-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();
-}
+import 'snapshot_test_helper.dart';
 
 Future<void> main(List<String> args) async {
-  if (args.length == 1 && args[0] == "--child") {
-    print("Hello, Appended AOT");
+  if (args.length == 1 && args[0] == '--child') {
+    print('Hello, Appended AOT');
     return;
   }
 
+  final String sourcePath = path.join(
+      'runtime', 'tests', 'vm', 'dart', 'run_appended_aot_snapshot_test.dart');
+
   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 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 result = await generateAotKernel(checkedInDartVM, genKernel,
+          platformDill, sourcePath, dillPath, null, []);
+      Expect.equals(result.stderr, '');
+      Expect.equals(result.exitCode, 0);
+      Expect.equals(result.stdout, '');
+    }
 
-    final aotResult = await runGenSnapshot("generate aot", [
-      "--snapshot-kind=app-aot-blobs",
-      "--blobs_container_filename=$aotPath",
-      dillPath,
-    ]);
-    expectOutput("", aotResult);
+    {
+      final result =
+          await generateAotSnapshot(genSnapshot, dillPath, aotPath, false);
+      Expect.equals(result.stderr, '');
+      Expect.equals(result.exitCode, 0);
+      Expect.equals(result.stdout, '');
+    }
 
     await writeAppendedExecutable(dartPrecompiledRuntime, aotPath, exePath);
 
     if (Platform.isLinux || Platform.isMacOS) {
-      final execResult =
-          await runBinary("make executable", "chmod", ["+x", exePath]);
-      expectOutput("", execResult);
+      final result = await markExecutable(exePath);
+      Expect.equals(result.stderr, '');
+      Expect.equals(result.exitCode, 0);
+      Expect.equals(result.stdout, '');
     }
 
     final runResult =
-        await runBinary("run appended aot snapshot", exePath, ["--child"]);
-    expectOutput("Hello, Appended AOT", runResult);
+        await runBinary('run appended aot snapshot', exePath, ['--child']);
+    expectOutput('Hello, Appended AOT', runResult);
   });
 }
diff --git a/runtime/tests/vm/dart/single_target_and_method_extractors2_test.dart b/runtime/tests/vm/dart/single_target_and_method_extractors2_test.dart
new file mode 100644
index 0000000..09d44a0
--- /dev/null
+++ b/runtime/tests/vm/dart/single_target_and_method_extractors2_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that AOT compiler is correctly handling method extractors
+// when resolving targets of method invocations.
+
+import "package:expect/expect.dart";
+
+abstract class MyQueue<E> {}
+
+class MyListQueue<E> implements MyQueue<E> {
+  String toString() => 'good';
+}
+
+class NextRound {
+  runNextRound() {
+    // During the 2nd iteration of precompilation loop (Precompiler::Iterate)
+    // we're going to discover a call to get:toString() which is only resolved
+    // to Object.get:toString at this time, as MyListQueue.get:toString method
+    // extractor is not created yet. Verify that compiler doesn't use that
+    // target.
+    MyQueue q = new MyListQueue();
+    dynamic x = q.toString;
+    Expect.equals("good", x.call());
+  }
+}
+
+class NextRound2 {
+  runNextRound() {}
+}
+
+getNextRound(i) => i > 5 ? new NextRound() : new NextRound2();
+
+void main() {
+  // During the 1st iteration of precompilation loop (Precompiler::Iterate)
+  // we need to create method extractor for Object.toString.
+  var x = new Object().toString;
+  x.call();
+  // Trigger the next round via new dynamic selector.
+  dynamic y = getNextRound(17);
+  y.runNextRound();
+}
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index 35accd4..162c2e0 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -16,10 +16,13 @@
 
 where
 
-    --help     : prints help and exits
-    --seed     : defines random seed (system-set by default)
-    --[no-]fp  : enables/disables floating-point operations (default: on)
-    --[no-]ffi : enables/disables FFI method calls (default: off)
+    --help      : prints help and exits
+    --seed      : defines random seed (system-set by default)
+    --[no-]fp   : enables/disables floating-point operations (default: on)
+    --[no-]ffi  : enables/disables FFI method calls (default: off)
+    --[no-]mini : enables minimization mode (default: off)
+    --smask     : bitmask indicating which statements to omit (Bit=1 omits, defaults to "0")
+    --emask     : bitmask indicating which expressions to omit (Bit=1 omits, defaults to "0")
 
 The tool provides a runnable main isolate. A typical single
 test run looks as:
diff --git a/runtime/tools/dartfuzz/README_minimize.md b/runtime/tools/dartfuzz/README_minimize.md
new file mode 100644
index 0000000..49d731d
--- /dev/null
+++ b/runtime/tools/dartfuzz/README_minimize.md
@@ -0,0 +1,88 @@
+Minimize
+========
+
+The `minimize.py` script minimizes a program generated by `dartfuzz.dart`.
+
+The Minimization is done in two phases:
+
+1. Minimize statements.
+2. Minimize expressions.
+
+
+### Example
+
+Generate a dart program that triggers a bug:
+
+```
+dart dartfuzz.dart --no-ffi --no-fp --seed 790976770 test.dart
+```
+
+Examine the bug (sample crash shown below):
+
+```
+dart --optimization_counter_threshold=1 test.dart
+
+...
+===== CRASH =====
+si_signo=Segmentation fault(11), si_code=1, si_addr=(nil)
+version=2.6.0-edge.de7ad46797d36a25e6d2800820f61f4af3bd1135 (Wed Sep 11 18:20:46 2019 +0000) on "linux_x64"
+thread=183944, isolate=main(0x559bd215cc00)
+...
+  pc 0x0000559bd0e40a69 fp 0x00007f73d7a7de70 ../../../../sdk/out/ReleaseX64/dart+0x190ca69
+-- End of DumpStackTrace
+```
+
+Pick a keyword identifying the bug in the output, e.g. "Segmentation".
+This will be the `--err` parameter.
+Determine whether the bug is deterministic.
+If not, set the `--tries` parameter such that the number of tries triggers
+the error at least once with high probability.
+
+
+Minimize statements of the generated program:
+
+#### Phase 1
+```
+python3 minimize.py \
+    --dartfuzz "dart dartfuzz.dart --no-ffi --no-fp --seed 790976770" \
+    --dart "dart --optimization_counter_threshold=1" \
+    --testfile mini.dart \
+    --err Segmentation \
+    --tries 4 \
+    --threads 4 \
+    --typ s \
+    --verbose
+
+3fffffffffffffffffffffffffffffffffffffffffffffffff
+error
+7fffffffffffffffffffffffffffffffffffffffffffffffff
+error
+STOP
+Best I could do is 198/198
+dart dartfuzz.dart --no-ffi --no-fp --seed 790976770 mini.dart --mini --smask 0x7fffffffffffffffffffffffffffffffffffffffffffffffff --emask 0
+```
+
+We were able to eliminate all of the statements.
+Taking a look at `mini.dart` we see that function parameters still remain.
+These can be minimized in phase 2.
+
+Minimize expressions of the generated program:
+
+#### Phase 2
+```
+python3 minimize.py \
+    --dartfuzz "dart dartfuzz.dart --no-ffi --no-fp --seed 790976770" \
+    --dart "dart --optimization_counter_threshold=1" \
+    --testfile mini.dart \
+    --err Segmentation \
+    --tries 4 \
+    --threads 4 \
+    --typ e \
+    --verbose \
+    --smask 0x7fffffffffffffffffffffffffffffffffffffffffffffffff
+..
+STOP
+Best I could do is 4626/4628
+dart dartfuzz.dart --no-ffi --no-fp --seed 790976770 mini.dart --mini --smask 0x7fffffffffffffffffffffffffffffffffffffffffffffffff \
+    --emask 0x1ff...ff2ff...fff
+```
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index ba9b779..56730f1 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,7 +14,7 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.49';
+const String version = '1.52';
 
 // Restriction on statements and expressions.
 const int stmtDepth = 1;
@@ -23,7 +23,6 @@
 const int numGlobalVars = 4;
 const int numLocalVars = 4;
 const int numGlobalMethods = 4;
-const int numClassMethods = 3;
 const int numMethodParams = 4;
 const int numClasses = 4;
 
@@ -115,7 +114,8 @@
 
 /// Class that generates a random, but runnable Dart program for fuzz testing.
 class DartFuzz {
-  DartFuzz(this.seed, this.fp, this.ffi, this.file);
+  DartFuzz(this.seed, this.fp, this.ffi, this.file,
+      {this.minimize = false, this.smask, this.emask});
 
   void run() {
     // Initialize program variables.
@@ -124,6 +124,8 @@
     nest = 0;
     currentClass = null;
     currentMethod = null;
+    // Setup minimization parameters.
+    initMinimization();
     // Setup the library and ffi api.
     api = DartApi(ffi);
     // Setup the types.
@@ -135,6 +137,7 @@
     globalMethods =
         fillTypes2(limit2: numGlobalMethods, limit1: numMethodParams);
     classFields = fillTypes2(limit2: numClasses, limit1: numLocalVars);
+    final int numClassMethods = 1 + numClasses - classFields.length;
     classMethods = fillTypes3(classFields.length,
         limit2: numClassMethods, limit1: numMethodParams);
 
@@ -165,6 +168,135 @@
   }
 
   //
+  // Minimization components.
+  //
+
+  void initMinimization() {
+    stmtCntr = 0;
+    exprCntr = 0;
+    skipStmt = false;
+    skipExpr = false;
+  }
+
+  void emitMinimizedLiteral(DartType tp) {
+    switch (tp) {
+      case DartType.BOOL:
+        emit('true');
+        break;
+      case DartType.INT:
+        emit('1');
+        break;
+      case DartType.DOUBLE:
+        emit('1.0');
+        break;
+      case DartType.STRING:
+        emit('"a"');
+        break;
+      case DartType.INT_LIST:
+        emit('[1]');
+        break;
+      case DartType.INT_SET:
+        emit('{1}');
+        break;
+      case DartType.INT_STRING_MAP:
+        emit('{1: "a"}');
+        break;
+      default:
+        throw 'Unknown DartType ${tp}';
+    }
+  }
+
+  BigInt genMask(int m) => BigInt.from(1) << m;
+
+  // Process the opening of a statement.
+  // Determine whether the statement should be skipped based on the
+  // statement index stored in stmtCntr and the statement mask stored
+  // in smask.
+  // Returns true if the statement should be skipped.
+  bool processStmtOpen() {
+    // Do nothing if we are not in minimization mode.
+    if (!minimize) {
+      return false;
+    }
+    // Check whether the bit for the current statement number is set in the
+    // statement bitmap. If so skip this statement.
+    final newMask = genMask(stmtCntr);
+    final maskBitSet = (smask & newMask) != BigInt.zero;
+    // Statements are nested, therefore masking one statement like e.g.
+    // a for loop leads to other statements being omitted.
+    // Here we update the statement mask to include the additionally
+    // omitted statements.
+    if (skipStmt) {
+      smask |= newMask;
+    }
+    // Increase the statement counter.
+    stmtCntr++;
+    if (!skipStmt && maskBitSet) {
+      skipStmt = true;
+      return true;
+    }
+    return false;
+  }
+
+  // Process the closing of a statement.
+  // The variable resetSkipStmt indicates whether this
+  // statement closes the sequence of skipped statement.
+  // E.g. the end of a loop where all contained statements
+  // were skipped.
+  void processStmtClose(bool resetSkipStmt) {
+    if (!minimize) {
+      return;
+    }
+    if (resetSkipStmt) {
+      skipStmt = false;
+    }
+  }
+
+  // Process the opening of an expression.
+  // Determine whether the expression should be skipped based on the
+  // expression index stored in exprCntr and the expression mask stored
+  // in emask.
+  // Returns true is the expression is skipped.
+  bool processExprOpen(DartType tp) {
+    // Do nothing if we are not in minimization mode.
+    if (!minimize) {
+      return false;
+    }
+    // Check whether the bit for the current expression number is set in the
+    // expression bitmap. If so skip this expression.
+    final newMask = genMask(exprCntr);
+    final maskBitSet = (emask & newMask) != BigInt.zero;
+    // Expressions are nested, therefore masking one expression like e.g.
+    // a for loop leads to other expressions being omitted.
+    // Similarly, if the whole statement is skipped, all the expressions
+    // within that statement are implicitly masked.
+    // Here we update the expression mask to include the additionally
+    // omitted expressions.
+    if (skipExpr || skipStmt) {
+      emask |= newMask;
+    }
+    exprCntr++;
+    if (skipStmt) {
+      return false;
+    }
+    if (!skipExpr && maskBitSet) {
+      emitMinimizedLiteral(tp);
+      skipExpr = true;
+      return true;
+    }
+    return false;
+  }
+
+  void processExprClose(bool resetExprStmt) {
+    if (!minimize || skipStmt) {
+      return;
+    }
+    if (resetExprStmt) {
+      skipExpr = false;
+    }
+  }
+
+  //
   // Program components.
   //
 
@@ -346,6 +478,11 @@
     tryBody();
     emit(";", newline: true);
     indent -= 2;
+    emitLn('} on OutOfMemoryError {');
+    indent += 2;
+    emitLn("print(\'oom\');");
+    emitLn("exit(${oomExitCode});");
+    indent -= 2;
     emitLn('} catch (e, st) {');
     indent += 2;
     catchBody();
@@ -731,9 +868,8 @@
     return true;
   }
 
-  // Emit a statement. Returns true if code *may* fall-through
-  // (not made too advanced to avoid FE complaints).
-  bool emitStatement(int depth) {
+  // Emit a single statement.
+  bool emitSingleStatement(int depth) {
     // Throw in a comment every once in a while.
     if (rand.nextInt(10) == 0) {
       emitComment();
@@ -778,6 +914,16 @@
     }
   }
 
+  // Emit a statement (main entry).
+  // Returns true if code *may* fall-through
+  // (not made too advanced to avoid FE complaints).
+  bool emitStatement(int depth) {
+    final resetSkipStmt = processStmtOpen();
+    bool ret = emitSingleStatement(depth);
+    processStmtClose(resetSkipStmt);
+    return ret;
+  }
+
   // Emit statements. Returns true if code may fall-through.
   bool emitStatements(int depth) {
     int s = 1 + rand.nextInt(numStatements);
@@ -869,7 +1015,7 @@
 
   void emitCollectionElement(int depth, DartType tp, {RhsFilter rhsFilter}) {
     int r = depth <= exprDepth ? rand.nextInt(10) : 10;
-    switch (r) {
+    switch (r + 3) {
       // Favors elements over control-flow collections.
       case 0:
         // TODO (ajcbik): Remove restriction once compiler is fixed.
@@ -958,7 +1104,9 @@
     } else if (tp == DartType.INT_LIST ||
         tp == DartType.INT_SET ||
         tp == DartType.INT_STRING_MAP) {
+      final resetExprStmt = processExprOpen(tp);
       emitCollection(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
+      processExprClose(resetExprStmt);
     } else {
       assert(false);
     }
@@ -1231,35 +1379,38 @@
 
   // Emit expression.
   void emitExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
+    final resetExprStmt = processExprOpen(tp);
     // Continuing nested expressions becomes less likely as the depth grows.
     if (rand.nextInt(depth + 1) > exprDepth) {
       emitTerminal(depth, tp, rhsFilter: rhsFilter);
-      return;
+    } else {
+      // Possibly nested expression.
+      switch (rand.nextInt(7)) {
+        case 0:
+          emitUnaryExpr(depth, tp, rhsFilter: rhsFilter);
+          break;
+        case 1:
+          emitBinaryExpr(depth, tp, rhsFilter: rhsFilter);
+          break;
+        case 2:
+          emitTernaryExpr(depth, tp, rhsFilter: rhsFilter);
+          break;
+        case 3:
+          emitPreOrPostExpr(depth, tp, rhsFilter: rhsFilter);
+          break;
+        case 4:
+          emitLibraryCall(depth, tp,
+              rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
+          break;
+        case 5:
+          emitMethodCall(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
+          break;
+        default:
+          emitTerminal(depth, tp, rhsFilter: rhsFilter);
+          break;
+      }
     }
-    // Possibly nested expression.
-    switch (rand.nextInt(7)) {
-      case 0:
-        emitUnaryExpr(depth, tp, rhsFilter: rhsFilter);
-        break;
-      case 1:
-        emitBinaryExpr(depth, tp, rhsFilter: rhsFilter);
-        break;
-      case 2:
-        emitTernaryExpr(depth, tp, rhsFilter: rhsFilter);
-        break;
-      case 3:
-        emitPreOrPostExpr(depth, tp, rhsFilter: rhsFilter);
-        break;
-      case 4:
-        emitLibraryCall(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
-        break;
-      case 5:
-        emitMethodCall(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
-        break;
-      default:
-        emitTerminal(depth, tp, rhsFilter: rhsFilter);
-        break;
-    }
+    processExprClose(resetExprStmt);
   }
 
   //
@@ -1522,6 +1673,9 @@
 
   // Emits text to append to program.
   void emit(String txt, {bool newline = false}) {
+    if (skipStmt || skipExpr) {
+      return;
+    }
     file.writeStringSync(txt);
     if (newline) {
       file.writeStringSync('\n');
@@ -1533,6 +1687,9 @@
     return choices[rand.nextInt(choices.length)];
   }
 
+  // Special return code to handle oom errors.
+  static const oomExitCode = 254;
+
   // Random seed used to generate program.
   final int seed;
 
@@ -1581,6 +1738,16 @@
 
   // Parent class indices for all classes.
   List<int> classParents;
+
+  // Minimization mode extensions.
+  final bool minimize;
+  BigInt smask;
+  BigInt emask;
+  bool skipStmt;
+  bool skipExpr;
+  bool skipExprCntr;
+  int stmtCntr;
+  int exprCntr;
 }
 
 // Generate seed. By default (no user-defined nonzero seed given),
@@ -1604,15 +1771,49 @@
         help: 'random seed (0 forces time-based seed)', defaultsTo: '0')
     ..addFlag('fp', help: 'enables floating-point operations', defaultsTo: true)
     ..addFlag('ffi',
-        help: 'enables FFI method calls (default: off)', defaultsTo: false);
+        help: 'enables FFI method calls (default: off)', defaultsTo: false)
+    // Minimization mode extensions.
+    ..addFlag('mini',
+        help: 'enables minimization mode (default: off)', defaultsTo: false)
+    ..addOption('smask',
+        help: 'Bitmask indicating which statements to omit'
+            '(Bit=1 omits)',
+        defaultsTo: '0')
+    ..addOption('emask',
+        help: 'Bitmask indicating which expressions to omit'
+            '(Bit=1 omits)',
+        defaultsTo: '0');
   try {
     final results = parser.parse(arguments);
     final seed = getSeed(results['seed']);
     final fp = results['fp'];
     final ffi = results['ffi'];
     final file = File(results.rest.single).openSync(mode: FileMode.write);
-    DartFuzz(seed, fp, ffi, file).run();
+    final minimize = results['mini'];
+    final smask = BigInt.parse(results['smask']);
+    final emask = BigInt.parse(results['emask']);
+    final dartFuzz = DartFuzz(seed, fp, ffi, file,
+        minimize: minimize, smask: smask, emask: emask);
+    dartFuzz.run();
     file.closeSync();
+    // Print information that will be parsed by minimize.py
+    if (minimize) {
+      // Updated statement mask.
+      // This might be different from the input parameter --smask
+      // since masking a statement that contains nested statements leads to
+      // those being masked as well.
+      print(dartFuzz.smask.toRadixString(10));
+      // Total number of statements in the generated program.
+      print(dartFuzz.stmtCntr);
+      // Updated expression mask.
+      // This might be different from the input parameter --emask
+      // since masking a statement that contains expressions or
+      // an expression that contains nested expressions leads to
+      // those being masked as well.
+      print(dartFuzz.emask.toRadixString(10));
+      // Total number of expressions in the generated program.
+      print(dartFuzz.exprCntr);
+    }
   } catch (e) {
     print('Usage: dart dartfuzz.dart [OPTIONS] FILENAME\n${parser.usage}\n$e');
     exitCode = 255;
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index c1fcbe7..dc61138 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -13,6 +13,7 @@
 const debug = false;
 const sigkill = 9;
 const timeout = 60; // in seconds
+const dartHeapSize = 128; // in Mb
 
 // Status of divergence report.
 enum ReportStatus { reported, ignored, rerun, no_divergence }
@@ -155,7 +156,12 @@
       this.fileName, List<String> extraFlags) {
     description = '$prefix-$tag';
     dart = '$top/out/$tag/dart';
-    cmd = [dart, ...extraFlags, fileName];
+    cmd = [
+      dart,
+      ...extraFlags,
+      '--old_gen_heap_size=${dartHeapSize}',
+      fileName
+    ];
   }
 
   TestResult run() {
@@ -189,7 +195,8 @@
     if (result.exitCode != 0) {
       return result;
     }
-    return runCommand([dart, snapshot], env);
+    return runCommand(
+        [dart, '--old_gen_heap_size=${dartHeapSize}', snapshot], env);
   }
 
   void printReproductionCommand() {
@@ -214,12 +221,17 @@
     description = '$prefix-$tag';
     dart = '$top/out/$tag/dart';
     if (kbcSrc) {
-      cmd = [dart, ...extraFlags, fileName];
+      cmd = [
+        dart,
+        ...extraFlags,
+        '--old_gen_heap_size=${dartHeapSize}',
+        fileName
+      ];
     } else {
       generate = '$top/pkg/vm/tool/gen_kernel';
       platform = '--platform=$top/out/$tag/vm_platform_strong.dill';
       dill = '$tmp/out.dill';
-      cmd = [dart, ...extraFlags, dill];
+      cmd = [dart, ...extraFlags, '--old_gen_heap_size=${dartHeapSize}', dill];
     }
   }
 
@@ -445,11 +457,17 @@
       // Divergence in result code.
       if (trueDivergence) {
         // When only true divergences are requested, any divergence
-        // with at least one time out is treated as a regular time out.
+        // with at least one time out or out of memory error is
+        // treated as a regular time out or skipped test, respectively.
         if (result1.exitCode == -sigkill || result2.exitCode == -sigkill) {
           numTimeout++;
           timeoutSeeds.add(seed);
           return ReportStatus.ignored;
+        } else if (result1.exitCode == DartFuzz.oomExitCode ||
+            result2.exitCode == DartFuzz.oomExitCode) {
+          numSkipped++;
+          skippedSeeds.add(seed);
+          return ReportStatus.ignored;
         }
       }
       reportDivergence(result1, result2);
diff --git a/runtime/tools/dartfuzz/minimize.py b/runtime/tools/dartfuzz/minimize.py
new file mode 100755
index 0000000..c9be86a
--- /dev/null
+++ b/runtime/tools/dartfuzz/minimize.py
@@ -0,0 +1,414 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+"""
+This script minimizes a program generated by dartfuzz.dart.
+"""
+
+import argparse
+import multiprocessing as mp
+import re
+import shlex
+import subprocess
+
+STATEMENT_MASK_LINE = 0
+STATEMENT_NUMBER_LINE = 1
+EXPRESSION_MASK_LINE = 2
+EXPRESSION_NUMBER_LINE = 3
+
+
+class MaskGen(object):
+    """
+    Generates bitpatterns of <nbits> bits which indicate which
+    statements or expressions should be masked when passed as the
+    --smask or --emask parameter to dartfuzz.dart.
+    The patterns are generated in the following manner:
+    11111111111111111111111111111111
+    11111111111111110000000000000000
+    00000000000000001111111111111111
+    11111111111111111111111100000000
+    11111111111111110000000011111111
+    11111111000000001111111111111111
+    00000000111111111111111111111111
+    ...
+    If the error persists with a given a pattern it is stored in the
+    parameter <mask>.
+    """
+
+    def __init__(self, nbits, mask):
+        # Mask bitlength.
+        self.nbits = nbits
+        # Mask determining which statements or expressions to skip.
+        self.mask = mask
+        # Current mask modification start index.
+        self.convolution_idx = 0
+        # Max mask with all bits set to 1.
+        self.max = (1 << (nbits + 1)) - 1
+        # Current number of bits set in the mask modification mask.
+        self.nbitsVar = int(nbits)
+        # Current mask modification mask.
+        # This will be folded over the current value of self.mask
+        # starting from 0.
+        self.filter_mask = (1 << self.nbitsVar) - 1
+        # All the masks already tested.
+        self.tested = set()
+        self.gen_new_mask = False
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        return self.next()
+
+    # Update the set of tested masks.
+    # This is used to keep track of tested masks that did not produce a crash.
+    def update_tested(self, new_mask):
+        self.tested.add(new_mask)
+
+    # Update the current mask with the new mask that produced a crash.
+    # Note: We assume that if mask
+    # 11110000 produces a crash and
+    # 00000011 produces a crash that
+    # 11110011 will also produce a crash.
+    # This might not be true for some cases.
+    def update_mask(self, new_mask):
+        new_mask = (self.mask | new_mask) & self.max
+        self.mask = new_mask
+
+    # Count the bits of the current mask.
+    # More bits mean more statements omitted, so this is used
+    # to determine the quality of the current mask.
+    def count_bits(self):
+        return bin(self.mask).count('1')
+
+    def inc_var(self):
+        self.convolution_idx = 0
+        self.nbitsVar = self.nbitsVar >> 1
+        self.filter_mask = (1 << self.nbitsVar) - 1
+        return self.filter_mask == 0
+
+    def stop(self):
+        if self.convolution_idx >= self.nbits and self.inc_var() > 0:
+            # Check if the last run generated a new mask.
+            if self.gen_new_mask:
+                # Restart mask generation from beginning.
+                self.nbitsVar = self.nbits >> 1
+                self.inc_var()
+                self.gen_new_mask = False
+                return False
+            print("STOP")
+            return True
+        return False
+
+    def next(self):
+        while not self.stop():
+            # Generate a new mask according to the mask generation algorithm.
+            new_mask = (self.mask |
+                        (self.filter_mask << self.convolution_idx)) & self.max
+            # Update the counter variable for the mask generation algorithm.
+            self.convolution_idx += self.nbitsVar
+            # If the new_mask has new bits and has not been tested yet.
+            # We need to check both because only masks that produce an
+            # error are merged into self.mask.
+            if new_mask != self.mask and \
+                new_mask not in self.tested:
+                # Add new mask to the set of tested masks.
+                self.tested.add(new_mask)
+                # Mark that we generated a new mask on this run.
+                self.gen_new_mask = True
+                # Return the new mask to be tested.
+                return new_mask
+        raise StopIteration()
+
+
+# Generate a Dart program for the given statement (smask) and
+# expression (emask) masks. Dartfuzz parameters for seed, ffi and
+# fp are static and therefore contained in the dartfuzz_cmd parameter.
+def generate_dart(dartfuzz_cmd, dart_test, smask, mask, do_expr):
+    if do_expr:
+        # Minimizing expressions.
+        cmds = shlex.split(dartfuzz_cmd) + [dart_test] + \
+            ['--mini', '--smask', '%d' % smask, '--emask', '%d' % mask]
+        p = subprocess.Popen(cmds, stdout=subprocess.PIPE)
+    else:
+        # Minimizing statements.
+        cmds = shlex.split(dartfuzz_cmd) + [dart_test] + \
+            ['--mini', '--smask', '%d' % mask]
+        p = subprocess.Popen(cmds, stdout=subprocess.PIPE)
+    p_stdout, p_stderr = p.communicate()
+    if p.returncode != 0:
+        raise 'Invalid return code on generate %d' % p.returncode
+    mask_new = 0
+    if do_expr:
+        mask_new = int(p_stdout.decode().splitlines()[EXPRESSION_MASK_LINE])
+    else:
+        mask_new = int(p_stdout.decode().splitlines()[STATEMENT_MASK_LINE])
+    return mask_new
+
+
+# Run the Dart program and check for error (by matching error_match_p).
+def run_dart(dart_cmd, dart_test, error_match_p, timeout):
+    cmd = ['timeout', str(timeout)] + shlex.split(dart_cmd) + [dart_test]
+    p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+    p_stdout, p_stderr = p.communicate()
+    if error_match_p.search(p_stdout.decode()) or \
+        error_match_p.search(p_stderr.decode()):
+        return True
+    if p.returncode != 0:
+        print("Warning: error return code %d" % p.returncode)
+    return False
+
+
+# Run multiple tries of the given dart_cmd and check for errors by matching
+# against error_match_p.
+def run_dart_mp(dart_cmd, dart_test, error_match_p, tries, nthreads, timeout):
+    if tries == 1:
+        return run_dart(dart_cmd, dart_test, error_match_p, timeout)
+    pool = mp.Pool(nthreads)
+    results = [
+        pool.apply_async(run_dart,
+                         (dart_cmd, dart_test, error_match_p, timeout))
+        for i in range(tries)
+    ]
+    worker_done = [False for i in range(tries)]
+    while True:
+        all_done = True
+        for i, result in enumerate(results):
+            if worker_done[i]:
+                continue
+            try:
+                r = result.get(timeout=0.5)
+                worker_done[i] = True
+                if r:
+                    pool.close()
+                    pool.terminate()
+                    pool.join()
+                    return True
+            except mp.TimeoutError:
+                all_done = False
+        if all_done:
+            break
+    pool.close()
+    pool.join()
+    return False
+
+
+def minimize(dartfuzz_cmd,
+             dart_cmd,
+             dart_cmd_ref,
+             dart_test,
+             error_match1,
+             error_match2,
+             smask,
+             emask,
+             do_expr,
+             verbose,
+             tries,
+             tries_ref,
+             threads,
+             timeout,
+             print_every=32):
+    # Run dartfuzz command once to get the total number of statements
+    # and expressions in the generated program.
+    # Output will look like this:
+    # <Current Statement Mask>
+    # <Number of Statements>
+    # <Current Expression Mask>
+    # <Number of Expressions>
+    p = subprocess.Popen(
+        dartfuzz_cmd + " --mini " + dart_test,
+        shell=True,
+        stdout=subprocess.PIPE)
+    p_stdout, p_stderr = p.communicate()
+    if do_expr:
+        # Minimizing expressions.
+        nstmts = int(p_stdout.decode().splitlines()[EXPRESSION_NUMBER_LINE])
+        mask_gen = MaskGen(nstmts, emask)
+    else:
+        # Minimizing statements.
+        nstmts = int(p_stdout.decode().splitlines()[STATEMENT_NUMBER_LINE])
+        mask_gen = MaskGen(nstmts, smask)
+    # Best mask found so far.
+    min_mask = 0
+    # Maximum number of statements or expressions masked.
+    max_bits = 0
+    # Count number of iterations.
+    cntr = 0
+    # Result of the last run.
+    last_err = True
+    # Compile pattern to match standard output and error for a string
+    # identifying the crash.
+    error_match_p1 = re.compile(error_match1)
+    error_match_p2 = None
+    if error_match2 is not None:
+        error_match_p2 = re.compile(error_match2)
+    for mask in mask_gen:
+        if (verbose):
+            print("Mask: %x" % mask)
+        cntr += 1
+        if cntr % print_every == 0:
+            cntr = 0
+            print("Best I could do so far is mask %d/%d" \
+                  % (max_bits, nstmts))
+            if do_expr:
+                print(dartfuzz_cmd + " " + dart_test +
+                      " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
+            else:
+                print(dartfuzz_cmd + " " + dart_test +
+                      " --mini --smask 0x%x --emask 0" % (min_mask))
+        # The return value mask_new contains the actual mask applied by
+        # dartfuzz. Due to nesting, masking one statement might lead to other
+        # statements being masked as well; mask_new will contain this updated
+        # mask.
+        mask_new = generate_dart(dartfuzz_cmd, dart_test, smask, mask, do_expr)
+        # Run generated Dart program and check for error.
+        err = run_dart_mp(dart_cmd, dart_test, error_match_p1, tries, threads,
+                          timeout)
+        if err and verbose:
+            print("Matched error 1 " + error_match1)
+        err_ref = True
+        if (dart_cmd_ref is not None) and (error_match_p2 is not None):
+            err_ref = run_dart_mp(dart_cmd_ref, dart_test, error_match_p2,
+                                  tries_ref, threads, timeout)
+            if err_ref and verbose:
+                print("Matched error 2 " + error_match2)
+        if err and err_ref:
+            # In case the mask used for generating the Dart program lead to an
+            # error, update the mask generator accordingly.
+            mask_gen.update_mask(mask)
+            # TODO (felih): this line should be enough but there seems to be a
+            # bug in dartfuzz.dart calculating mask_new.
+            mask_gen.update_mask(mask_new)
+            max_bits = mask_gen.count_bits()
+            min_mask = mask_gen.mask
+        elif last_err:
+            # If the last run removed the error try the inverse.
+            invMaskNew = mask_gen.mask | (mask_gen.max & ~mask_new)
+            if invMaskNew != mask_gen.mask and \
+                invMaskNew not in mask_gen.tested:
+                if (verbose):
+                    print("Mask: %x (i)" % invMaskNew)
+                mask_new = generate_dart(dartfuzz_cmd, dart_test, smask,
+                                         invMaskNew, do_expr)
+                err = run_dart_mp(dart_cmd, dart_test, error_match_p1, tries,
+                                  threads, timeout)
+                if err and verbose:
+                    print("Matched error 1 " + error_match1)
+                err_ref = True
+                if (dart_cmd_ref is not None) and (error_match_p2 is not None):
+                    err_ref = run_dart_mp(dart_cmd_ref, dart_test,
+                                          error_match_p2, tries_ref, threads,
+                                          timeout)
+                    if err_ref and verbose:
+                        print("Matched error 2 " + error_match2)
+                if err and err_ref:
+                    mask_gen.update_mask(invMaskNew)
+                    mask_gen.update_mask(mask_new)
+                    max_bits = mask_gen.count_bits()
+                    min_mask = mask_gen.mask
+        last_err = err and err_ref
+        # Update the set of tested masks with the one we just tested.
+        mask_gen.update_tested(mask_new)
+
+    print("Best I could do is %d/%d" \
+          % (max_bits,nstmts))
+
+    if do_expr:
+        print(dartfuzz_cmd + " " + dart_test +
+              " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
+    else:
+        print(dartfuzz_cmd + " " + dart_test +
+              " --mini --smask 0x%x --emask 0" % (min_mask))
+
+    return min_mask
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description='Minimize a generated Dart program ' +
+        ' while maintaining an identified crash or divergence. ' +
+        'A second Dart program can be specified for divergence testing.')
+    parser.add_argument(
+        '--dartfuzz',
+        required=True,
+        help="dartfuzz command string "
+        "e.g. dart dartfuzz.dart --no-ffi --no-fp --seed 243123600")
+    parser.add_argument(
+        '--dart',
+        help="Dart command string "
+        "e.g. ./sdk/out/ReleaseX64/dart",
+        required=True)
+    parser.add_argument(
+        '--dart-ref',
+        dest="dart_ref",
+        help="Dart command string for reference build " +
+        "(in case of divergence testing) " + "e.g. ./sdk/out/ReleaseX64/dart",
+        default=None)
+    parser.add_argument(
+        '--testfile',
+        required=True,
+        help="output filename for program generated by "
+        "dartfuzz command and passed to Dart command "
+        "e.g fuzz.dart")
+    parser.add_argument(
+        '--err',
+        help="string indicating an error for Dart cmd (no multiline matches)",
+        required=True)
+    parser.add_argument(
+        '--err-ref',
+        dest="err_ref",
+        help="string matching the diverging output for the Dart " +
+        "reference command (no multiline matches)",
+        default=None)
+    parser.add_argument(
+        '--smask', help="hexadecimal statements mask", default="0")
+    parser.add_argument(
+        '--emask', help="hexadecimal expressions mask", default="0")
+    parser.add_argument(
+        '--typ',
+        choices=["s", "e", "se"],
+        required=True,
+        help="minimize statements (s) or expressions (e) or both (se)")
+    parser.add_argument(
+        '--tries',
+        type=int,
+        default=1,
+        help='number of retries per run for Dart cmd')
+    parser.add_argument(
+        '--tries-ref',
+        type=int,
+        dest='tries_ref',
+        default=1,
+        help='number of retries per run for Dart reference cmd')
+    parser.add_argument(
+        '--threads',
+        type=int,
+        default=4,
+        help='number of threads to use for retries')
+    parser.add_argument(
+        '--timeout', type=int, default=60, help='timeout for Dart command')
+    parser.add_argument(
+        '--verbose', help="print intermediate results", action="store_true")
+    args = parser.parse_args()
+    timeout = args.timeout
+    do_stmt = "s" in args.typ
+    do_expr = "e" in args.typ
+    smask = int(args.smask, 16)
+    if do_stmt:
+        print("Minimizing Statements")
+        smask = minimize(args.dartfuzz, args.dart, args.dart_ref,
+                         args.testfile, args.err, args.err_ref, smask,
+                         int(args.emask, 16), False, args.verbose, args.tries,
+                         args.tries_ref, args.threads, timeout)
+    if do_expr:
+        print("Minimizing Expressions")
+        minimize(args.dartfuzz, args.dart, args.dart_ref,
+                 args.testfile, args.err, args.err_ref, smask,
+                 int(args.emask, 16), True, args.verbose, args.tries,
+                 args.tries_ref, args.threads, timeout)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 5850a97..9223327 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -140,14 +140,13 @@
       "-Ddart.developer.causal_async_stacks=$allow_causal_async_stacks",
       "-Ddart.isVM=true",
     ]
-
     if (defined(invoker.exclude_source) && invoker.exclude_source) {
       args += [ "--exclude-source" ]
     }
-    outline = "vm_outline" + output_postfix + ".dill"
-    if (dart_platform_bytecode) {
+    if (defined(invoker.bytecode) && invoker.bytecode) {
       args += [ "--bytecode" ]
     }
+    outline = "vm_outline" + output_postfix + ".dill"
   }
 }
 
@@ -161,6 +160,10 @@
   add_implicit_vm_platform_dependency = false
   exclude_source = true
   output_postfix = "_strong_stripped"
+
+  if (dart_platform_bytecode) {
+    bytecode = true
+  }
 }
 
 group("kernel_platform_files") {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index c947c02..336163a 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -392,6 +392,7 @@
   V(TransferableTypedData_factory, 2)                                          \
   V(TransferableTypedData_materialize, 1)                                      \
   V(Wasm_initModule, 2)                                                        \
+  V(Wasm_describeModule, 1)                                                    \
   V(Wasm_initImports, 2)                                                       \
   V(Wasm_addMemoryImport, 3)                                                   \
   V(Wasm_addGlobalImport, 5)                                                   \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 70459fd..634f9e7 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -90,6 +90,7 @@
 #endif
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void SerializationCluster::WriteAndMeasureAlloc(Serializer* serializer) {
   if (LOG_SECTION_BOUNDARIES) {
     OS::PrintErr("Data + %" Px ": Alloc %s\n", serializer->bytes_written(),
@@ -115,7 +116,6 @@
   size_ += (stop - start);
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
 class ClassSerializationCluster : public SerializationCluster {
  public:
   explicit ClassSerializationCluster(intptr_t num_cids)
@@ -4336,6 +4336,10 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
+#if defined(DEBUG)
+static const int32_t kSectionMarker = 0xABAB;
+#endif
+
 Serializer::Serializer(Thread* thread,
                        Snapshot::Kind kind,
                        uint8_t** buffer,
@@ -4551,6 +4555,7 @@
 #endif  // !DART_PRECOMPILED_RUNTIME
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void Serializer::WriteInstructions(RawInstructions* instr, RawCode* code) {
   ASSERT(code != Code::null());
 
@@ -4740,11 +4745,6 @@
   free(const_cast<char*>(expected_features));
 }
 
-#if defined(DEBUG)
-static const int32_t kSectionMarker = 0xABAB;
-#endif
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
 static int CompareClusters(SerializationCluster* const* a,
                            SerializationCluster* const* b) {
   if ((*a)->size() > (*b)->size()) {
@@ -4755,7 +4755,6 @@
     return 0;
   }
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 void Serializer::Serialize() {
   while (stack_.length() > 0) {
@@ -5019,6 +5018,7 @@
 
   heap_->ResetObjectIdTable();
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 Deserializer::Deserializer(Thread* thread,
                            Snapshot::Kind kind,
@@ -5519,6 +5519,7 @@
             "Write a snapshot profile in V8 format to a file.");
 #endif
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
                                        uint8_t** vm_snapshot_data_buffer,
                                        uint8_t** isolate_snapshot_data_buffer,
@@ -5655,6 +5656,7 @@
   }
 #endif
 }
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
 
 FullSnapshotReader::FullSnapshotReader(const Snapshot* snapshot,
                                        const uint8_t* instructions_buffer,
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 375e171..1697657 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -944,18 +944,9 @@
       for (intptr_t i = 0; i < class_ids.length(); i++) {
         const intptr_t cid = class_ids[i];
         cls = isolate()->class_table()->At(cid);
-        // Even if we are resolving get:M on a class that has method M
-        // ResolveForReceiverClass would not inject a method extractor into
-        // a class becuase FLAG_lazy_dispatchers is set to false during AOT
-        // compilation. Precompiler however does inject method extractors
-        // (see Precompiler::CheckForNewDynamicFunctions). This means that that
-        // lookup for get:m might overlook a method M in subclass and return
-        // get:m (method extractor for M) from a superclass.
-        // For this reason we abort optimization if lookup returns any
-        // artificial functions that can be inserted lazily.
         target = instr->ResolveForReceiverClass(cls);
-        if (target.IsNull() || target.IsMethodExtractor() ||
-            target.IsInvokeFieldDispatcher()) {
+        ASSERT(target.IsNull() || !target.IsInvokeFieldDispatcher());
+        if (target.IsNull()) {
           single_target = Function::null();
           ic_data = ICData::null();
           break;
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index b92b714..6be5427 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -17,6 +17,7 @@
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/inliner.h"
 #include "vm/compiler/backend/linearscan.h"
 #include "vm/compiler/backend/range_analysis.h"
@@ -67,10 +68,6 @@
     max_speculative_inlining_attempts,
     1,
     "Max number of attempts with speculative inlining (precompilation only)");
-DEFINE_FLAG(charp,
-            serialize_flow_graphs_to,
-            nullptr,
-            "Serialize flow graphs to the given file");
 
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -90,6 +87,17 @@
 DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold);
 DECLARE_FLAG(bool, print_instruction_stats);
 
+DEFINE_FLAG(charp,
+            serialize_flow_graphs_to,
+            nullptr,
+            "Serialize flow graphs to the given file");
+
+DEFINE_FLAG(bool,
+            populate_llvm_constant_pool,
+            false,
+            "Add constant pool entries from flow graphs to a special pool "
+            "serialized in AOT snapshots (with --serialize_flow_graphs_to)");
+
 Precompiler* Precompiler::singleton_ = nullptr;
 
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
@@ -200,6 +208,16 @@
         auto file = file_open(FLAG_serialize_flow_graphs_to, /*write=*/true);
         set_il_serialization_stream(file);
       }
+      if (FLAG_populate_llvm_constant_pool) {
+        auto const object_store = I->object_store();
+        auto& llvm_constants = GrowableObjectArray::Handle(
+            zone_, GrowableObjectArray::New(16, Heap::kOld));
+        auto& llvm_constants_hash_table = Array::Handle(
+            zone_, HashTables::New<FlowGraphSerializer::LLVMConstantsMap>(
+                       16, Heap::kOld));
+        object_store->set_llvm_constant_pool(llvm_constants);
+        object_store->set_llvm_constant_hash_table(llvm_constants_hash_table);
+      }
     }
 
     if (FLAG_use_bare_instructions) {
@@ -324,6 +342,19 @@
 
       I->set_compilation_allowed(false);
 
+      if (FLAG_serialize_flow_graphs_to != nullptr &&
+          Dart::file_write_callback() != nullptr) {
+        if (auto file_close = Dart::file_close_callback()) {
+          file_close(il_serialization_stream());
+          set_il_serialization_stream(nullptr);
+        }
+        if (FLAG_populate_llvm_constant_pool) {
+          // We don't want the Array backing for the map from constants to
+          // indices in the snapshot, only the constant pool itself.
+          I->object_store()->set_llvm_constant_hash_table(Array::null_array());
+        }
+      }
+
       TraceForRetainedFunctions();
       DropFunctions();
       DropFields();
@@ -364,13 +395,6 @@
 
     ProgramVisitor::Dedup();
 
-    if (il_serialization_stream() != nullptr) {
-      auto file_close = Dart::file_close_callback();
-      ASSERT(file_close != nullptr);
-      file_close(il_serialization_stream());
-      set_il_serialization_stream(nullptr);
-    }
-
     zone_ = NULL;
   }
 
@@ -1410,6 +1434,7 @@
         function ^= functions.At(j);
         bool retain = functions_to_retain_.ContainsKey(function);
         function.DropUncompiledImplicitClosureFunction();
+        function.ClearBytecode();
         if (retain) {
           retained_functions.Add(function);
         } else {
@@ -1435,6 +1460,7 @@
   for (intptr_t j = 0; j < closures.Length(); j++) {
     function ^= closures.At(j);
     bool retain = functions_to_retain_.ContainsKey(function);
+    function.ClearBytecode();
     if (retain) {
       retained_functions.Add(function);
     } else {
@@ -1455,6 +1481,7 @@
   Field& field = Field::Handle(Z);
   GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z);
   AbstractType& type = AbstractType::Handle(Z);
+  Function& initializer_function = Function::Handle(Z);
 
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
     lib ^= libraries_.At(i);
@@ -1470,6 +1497,10 @@
       for (intptr_t j = 0; j < fields.Length(); j++) {
         field ^= fields.At(j);
         bool retain = fields_to_retain_.HasKey(&field);
+        if (field.HasInitializerFunction()) {
+          initializer_function = field.InitializerFunction();
+          initializer_function.ClearBytecode();
+        }
         if (retain) {
           retained_fields.Add(field);
           type = field.type();
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 7c52d628..afef14c 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1029,14 +1029,15 @@
     VariableLivenessAnalysis* variable_liveness,
     ZoneGrowableArray<Definition*>* inlining_parameters) {
   ASSERT(!IsCompiledForOsr());
-  const intptr_t parameter_count = num_direct_parameters_;
+  const intptr_t direct_parameter_count = num_direct_parameters_;
 
   // Check if inlining_parameters include a type argument vector parameter.
   const intptr_t inlined_type_args_param =
       ((inlining_parameters != NULL) && function().IsGeneric()) ? 1 : 0;
 
-  ASSERT(parameter_count <= env->length());
-  for (intptr_t i = 0; i < parameter_count; i++) {
+  ASSERT(variable_count() == env->length());
+  ASSERT(direct_parameter_count <= env->length());
+  for (intptr_t i = 0; i < direct_parameter_count; i++) {
     ParameterInstr* param = new (zone()) ParameterInstr(i, function_entry);
     param->set_ssa_temp_index(alloc_ssa_temp_index());
     AddToInitialDefinitions(function_entry, param);
@@ -1097,8 +1098,7 @@
   // 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();
-  ASSERT(env->length() == (parameter_count - osr_entry->stack_depth()));
-  env->EnsureLength(parameter_count, constant_dead());
+  ASSERT(parameter_count == env->length());
   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());
@@ -1120,7 +1120,7 @@
           : -1;
 
   // Add real definitions for all locals and parameters.
-  ASSERT(variable_count() <= env->length());
+  ASSERT(variable_count() == env->length());
   for (intptr_t i = 0, n = variable_count(); i < n; ++i) {
     // Replace usages of the raw exception/stacktrace variables with
     // [SpecialParameterInstr]s.
@@ -1288,7 +1288,7 @@
         PushArgumentInstr* push_arg = current->PushArgumentAt(i);
         ASSERT(push_arg->IsPushArgument());
         ASSERT(reaching_defn->ssa_temp_index() != -1);
-        ASSERT(reaching_defn->IsPhi());
+        ASSERT(reaching_defn->IsPhi() || reaching_defn == constant_dead());
         push_arg->ReplaceUsesWith(push_arg->InputAt(0)->definition());
         push_arg->UnuseAllInputs();
         push_arg->previous()->LinkTo(push_arg->next());
@@ -1416,29 +1416,30 @@
     // Update expression stack and remove current instruction from the graph.
     Definition* definition = current->Cast<Definition>();
     if (definition->HasTemp()) {
-      ASSERT(result != NULL);
+      ASSERT(result != nullptr);
       env->Add(result);
     }
     it.RemoveCurrentFromGraph();
   }
 
   // 3. Process dominated blocks.
-  BlockEntryInstr* osr_succ =
-      (block_entry == graph_entry() && IsCompiledForOsr())
-          ? graph_entry()->osr_entry()->last_instruction()->SuccessorAt(0)
-          : nullptr;
+  const bool set_stack = (block_entry == graph_entry()) && IsCompiledForOsr();
   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());
+    // During OSR, when traversing from the graph entry directly any block
+    // (which may be a non-entry), we must adjust the environment to mimic
+    // a non-empty incoming expression stack to ensure temporaries refer to
+    // the right stack items.
+    const intptr_t stack_depth = block->stack_depth();
+    ASSERT(stack_depth >= 0);
+    if (set_stack) {
+      ASSERT(variable_count() == new_env.length());
+      new_env.FillWith(constant_dead(), variable_count(), stack_depth);
+    } else if (!block->last_instruction()->IsTailCall()) {
+      // Assert environment integrity otherwise.
+      ASSERT((variable_count() + stack_depth) == new_env.length());
     }
     RenameRecursive(block, &new_env, live_phis, variable_liveness,
                     inlining_parameters);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 7db6c39..af3e2f5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -952,9 +952,7 @@
 
   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 2e8362a..8c9f45d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -920,9 +920,7 @@
 
   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 f311a34..5b1a9c3 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -839,9 +839,7 @@
   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 fe4eace..78987ee 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -935,9 +935,7 @@
   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 2b1152a..b7adcf9 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1129,7 +1129,10 @@
 GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
                                  intptr_t osr_id,
                                  intptr_t deopt_id)
-    : BlockEntryWithInitialDefs(0, kInvalidTryIndex, deopt_id),
+    : BlockEntryWithInitialDefs(0,
+                                kInvalidTryIndex,
+                                deopt_id,
+                                /*stack_depth*/ 0),
       parsed_function_(parsed_function),
       catch_entries_(),
       indirect_entries_(),
@@ -1656,11 +1659,11 @@
       // we can simply jump to the beginning of the block.
       ASSERT(instr->previous() == this);
 
-      const intptr_t stack_depth = instr->AsCheckStackOverflow()->stack_depth();
+      ASSERT(stack_depth() == instr->AsCheckStackOverflow()->stack_depth());
       auto normal_entry = graph_entry->normal_entry();
-      auto osr_entry = new OsrEntryInstr(graph_entry, normal_entry->block_id(),
-                                         normal_entry->try_index(),
-                                         normal_entry->deopt_id(), stack_depth);
+      auto osr_entry = new OsrEntryInstr(
+          graph_entry, normal_entry->block_id(), normal_entry->try_index(),
+          normal_entry->deopt_id(), stack_depth());
 
       auto goto_join = new GotoInstr(AsJoinEntry(),
                                      CompilerState::Current().GetNextDeoptId());
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 8128fb9..7d13712 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -1384,6 +1384,10 @@
   intptr_t offset() const { return offset_; }
   void set_offset(intptr_t offset) { offset_ = offset; }
 
+  // Stack-based IR bookkeeping.
+  intptr_t stack_depth() const { return stack_depth_; }
+  void set_stack_depth(intptr_t s) { stack_depth_ = s; }
+
   // For all instruction in this block: Remove all inputs (including in the
   // environment) from their definition's use lists for all instructions.
   void ClearAllInstructions();
@@ -1395,12 +1399,16 @@
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  protected:
-  BlockEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
+  BlockEntryInstr(intptr_t block_id,
+                  intptr_t try_index,
+                  intptr_t deopt_id,
+                  intptr_t stack_depth)
       : Instruction(deopt_id),
         block_id_(block_id),
         try_index_(try_index),
         preorder_number_(-1),
         postorder_number_(-1),
+        stack_depth_(stack_depth),
         dominator_(nullptr),
         dominated_blocks_(1),
         last_instruction_(NULL),
@@ -1428,6 +1436,8 @@
   intptr_t try_index_;
   intptr_t preorder_number_;
   intptr_t postorder_number_;
+  // Expected stack depth on entry (for stack-based IR only).
+  intptr_t stack_depth_;
   // Starting and ending lifetime positions for this block.  Used by
   // the linear scan register allocator.
   intptr_t start_pos_;
@@ -1512,8 +1522,9 @@
  public:
   BlockEntryWithInitialDefs(intptr_t block_id,
                             intptr_t try_index,
-                            intptr_t deopt_id)
-      : BlockEntryInstr(block_id, try_index, deopt_id) {}
+                            intptr_t deopt_id,
+                            intptr_t stack_depth)
+      : BlockEntryInstr(block_id, try_index, deopt_id, stack_depth) {}
 
   GrowableArray<Definition*>* initial_definitions() {
     return &initial_definitions_;
@@ -1630,8 +1641,11 @@
 
 class JoinEntryInstr : public BlockEntryInstr {
  public:
-  JoinEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
-      : BlockEntryInstr(block_id, try_index, deopt_id),
+  JoinEntryInstr(intptr_t block_id,
+                 intptr_t try_index,
+                 intptr_t deopt_id,
+                 intptr_t stack_depth = 0)
+      : BlockEntryInstr(block_id, try_index, deopt_id, stack_depth),
         predecessors_(2),  // Two is the assumed to be the common case.
         phis_(NULL) {}
 
@@ -1698,8 +1712,11 @@
 
 class TargetEntryInstr : public BlockEntryInstr {
  public:
-  TargetEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
-      : BlockEntryInstr(block_id, try_index, deopt_id),
+  TargetEntryInstr(intptr_t block_id,
+                   intptr_t try_index,
+                   intptr_t deopt_id,
+                   intptr_t stack_depth = 0)
+      : BlockEntryInstr(block_id, try_index, deopt_id, stack_depth),
         predecessor_(NULL),
         edge_weight_(0.0) {}
 
@@ -1749,7 +1766,10 @@
                      intptr_t block_id,
                      intptr_t try_index,
                      intptr_t deopt_id)
-      : BlockEntryWithInitialDefs(block_id, try_index, deopt_id),
+      : BlockEntryWithInitialDefs(block_id,
+                                  try_index,
+                                  deopt_id,
+                                  /*stack_depth=*/0),
         graph_entry_(graph_entry) {}
 
   DECLARE_INSTRUCTION(FunctionEntry)
@@ -1815,8 +1835,7 @@
                 intptr_t try_index,
                 intptr_t deopt_id,
                 intptr_t stack_depth)
-      : BlockEntryWithInitialDefs(block_id, try_index, deopt_id),
-        stack_depth_(stack_depth),
+      : BlockEntryWithInitialDefs(block_id, try_index, deopt_id, stack_depth),
         graph_entry_(graph_entry) {}
 
   DECLARE_INSTRUCTION(OsrEntry)
@@ -1829,7 +1848,6 @@
     return graph_entry_;
   }
 
-  intptr_t stack_depth() const { return stack_depth_; }
   GraphEntryInstr* graph_entry() const { return graph_entry_; }
 
   PRINT_TO_SUPPORT
@@ -1841,7 +1859,6 @@
     graph_entry_ = predecessor->AsGraphEntry();
   }
 
-  const intptr_t stack_depth_;
   GraphEntryInstr* graph_entry_;
 
   DISALLOW_COPY_AND_ASSIGN(OsrEntryInstr);
@@ -1880,7 +1897,10 @@
                        const LocalVariable* stacktrace_var,
                        const LocalVariable* raw_exception_var,
                        const LocalVariable* raw_stacktrace_var)
-      : BlockEntryWithInitialDefs(block_id, try_index, deopt_id),
+      : BlockEntryWithInitialDefs(block_id,
+                                  try_index,
+                                  deopt_id,
+                                  /*stack_depth=*/0),
         graph_entry_(graph_entry),
         predecessor_(NULL),
         catch_handler_types_(Array::ZoneHandle(handler_types.raw())),
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index b6e2166..6ed9d5b 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -510,9 +510,7 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
-#if defined(DEBUG)
   __ bkpt(0);
-#endif
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 74c983d..3f7f28f 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -499,9 +499,7 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
-#if defined(DEBUG)
   __ brk(0);
-#endif
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index a290225..ff3df26 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -392,9 +392,7 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
-#if defined(DEBUG)
   __ int3();
-#endif
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index 1ab17fd..486973b 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -9,6 +9,7 @@
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/method_recognizer.h"
+#include "vm/object_store.h"
 #include "vm/os.h"
 
 namespace dart {
@@ -16,23 +17,62 @@
 DEFINE_FLAG(bool,
             serialize_flow_graph_types,
             true,
-            "Serialize inferred type information in flow graphs"
-            " (with --serialize_flow_graphs_to)");
+            "Serialize inferred type information in flow graphs");
 
 DEFINE_FLAG(bool,
             verbose_flow_graph_serialization,
             false,
-            "Serialize extra information useful for debugging"
-            " (with --serialize_flow_graphs_to)");
+            "Serialize extra information useful for debugging");
 
 DEFINE_FLAG(bool,
             pretty_print_serialization,
             false,
-            "Format serialized output nicely"
-            " (with --serialize_flow_graphs_to)");
+            "Format serialized output nicely");
+
+DECLARE_FLAG(bool, populate_llvm_constant_pool);
 
 const char* const FlowGraphSerializer::initial_indent = "";
 
+FlowGraphSerializer::FlowGraphSerializer(Zone* zone,
+                                         const FlowGraph* flow_graph)
+    : flow_graph_(ASSERT_NOTNULL(flow_graph)),
+      zone_(zone),
+      object_store_(flow_graph->thread()->isolate()->object_store()),
+      open_recursive_types_(zone_),
+      llvm_pool_(
+          GrowableObjectArray::Handle(zone_,
+                                      object_store_->llvm_constant_pool())),
+      llvm_map_(zone_, object_store_->llvm_constant_hash_table()),
+      llvm_index_(Smi::Handle(zone_)),
+      tmp_string_(String::Handle(zone_)),
+      array_type_args_((TypeArguments::Handle(zone_))),
+      closure_context_(Context::Handle(zone_)),
+      closure_function_(Function::Handle(zone_)),
+      closure_type_args_(TypeArguments::Handle(zone_)),
+      code_owner_(Object::Handle(zone_)),
+      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_)),
+      serialize_owner_(Class::Handle(zone_)),
+      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.
+  ASSERT(flow_graph->zone()->ContainsNestedZone(zone));
+}
+
+FlowGraphSerializer::~FlowGraphSerializer() {
+  object_store_->set_llvm_constant_hash_table(llvm_map_.Release());
+}
+
 void FlowGraphSerializer::SerializeToBuffer(const FlowGraph* flow_graph,
                                             TextBuffer* buffer) {
   SerializeToBuffer(Thread::Current()->zone(), flow_graph, buffer);
@@ -695,7 +735,8 @@
     AddSymbol(elem, "def");
     elem->Add(UseToSExp(definition));
     // Use ObjectToSExp here, not DartValueToSExp!
-    elem->Add(ObjectToSExp(definition->AsConstant()->value()));
+    const auto& value = definition->AsConstant()->value();
+    elem->Add(ObjectToSExp(value));
     // Check this first, otherwise Type() can have the side effect of setting
     // a new CompileType!
     if (definition->HasType()) {
@@ -704,6 +745,16 @@
         elem->AddExtra("type", type->ToSExpression(this));
       }
     }
+    if (FLAG_populate_llvm_constant_pool) {
+      auto const pool_len = llvm_pool_.Length();
+      llvm_index_ = Smi::New(pool_len);
+      llvm_index_ =
+          Smi::RawCast(llvm_map_.InsertOrGetValue(value, llvm_index_));
+      if (llvm_index_.Value() == pool_len) {
+        llvm_pool_.Add(value);
+      }
+      AddExtraInteger(elem, "llvm_index", llvm_index_.Value());
+    }
     constant_list->Add(elem);
   }
   return constant_list;
diff --git a/runtime/vm/compiler/backend/il_serializer.h b/runtime/vm/compiler/backend/il_serializer.h
index 94945e0..7fb3088 100644
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ b/runtime/vm/compiler/backend/il_serializer.h
@@ -12,6 +12,7 @@
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/sexpression.h"
+#include "vm/hash_table.h"
 #include "vm/object.h"
 #include "vm/zone.h"
 
@@ -108,34 +109,10 @@
   void AddExtraSymbol(SExpList* sexp, const char* label, const char* cstr);
 
  private:
-  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_)),
-        closure_function_(Function::Handle(zone_)),
-        closure_type_args_(TypeArguments::Handle(zone_)),
-        code_owner_(Object::Handle(zone_)),
-        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_)),
-        serialize_owner_(Class::Handle(zone_)),
-        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.
-    ASSERT(flow_graph->zone()->ContainsNestedZone(zone));
-  }
+  friend class Precompiler;  // For LLVMConstantsMap.
+
+  FlowGraphSerializer(Zone* zone, const FlowGraph* flow_graph);
+  ~FlowGraphSerializer();
 
   static const char* const initial_indent;
 
@@ -147,11 +124,33 @@
 
   const FlowGraph* const flow_graph_;
   Zone* const zone_;
+  ObjectStore* const object_store_;
 
   // 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_;
 
+  // Used for --populate-llvm-constant-pool in ConstantPoolToSExp.
+  class LLVMConstantMapKeyEqualsTraits : public AllStatic {
+   public:
+    static const char* Name() { return "LLVMConstantMapKeyEqualsTraits"; }
+    static bool ReportStats() { return false; }
+
+    static bool IsMatch(const Object& a, const Object& b) {
+      return a.raw() == b.raw();
+    }
+    static uword Hash(const Object& obj) {
+      if (obj.IsSmi()) return reinterpret_cast<uword>(obj.raw());
+      if (obj.IsInstance()) return Instance::Cast(obj).CanonicalizeHash();
+      return obj.GetClassId();
+    }
+  };
+  typedef UnorderedHashMap<LLVMConstantMapKeyEqualsTraits> LLVMConstantsMap;
+
+  GrowableObjectArray& llvm_pool_;
+  LLVMConstantsMap llvm_map_;
+  Smi& llvm_index_;
+
   // Handles used across functions, where the contained value is used
   // immediately and does not need to live across calls to other serializer
   // functions.
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index b7cf98f..10face2 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -521,9 +521,7 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
-#if defined(DEBUG)
   __ int3();
-#endif
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 5e93802..2d10861 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -160,6 +160,7 @@
     if (function.IsNull()) {
       return false;
     }
+    ASSERT(!function.IsInvokeFieldDispatcher());
 
     // Update the CallTargets attached to the instruction with our speculative
     // target. The next round of CallSpecializer::VisitInstanceCall will make
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index c6ac8e4..fad3c15 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -661,8 +661,8 @@
 }
 
 TargetEntryInstr* BaseFlowGraphBuilder::BuildTargetEntry() {
-  return new (Z)
-      TargetEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
+  return new (Z) TargetEntryInstr(AllocateBlockId(), CurrentTryIndex(),
+                                  GetNextDeoptId(), GetStackDepth());
 }
 
 FunctionEntryInstr* BaseFlowGraphBuilder::BuildFunctionEntry(
@@ -672,12 +672,13 @@
 }
 
 JoinEntryInstr* BaseFlowGraphBuilder::BuildJoinEntry(intptr_t try_index) {
-  return new (Z) JoinEntryInstr(AllocateBlockId(), try_index, GetNextDeoptId());
+  return new (Z) JoinEntryInstr(AllocateBlockId(), try_index, GetNextDeoptId(),
+                                GetStackDepth());
 }
 
 JoinEntryInstr* BaseFlowGraphBuilder::BuildJoinEntry() {
-  return new (Z)
-      JoinEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
+  return new (Z) JoinEntryInstr(AllocateBlockId(), CurrentTryIndex(),
+                                GetNextDeoptId(), GetStackDepth());
 }
 
 ArgumentArray BaseFlowGraphBuilder::GetArguments(int count) {
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 034716b..349db75 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -2177,6 +2177,7 @@
         B->stack_ = stack_state;
       }
       code_ = Fragment(join);
+      join->set_stack_depth(B->GetStackDepth());
       B->SetCurrentTryIndex(join->try_index());
     } else {
       // Unreachable bytecode is not allowed.
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 787c06a..6f2240a 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -756,7 +756,7 @@
         //     of those cases require a dynamic invocation forwarder;
         //   * we assume that all closures are entered in a checked way.
         if (isDynamic && (kind != InvocationKind::getter) &&
-            !FLAG_precompiled_mode && I->should_emit_strong_mode_checks() &&
+            I->should_emit_strong_mode_checks() &&
             (name.raw() != Symbols::EqualOperator().raw()) &&
             (name.raw() != Symbols::Call().raw())) {
           name = Function::CreateDynamicInvocationForwarderName(name);
@@ -894,8 +894,7 @@
         //     checked at the entry because the parameter is marked covariant,
         //     neither of those cases require a dynamic invocation forwarder;
         //   * we assume that all closures are entered in a checked way.
-        if (!Field::IsGetterName(name) && !FLAG_precompiled_mode &&
-            I->should_emit_strong_mode_checks() &&
+        if (!Field::IsGetterName(name) && I->should_emit_strong_mode_checks() &&
             (name.raw() != Symbols::EqualOperator().raw()) &&
             (name.raw() != Symbols::Call().raw())) {
           name = Function::CreateDynamicInvocationForwarderName(name);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 9fb9b27..c142b3f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1157,6 +1157,8 @@
       return BuildConstructorInvocation(true, position);
     case kNot:
       return BuildNot(position);
+    case kNullCheck:
+      return BuildNullCheck(position);
     case kLogicalExpression:
       return BuildLogicalExpression(position);
     case kConditionalExpression:
@@ -3245,6 +3247,17 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildNullCheck(TokenPosition* p) {
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  TokenPosition operand_position = TokenPosition::kNoSource;
+  Fragment instructions =
+      BuildExpression(&operand_position);  // read expression.
+  // TODO(37479): Implement null-check semantics.
+  return instructions;
+}
+
 // Translate the logical expression (lhs && rhs or lhs || rhs) in a context
 // where a value is required.
 //
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 2cdbb28..e26f76d 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -301,6 +301,7 @@
   Fragment BuildStaticInvocation(bool is_const, TokenPosition* position);
   Fragment BuildConstructorInvocation(bool is_const, TokenPosition* position);
   Fragment BuildNot(TokenPosition* position);
+  Fragment BuildNullCheck(TokenPosition* position);
   Fragment BuildLogicalExpression(TokenPosition* position);
   Fragment TranslateLogicalExpressionForValue(bool negated,
                                               TestFragment* side_exits);
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 2f8fc9f..a6b9762 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -442,6 +442,10 @@
     case kNot:
       CalculateExpressionFingerprint();  // read expression.
       return;
+    case kNullCheck:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
     case kLogicalExpression:
       CalculateExpressionFingerprint();  // read left.
       SkipBytes(1);                      // read operator.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 771d4ce..eb23c65 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2229,6 +2229,10 @@
     case kNot:
       SkipExpression();  // read expression.
       return;
+    case kNullCheck:
+      ReadPosition();    // read position.
+      SkipExpression();  // read expression.
+      return;
     case kLogicalExpression:
       SkipExpression();  // read left.
       SkipBytes(1);      // read operator.
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index d4f7829..d9ce861 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -267,8 +267,6 @@
     copy_args_prologue += Drop();
 
     for (intptr_t i = 0; param < num_params; ++param, ++i) {
-      JoinEntryInstr* join = BuildJoinEntry();
-
       copy_args_prologue += IntConstant(
           compiler::target::ArgumentsDescriptor::named_entry_size() /
           compiler::target::kWordSize);
@@ -299,6 +297,9 @@
       TargetEntryInstr *supplied, *missing;
       copy_args_prologue += BranchIfStrictEqual(&supplied, &missing);
 
+      // Join good/not_good.
+      JoinEntryInstr* join = BuildJoinEntry();
+
       // Let's load position from arg descriptor (to see which parameter is the
       // name) and move kEntrySize forward in ArgDescriptopr names array.
       Fragment good(supplied);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 2866061..d4e6473 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -33,7 +33,8 @@
   // In AOT mode we don't dynamically generate such trampolines but instead rely
   // on a static analysis to discover which methods can be invoked dynamically,
   // and generate the necessary trampolines during precompilation.
-  if (method.name() == Symbols::Call().raw()) {
+  if (method.name() == Symbols::Call().raw() ||
+      method.CanReceiveDynamicInvocation()) {
     // Currently we consider all call methods to be invoked dynamically and
     // don't mangle their names.
     // TODO(vegorov) remove this once we also introduce special type checking
@@ -763,6 +764,10 @@
     case kNot:
       VisitExpression();  // read expression.
       return;
+    case kNullCheck:
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read expression.
+      return;
     case kLogicalExpression:
       needs_expr_temp_ = true;
       VisitExpression();     // read left.
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 84b3baf..68217ef 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -187,7 +187,7 @@
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
-#if !defined(TARGET_HASH_IN_OBJECT_HEADER)
+#if !defined(HASH_IN_OBJECT_HEADER)
   // These two are more complicated on 32 bit platforms, where the
   // identity hash is not stored in the header of the object.  We
   // therefore don't intrinsify them, falling back on the native C++
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index feb31a3..af363e6 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 = 32;
+const intptr_t kTrampolineSize = OS::kMaxPreferredCodeAlignment;
 
 CodeRelocator::CodeRelocator(Thread* thread,
                              GrowableArray<RawCode*>* code_objects,
@@ -33,16 +33,7 @@
       commands_(commands),
       kind_type_and_offset_(Smi::Handle(thread->zone())),
       target_(Object::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);
-}
+      destination_(Code::Handle(thread->zone())) {}
 
 void CodeRelocator::Relocate(bool is_vm_isolate) {
   Zone* zone = Thread::Current()->zone();
@@ -417,12 +408,7 @@
 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);
@@ -478,6 +464,9 @@
       // 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 88ad78e..e7f6f80 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -508,6 +508,7 @@
   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 3e93b40..add5eab 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 =
-    12;
+    16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
@@ -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 =
-    16;
+    24;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
@@ -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 =
-    12;
+    16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
@@ -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 =
-    16;
+    24;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
@@ -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 =
-    16;
+    24;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
@@ -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 =
-    12;
+    16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 0463a15..c771da7 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -53,6 +53,10 @@
 DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
 DECLARE_FLAG(bool, strong);
 
+#if defined(DART_PRECOMPILED_RUNTIME)
+DEFINE_FLAG(bool, print_llvm_constant_pool, false, "Print LLVM constant pool");
+#endif
+
 Isolate* Dart::vm_isolate_ = NULL;
 int64_t Dart::start_time_micros_ = 0;
 ThreadPool* Dart::thread_pool_ = NULL;
@@ -722,6 +726,32 @@
   // AOT: The megamorphic miss function and code come from the snapshot.
   ASSERT(I->object_store()->megamorphic_miss_code() != Code::null());
   ASSERT(I->object_store()->build_method_extractor_code() != Code::null());
+  if (FLAG_print_llvm_constant_pool) {
+    StackZone printing_zone(T);
+    HandleScope printing_scope(T);
+    const auto& arr =
+        GrowableObjectArray::Handle(I->object_store()->llvm_constant_pool());
+    if (arr.IsNull()) {
+      THR_Print("No constant pool information in snapshot.\n");
+    } else {
+      auto const len = arr.Length();
+      THR_Print("Constant pool contents (length %" Pd "):\n", len);
+      auto& obj = Object::Handle();
+      for (intptr_t i = 0; i < len; i++) {
+        obj = arr.At(i);
+        THR_Print("  %5" Pd ": ", i);
+        if (obj.IsString()) {
+          auto& str = String::Cast(obj);
+          TextBuffer b(100);
+          b.AddEscapedString(str.ToCString());
+          THR_Print("\"%s\"\n", b.buf());
+        } else {
+          THR_Print("%s\n", obj.ToCString());
+        }
+      }
+      THR_Print("End of constant pool.\n\n");
+    }
+  }
 #else
   // JIT: The megamorphic miss function and code come from the snapshot in JIT
   // app snapshot, otherwise create them.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 4c62313..7636aa3 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1627,6 +1627,7 @@
   Thread::ExitIsolate();
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 static uint8_t* ApiReallocate(uint8_t* ptr,
                               intptr_t old_size,
                               intptr_t new_size) {
@@ -1634,12 +1635,16 @@
       ->zone()
       ->Realloc<uint8_t>(ptr, old_size, new_size);
 }
+#endif
 
 DART_EXPORT Dart_Handle
 Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
                     intptr_t* vm_snapshot_data_size,
                     uint8_t** isolate_snapshot_data_buffer,
                     intptr_t* isolate_snapshot_data_size) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return Api::NewError("Cannot create snapshots on an AOT runtime.");
+#else
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
   Isolate* I = T->isolate();
@@ -1676,6 +1681,7 @@
   }
   *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
   return Api::Success();
+#endif
 }
 
 DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
@@ -6182,10 +6188,6 @@
   return Api::NewError("AOT compilation is not supported on IA32.");
 #elif defined(TARGET_ARCH_DBC)
   return Api::NewError("AOT compilation is not supported on DBC.");
-#elif defined(TARGET_OS_WINDOWS)
-  return Api::NewError("Windows cannot load ELF.");
-#elif defined(TARGET_OS_MACOS)
-  return Api::NewError("macOS/iOS cannot load ELF.");
 #elif !defined(DART_PRECOMPILER)
   return Api::NewError(
       "This VM was built without support for AOT compilation.");
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 7ba428b..2271645 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -44,10 +44,6 @@
 namespace dart {
 
 DEFINE_FLAG(bool,
-            show_invisible_frames,
-            false,
-            "Show invisible frames in debugger stack traces");
-DEFINE_FLAG(bool,
             trace_debugger_stacktrace,
             false,
             "Trace debugger stacktrace collection");
@@ -3377,6 +3373,13 @@
   Class& cls = Class::Handle(zone);
   Library& lib = Library::Handle(zone, script.FindLibrary());
   ASSERT(!lib.IsNull());
+  if (!lib.IsDebuggable()) {
+    if (FLAG_verbose_debug) {
+      OS::PrintErr("Library '%s' has been marked as non-debuggable\n",
+                   lib.ToCString());
+    }
+    return false;
+  }
   const GrowableObjectArray& closures = GrowableObjectArray::Handle(
       zone, isolate_->object_store()->closure_functions());
   Array& functions = Array::Handle(zone);
@@ -4534,6 +4537,10 @@
   CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
   ASSERT(cbpt != NULL);
 
+  if (!Library::Handle(top_frame->Library()).IsDebuggable()) {
+    return Error::null();
+  }
+
   Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame);
   if (bpt_hit == NULL) {
     return Error::null();
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 6306029..769f3d5 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -4,66 +4,13 @@
 
 #include "vm/elf.h"
 
+#include "platform/elf.h"
 #include "platform/text_buffer.h"
 #include "vm/cpu.h"
 #include "vm/thread.h"
 
 namespace dart {
 
-#define ELFCLASS32 1
-#define ELFCLASS64 2
-
-static const intptr_t ELFDATA2LSB = 1;
-
-static const intptr_t ELFOSABI_SYSV = 0;
-
-#define EF_ARM_ABI_FLOAT_HARD 0x00000400
-#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
-#define EF_ARM_ABI 0x05000000
-
-static const intptr_t ET_DYN = 3;
-
-#define EM_386 3
-#define EM_ARM 40
-#define EM_X86_64 62
-#define EM_AARCH64 183
-
-static const intptr_t EV_CURRENT = 1;
-
-static const intptr_t SHT_PROGBITS = 1;
-static const intptr_t SHT_STRTAB = 3;
-static const intptr_t SHT_HASH = 5;
-static const intptr_t SHT_DYNSYM = 11;
-static const intptr_t SHT_DYNAMIC = 6;
-
-static const intptr_t SHF_WRITE = 0x1;
-static const intptr_t SHF_ALLOC = 0x2;
-static const intptr_t SHF_EXECINSTR = 0x4;
-
-static const intptr_t SHN_UNDEF = 0;
-
-static const intptr_t STN_UNDEF = 0;
-
-static const intptr_t PT_LOAD = 1;
-static const intptr_t PT_DYNAMIC = 2;
-static const intptr_t PT_PHDR = 6;
-
-static const intptr_t PF_X = 1;
-static const intptr_t PF_W = 2;
-static const intptr_t PF_R = 4;
-
-static const intptr_t STB_GLOBAL = 1;
-
-static const intptr_t STT_OBJECT = 1;  // I.e., data.
-static const intptr_t STT_FUNC = 2;
-
-static const intptr_t DT_NULL = 0;
-static const intptr_t DT_HASH = 4;
-static const intptr_t DT_STRTAB = 5;
-static const intptr_t DT_SYMTAB = 6;
-static const intptr_t DT_STRSZ = 10;
-static const intptr_t DT_SYMENT = 11;
-
 #if defined(TARGET_ARCH_IS_32_BIT)
 static const intptr_t kElfHeaderSize = 52;
 static const intptr_t kElfSectionTableAlignment = 4;
@@ -94,7 +41,7 @@
   intptr_t section_type = 0;
   intptr_t section_flags = 0;
   intptr_t section_index = -1;
-  intptr_t section_link = SHN_UNDEF;
+  intptr_t section_link = elf::SHN_UNDEF;
   intptr_t section_info = 0;
   intptr_t section_entry_size = 0;
   intptr_t file_size = 0;
@@ -119,16 +66,16 @@
               intptr_t memsz = -1) {
     if (memsz == -1) memsz = filesz;
 
-    section_type = SHT_PROGBITS;
+    section_type = elf::SHT_PROGBITS;
     if (allocate) {
-      section_flags = SHF_ALLOC;
-      if (executable) section_flags |= SHF_EXECINSTR;
-      if (writable) section_flags |= SHF_WRITE;
+      section_flags = elf::SHF_ALLOC;
+      if (executable) section_flags |= elf::SHF_EXECINSTR;
+      if (writable) section_flags |= elf::SHF_WRITE;
 
-      segment_type = PT_LOAD;
-      segment_flags = PF_R;
-      if (executable) segment_flags |= PF_X;
-      if (writable) segment_flags |= PF_W;
+      segment_type = elf::PT_LOAD;
+      segment_flags = elf::PF_R;
+      if (executable) segment_flags |= elf::PF_X;
+      if (writable) segment_flags |= elf::PF_W;
     }
 
     bytes_ = bytes;
@@ -148,10 +95,10 @@
 class StringTable : public Section {
  public:
   explicit StringTable(bool allocate) : text_(128) {
-    section_type = SHT_STRTAB;
-    section_flags = allocate ? SHF_ALLOC : 0;
-    segment_type = PT_LOAD;
-    segment_flags = PF_R;
+    section_type = elf::SHT_STRTAB;
+    section_flags = allocate ? elf::SHF_ALLOC : 0;
+    segment_type = elf::PT_LOAD;
+    segment_flags = elf::PF_R;
 
     text_.AddChar('\0');
     memory_size = file_size = text_.length();
@@ -186,10 +133,10 @@
 class SymbolTable : public Section {
  public:
   SymbolTable() {
-    section_type = SHT_DYNSYM;
-    section_flags = SHF_ALLOC;
-    segment_type = PT_LOAD;
-    segment_flags = PF_R;
+    section_type = elf::SHT_DYNSYM;
+    section_flags = elf::SHF_ALLOC;
+    segment_type = elf::PT_LOAD;
+    segment_flags = elf::PF_R;
 
     section_entry_size = kElfSymbolTableEntrySize;
     AddSymbol(NULL);
@@ -268,24 +215,24 @@
 class SymbolHashTable : public Section {
  public:
   SymbolHashTable(StringTable* strtab, SymbolTable* symtab) {
-    section_type = SHT_HASH;
-    section_flags = SHF_ALLOC;
+    section_type = elf::SHT_HASH;
+    section_flags = elf::SHF_ALLOC;
     section_link = symtab->section_index;
     section_entry_size = kElfSymbolHashTableEntrySize;
-    segment_type = PT_LOAD;
-    segment_flags = PF_R;
+    segment_type = elf::PT_LOAD;
+    segment_flags = elf::PF_R;
 
     nchain_ = symtab->length();
     nbucket_ = symtab->length();
 
     bucket_ = Thread::Current()->zone()->Alloc<int32_t>(nbucket_);
     for (intptr_t i = 0; i < nbucket_; i++) {
-      bucket_[i] = STN_UNDEF;
+      bucket_[i] = elf::STN_UNDEF;
     }
 
     chain_ = Thread::Current()->zone()->Alloc<int32_t>(nchain_);
     for (intptr_t i = 0; i < nchain_; i++) {
-      chain_[i] = STN_UNDEF;
+      chain_[i] = elf::STN_UNDEF;
     }
 
     for (intptr_t i = 1; i < symtab->length(); i++) {
@@ -322,20 +269,20 @@
   DynamicTable(StringTable* strtab,
                SymbolTable* symtab,
                SymbolHashTable* hash) {
-    section_type = SHT_DYNAMIC;
+    section_type = elf::SHT_DYNAMIC;
     section_link = strtab->section_index;
-    section_flags = SHF_ALLOC | SHF_WRITE;
+    section_flags = elf::SHF_ALLOC | elf::SHF_WRITE;
     section_entry_size = kElfDynamicTableEntrySize;
 
-    segment_type = PT_LOAD;
-    segment_flags = PF_R | PF_W;
+    segment_type = elf::PT_LOAD;
+    segment_flags = elf::PF_R | elf::PF_W;
 
-    AddEntry(DT_HASH, hash->memory_offset);
-    AddEntry(DT_STRTAB, strtab->memory_offset);
-    AddEntry(DT_STRSZ, strtab->memory_size);
-    AddEntry(DT_SYMTAB, symtab->memory_offset);
-    AddEntry(DT_SYMENT, kElfSymbolTableEntrySize);
-    AddEntry(DT_NULL, 0);
+    AddEntry(elf::DT_HASH, hash->memory_offset);
+    AddEntry(elf::DT_STRTAB, strtab->memory_offset);
+    AddEntry(elf::DT_STRSZ, strtab->memory_size);
+    AddEntry(elf::DT_SYMTAB, symtab->memory_offset);
+    AddEntry(elf::DT_SYMENT, kElfSymbolTableEntrySize);
+    AddEntry(elf::DT_NULL, 0);
   }
 
   void Write(Elf* stream) {
@@ -432,7 +379,7 @@
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
   symbol->name = symstrtab_->AddString(name);
-  symbol->info = (STB_GLOBAL << 4) | STT_FUNC;
+  symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
@@ -444,8 +391,16 @@
 }
 
 intptr_t Elf::AddBSSData(const char* name, intptr_t size) {
-  ProgramBits* image = new (zone_)
-      ProgramBits(true, false, true, nullptr, /*filesz=*/0, /*memsz=*/size);
+  // Ideally the BSS segment would take no space in the object, but Android's
+  // "strip" utility truncates the memory-size of our segments to their
+  // file-size.
+  //
+  // Therefore we must insert zero-filled pages for the BSS.
+  uint8_t* const bytes = Thread::Current()->zone()->Alloc<uint8_t>(size);
+  memset(bytes, 0, size);
+
+  ProgramBits* const image = new (zone_)
+      ProgramBits(true, false, true, bytes, /*filesz=*/size, /*memsz=*/size);
   image->section_name = shstrtab_->AddString(".bss");
   AddSection(image);
   AddSegment(image);
@@ -453,7 +408,7 @@
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
   symbol->name = symstrtab_->AddString(name);
-  symbol->info = (STB_GLOBAL << 4) | STT_OBJECT;
+  symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
@@ -473,7 +428,7 @@
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
   symbol->name = symstrtab_->AddString(name);
-  symbol->info = (STB_GLOBAL << 4) | STT_OBJECT;
+  symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
@@ -550,39 +505,52 @@
 
 void Elf::WriteHeader() {
 #if defined(TARGET_ARCH_IS_32_BIT)
-  uint8_t size = ELFCLASS32;
+  uint8_t size = elf::ELFCLASS32;
 #else
-  uint8_t size = ELFCLASS64;
+  uint8_t size = elf::ELFCLASS64;
 #endif
-  uint8_t e_ident[16] = {
-      0x7f, 'E', 'L', 'F', size, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
-      0,    0,   0,   0,   0,    0,           0,          0};
+  uint8_t e_ident[16] = {0x7f,
+                         'E',
+                         'L',
+                         'F',
+                         size,
+                         elf::ELFDATA2LSB,
+                         elf::EV_CURRENT,
+                         elf::ELFOSABI_SYSV,
+                         0,
+                         0,
+                         0,
+                         0,
+                         0,
+                         0,
+                         0,
+                         0};
   stream_->WriteBytes(e_ident, 16);
 
-  WriteHalf(ET_DYN);  // Shared library.
+  WriteHalf(elf::ET_DYN);  // Shared library.
 
 #if defined(TARGET_ARCH_IA32)
-  WriteHalf(EM_386);
+  WriteHalf(elf::EM_386);
 #elif defined(TARGET_ARCH_X64)
-  WriteHalf(EM_X86_64);
+  WriteHalf(elf::EM_X86_64);
 #elif defined(TARGET_ARCH_ARM)
-  WriteHalf(EM_ARM);
+  WriteHalf(elf::EM_ARM);
 #elif defined(TARGET_ARCH_ARM64)
-  WriteHalf(EM_AARCH64);
+  WriteHalf(elf::EM_AARCH64);
 #else
   // E.g., DBC.
   FATAL("Unknown ELF architecture");
 #endif
 
-  WriteWord(EV_CURRENT);  // Version
+  WriteWord(elf::EV_CURRENT);  // Version
   WriteAddr(0);           // "Entry point"
   WriteOff(program_table_file_offset_);
   WriteOff(section_table_file_offset_);
 
 #if defined(TARGET_ARCH_ARM)
-  uword flags = EF_ARM_ABI |
-                (TargetCPUFeatures::hardfp_supported() ? EF_ARM_ABI_FLOAT_HARD
-                                                       : EF_ARM_ABI_FLOAT_SOFT);
+  uword flags = elf::EF_ARM_ABI | (TargetCPUFeatures::hardfp_supported()
+                                       ? elf::EF_ARM_ABI_FLOAT_HARD
+                                       : elf::EF_ARM_ABI_FLOAT_SOFT);
 #else
   uword flags = 0;
 #endif
@@ -607,17 +575,17 @@
     ASSERT(kNumImplicitSegments == 3);
     const intptr_t start = stream_->position();
 #if defined(TARGET_ARCH_IS_32_BIT)
-    WriteWord(PT_PHDR);
+    WriteWord(elf::PT_PHDR);
     WriteOff(program_table_file_offset_);   // File offset.
     WriteAddr(program_table_file_offset_);  // Virtual address.
     WriteAddr(program_table_file_offset_);  // Physical address, not used.
     WriteWord(program_table_file_size_);
     WriteWord(program_table_file_size_);
-    WriteWord(PF_R);
+    WriteWord(elf::PF_R);
     WriteWord(kPageSize);
 #else
-    WriteWord(PT_PHDR);
-    WriteWord(PF_R);
+    WriteWord(elf::PT_PHDR);
+    WriteWord(elf::PF_R);
     WriteOff(program_table_file_offset_);   // File offset.
     WriteAddr(program_table_file_offset_);  // Virtual address.
     WriteAddr(program_table_file_offset_);  // Physical address, not used.
@@ -642,17 +610,17 @@
     ASSERT(kNumImplicitSegments == 3);
     const intptr_t start = stream_->position();
 #if defined(TARGET_ARCH_IS_32_BIT)
-    WriteWord(PT_LOAD);
+    WriteWord(elf::PT_LOAD);
     WriteOff(0);   // File offset.
     WriteAddr(0);  // Virtual address.
     WriteAddr(0);  // Physical address, not used.
     WriteWord(program_table_file_offset_ + program_table_file_size_);
     WriteWord(program_table_file_offset_ + program_table_file_size_);
-    WriteWord(PF_R);
+    WriteWord(elf::PF_R);
     WriteWord(kPageSize);
 #else
-    WriteWord(PT_LOAD);
-    WriteWord(PF_R);
+    WriteWord(elf::PT_LOAD);
+    WriteWord(elf::PF_R);
     WriteOff(0);   // File offset.
     WriteAddr(0);  // Virtual address.
     WriteAddr(0);  // Physical address, not used.
@@ -696,7 +664,7 @@
     ASSERT(kNumImplicitSegments == 3);
     const intptr_t start = stream_->position();
 #if defined(TARGET_ARCH_IS_32_BIT)
-    WriteWord(PT_DYNAMIC);
+    WriteWord(elf::PT_DYNAMIC);
     WriteOff(dynamic_->file_offset);
     WriteAddr(dynamic_->memory_offset);  // Virtual address.
     WriteAddr(dynamic_->memory_offset);  // Physical address, not used.
@@ -705,7 +673,7 @@
     WriteWord(dynamic_->segment_flags);
     WriteWord(dynamic_->alignment);
 #else
-    WriteWord(PT_DYNAMIC);
+    WriteWord(elf::PT_DYNAMIC);
     WriteWord(dynamic_->segment_flags);
     WriteOff(dynamic_->file_offset);
     WriteAddr(dynamic_->memory_offset);  // Virtual address.
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 42d44cc..d7b0a9f 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -165,6 +165,10 @@
   C(stress_async_stacks, false, false, bool, false,                            \
     "Stress test async stack traces")                                          \
   P(use_bare_instructions, bool, true, "Enable bare instructions mode.")       \
+  P(show_invisible_frames, bool, false,                                        \
+    "Show invisible frames in stack traces.")                                  \
+  R(show_invisible_isolates, false, bool, false,                               \
+    "Show invisible isolates in the vm-service.")                              \
   R(support_disassembler, false, bool, true, "Support the disassembler.")      \
   R(support_il_printer, false, bool, true, "Support the IL printer.")          \
   C(support_reload, false, false, bool, true, "Support isolate reload.")       \
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index bd6f62b..a926493 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -6,6 +6,7 @@
 
 #include "platform/assert.h"
 #include "vm/compiler/backend/code_statistics.h"
+#include "vm/compiler/runtime_api.h"
 #include "vm/dwarf.h"
 #include "vm/elf.h"
 #include "vm/hash.h"
@@ -80,6 +81,7 @@
                      reinterpret_cast<const void*>(body_b), body_size);
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 ImageWriter::ImageWriter(Heap* heap,
                          const void* shared_objects,
                          const void* shared_instructions,
@@ -219,7 +221,7 @@
 }
 
 static constexpr intptr_t kSimarmX64InstructionsAlignment =
-    compiler::target::ObjectAlignment::kObjectAlignment;
+    2 * compiler::target::ObjectAlignment::kObjectAlignment;
 static intptr_t InstructionsSizeInSnapshot(intptr_t len) {
   const intptr_t header_size = Utils::RoundUp(3 * compiler::target::kWordSize,
                                               kSimarmX64InstructionsAlignment);
@@ -677,7 +679,8 @@
       text_offset += WriteByteSequence(beginning, entry);
 #endif  // defined(IS_SIMARM_X64)
 
-      ASSERT((text_offset - instr_start) == insns.HeaderSize());
+      ASSERT((text_offset - instr_start) ==
+             compiler::target::Instructions::HeaderSize());
     }
 
     // 2. Write a label at the entry point.
@@ -753,9 +756,9 @@
 #else
       text_offset += WriteByteSequence(entry, end);
 #endif
+      ASSERT(kWordSize != compiler::target::kWordSize ||
+             (text_offset - instr_start) == insns.raw()->HeapSize());
     }
-
-    ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
   }
 
   FrameUnwindEpilogue();
@@ -1075,11 +1078,13 @@
                       instructions_blob_stream_.bytes_written());
     ASSERT(segment_base == segment_base2);
 
-    const intptr_t real_bss_base = elf_->AddBSSData("_kDartVMBSSData", 8);
+    const intptr_t real_bss_base =
+        elf_->AddBSSData("_kDartVMBSSData", sizeof(compiler::target::uword));
     ASSERT(bss_base == real_bss_base);
   }
 #endif
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 ImageReader::ImageReader(const uint8_t* data_image,
                          const uint8_t* instructions_image,
@@ -1143,6 +1148,7 @@
   return result;
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void DropCodeWithoutReusableInstructions(const void* reused_instructions) {
   class DropCodeVisitor : public FunctionVisitor, public ClassVisitor {
    public:
@@ -1242,5 +1248,6 @@
   ProgramVisitor::VisitClasses(&visitor);
   ProgramVisitor::VisitFunctions(&visitor);
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 427163e..03415ac 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 = 32;
+static const uint32_t kMaxSupportedKernelFormatVersion = 33;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -60,6 +60,7 @@
   V(ConstructorInvocation, 31)                                                 \
   V(ConstConstructorInvocation, 32)                                            \
   V(Not, 33)                                                                   \
+  V(NullCheck, 117)                                                            \
   V(LogicalExpression, 34)                                                     \
   V(ConditionalExpression, 35)                                                 \
   V(StringConcatenation, 36)                                                   \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 007878e..e06b85a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -84,7 +84,6 @@
 
 DECLARE_FLAG(bool, dual_map_code);
 DECLARE_FLAG(bool, intrinsify);
-DECLARE_FLAG(bool, show_invisible_frames);
 DECLARE_FLAG(bool, trace_deoptimization);
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
 DECLARE_FLAG(bool, trace_reload);
@@ -12495,21 +12494,6 @@
   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;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 33a9dad..81bc595 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4791,16 +4791,17 @@
   }
 
   static intptr_t InstanceSize(intptr_t size) {
-    // OS::PreferredCodeAlignment() is smaller than kObjectAlignment for
-    // simarm_x64.
-    const intptr_t alignment =
-        Utils::Maximum(OS::PreferredCodeAlignment(), kObjectAlignment);
-    return Utils::RoundUp(HeaderSize() + size, alignment);
+    intptr_t instructions_size =
+        Utils::RoundUp(size, OS::PreferredCodeAlignment());
+    intptr_t result = instructions_size + HeaderSize();
+    ASSERT(result % OS::PreferredCodeAlignment() == 0);
+    return result;
   }
 
   static intptr_t HeaderSize() {
-    intptr_t alignment = OS::PreferredCodeAlignment();
-    intptr_t aligned_size = Utils::RoundUp(sizeof(RawInstructions), alignment);
+    const intptr_t alignment = OS::PreferredCodeAlignment();
+    const intptr_t aligned_size =
+        Utils::RoundUp(sizeof(RawInstructions), alignment);
     return aligned_size;
   }
 
@@ -4819,8 +4820,19 @@
     return memcmp(a->ptr(), b->ptr(), InstanceSize(Size(a))) == 0;
   }
 
-  CodeStatistics* stats() const;
-  void set_stats(CodeStatistics* stats) const;
+  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
+  }
 
   uword unchecked_entrypoint_pc_offset() const {
     return raw_ptr()->unchecked_entrypoint_pc_offset_;
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 1fe1f7a..221a326 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -124,6 +124,8 @@
   RW(Function, async_star_move_next_helper)                                    \
   RW(Function, complete_on_async_return)                                       \
   RW(Class, async_star_stream_controller)                                      \
+  RW(GrowableObjectArray, llvm_constant_pool)                                  \
+  RW(Array, llvm_constant_hash_table)                                          \
   RW(ObjectPool, global_object_pool)                                           \
   RW(Array, unique_dynamic_targets)                                            \
   RW(GrowableObjectArray, megamorphic_cache_table)                             \
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index f36bf2e..af98eb1 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 = 16;
+  static const int kMaxPreferredCodeAlignment = 32;
 
   // Returns the preferred code alignment or zero if
   // the platform doesn't care. Guaranteed to be a power of two.
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 9c105a9..38168ad 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 = 16;
+  const int kMinimumAlignment = 32;
 #elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 8;
+  const int kMinimumAlignment = 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 56dc743..4eaae29 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 = 16;
+  const int kMinimumAlignment = 32;
 #elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 8;
+  const int kMinimumAlignment = 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 65541b0..9baba7e 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 = 16;
+  const int kMinimumAlignment = 32;
 #elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 8;
+  const int kMinimumAlignment = 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 5518b4a..4788b6c 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 = 16;
+  const int kMinimumAlignment = 32;
 #elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 8;
+  const int kMinimumAlignment = 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index fa7a880..c0f8e39 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -191,12 +191,12 @@
 }
 
 intptr_t OS::PreferredCodeAlignment() {
-  ASSERT(16 <= OS::kMaxPreferredCodeAlignment);
+  ASSERT(32 <= OS::kMaxPreferredCodeAlignment);
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
     defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  return 16;
+  return 32;
 #elif defined(TARGET_ARCH_ARM)
-  return 8;
+  return 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index db033d0..c8b057a 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -21,7 +21,6 @@
 
 DECLARE_FLAG(int, max_profile_depth);
 DECLARE_FLAG(int, profile_period);
-DECLARE_FLAG(bool, show_invisible_frames);
 DECLARE_FLAG(bool, profile_vm);
 
 #ifndef PRODUCT
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 1820fa8..9a33d1b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1478,6 +1478,15 @@
   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); }
 
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 26d4946..9dec549 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -116,20 +116,18 @@
       return function.raw();
     }
     // Getter invocation might actually be a method extraction.
-    if (FLAG_lazy_dispatchers) {
-      if (is_getter && function.IsNull()) {
-        function = cls.LookupDynamicFunction(demangled);
-        if (!function.IsNull()) {
-          if (allow_add) {
-            // We were looking for the getter but found a method with the same
-            // name. Create a method extractor and return it.
-            // The extractor does not exist yet, so using GetMethodExtractor is
-            // not necessary here.
-            function = function.CreateMethodExtractor(function_name);
-            return function.raw();
-          } else {
-            return Function::null();
-          }
+    if (is_getter && function.IsNull()) {
+      function = cls.LookupDynamicFunction(demangled);
+      if (!function.IsNull()) {
+        if (allow_add && FLAG_lazy_dispatchers) {
+          // We were looking for the getter but found a method with the same
+          // name. Create a method extractor and return it.
+          // The extractor does not exist yet, so using GetMethodExtractor is
+          // not necessary here.
+          function = function.CreateMethodExtractor(function_name);
+          return function.raw();
+        } else {
+          return Function::null();
         }
       }
     }
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 68cc4a7..43225fb 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -950,7 +950,8 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
-  ASSERT(!Isolate::IsVMInternalIsolate(isolate));
+  ASSERT(FLAG_show_invisible_isolates ||
+         !Isolate::IsVMInternalIsolate(isolate));
 
   if (FLAG_trace_service) {
     OS::PrintErr(
@@ -4280,7 +4281,7 @@
   virtual ~ServiceIsolateVisitor() {}
 
   void VisitIsolate(Isolate* isolate) {
-    if (!IsVMInternalIsolate(isolate)) {
+    if (FLAG_show_invisible_isolates || !IsVMInternalIsolate(isolate)) {
       jsarr_->AddValue(isolate);
     }
   }
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index b91b660..c37a63f 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1110,8 +1110,8 @@
 ### setFlag
 
 ```
-Success setFlag(string name,
-                string value)
+Success|Error setFlag(string name,
+                      string value)
 ```
 
 The _setFlag_ RPC is used to set a VM flag at runtime. Returns an error if the
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 1587330..e7441e1 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -35,7 +35,8 @@
       timestamp_(OS::GetCurrentTimeMillis()) {
   // We should never generate events for the vm or service isolates.
   ASSERT(isolate_ != Dart::vm_isolate());
-  ASSERT(isolate == NULL || !Isolate::IsVMInternalIsolate(isolate));
+  ASSERT(isolate == NULL || FLAG_show_invisible_isolates ||
+         !Isolate::IsVMInternalIsolate(isolate));
 
   if ((event_kind == ServiceEvent::kPauseStart) ||
       (event_kind == ServiceEvent::kPauseExit)) {
@@ -180,7 +181,11 @@
   PrintJSONHeader(&jsobj);
   if (kind() == kVMFlagUpdate) {
     jsobj.AddProperty("flag", flag_name());
+    // For backwards compatibility, "new_value" is also provided.
+    // TODO(bkonyi): remove when service protocol major version is incremented.
+    ASSERT(SERVICE_PROTOCOL_MAJOR_VERSION == 3);
     jsobj.AddProperty("new_value", flag_new_value());
+    jsobj.AddProperty("newValue", flag_new_value());
   }
   if (kind() == kIsolateReload) {
     if (reload_error_ == NULL) {
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index b01182b..6bd77f4 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -219,7 +219,7 @@
   }
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
-  if (Isolate::IsVMInternalIsolate(isolate)) {
+  if (!FLAG_show_invisible_isolates && Isolate::IsVMInternalIsolate(isolate)) {
     return false;
   }
   ASSERT(isolate != NULL);
@@ -245,7 +245,7 @@
   }
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
-  if (Isolate::IsVMInternalIsolate(isolate)) {
+  if (!FLAG_show_invisible_isolates && Isolate::IsVMInternalIsolate(isolate)) {
     return false;
   }
   ASSERT(isolate != NULL);
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 5a89221..394f45b 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -11,8 +11,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, show_invisible_frames);
-
 class StackTraceUtils : public AllStatic {
  public:
   /// Counts the number of stack frames.
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index ac2c84a..d4195bd 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -538,8 +538,9 @@
           klass, declaration_type_args);
     }
   } else {
-    // It can also be a phi node where the inputs are any of the above.
-    ASSERT(type_arguments->IsPhi());
+    // It can also be a phi node where the inputs are any of the above,
+    // or it could be the result of _prependTypeArguments call.
+    ASSERT(type_arguments->IsPhi() || type_arguments->IsStaticCall());
   }
 }
 
diff --git a/runtime/vm/utils_test.cc b/runtime/vm/utils_test.cc
index 7234392..59d4b24 100644
--- a/runtime/vm/utils_test.cc
+++ b/runtime/vm/utils_test.cc
@@ -230,6 +230,7 @@
   EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32be)[1]);
   EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value32be)[2]);
   EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32be)[3]);
+  EXPECT_EQ(0xf1f2u, Utils::BigEndianToHost32(value32be));
 
   uint32_t value32le = Utils::HostToLittleEndian32(0xf1f2);
   EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32le)[0]);
@@ -256,6 +257,7 @@
   EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[5]);
   EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[6]);
   EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[7]);
+  EXPECT_EQ(0xf1f2f3f4ul, Utils::LittleEndianToHost64(value64le));
 }
 
 VM_UNIT_TEST_CASE(DoublesBitEqual) {
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 2eb4372..fcd0f5e 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -57,9 +57,9 @@
                                         bool is_executable,
                                         const char* name);
 
+  // Returns the cached page size. Use only if Init() has been called.
   static intptr_t PageSize() {
     ASSERT(page_size_ != 0);
-    ASSERT(Utils::IsPowerOfTwo(page_size_));
     return page_size_;
   }
 
@@ -76,6 +76,8 @@
   static VirtualMemory* ForImagePage(void* pointer, uword size);
 
  private:
+  static intptr_t CalculatePageSize();
+
   // Free a sub segment. On operating systems that support it this
   // can give back the virtual memory to the system. Returns true on success.
   static void FreeSubSegment(void* address, intptr_t size);
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index 09e946d..4f2aa78 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -40,8 +40,15 @@
 
 uword VirtualMemory::page_size_ = 0;
 
+intptr_t VirtualMemory::CalculatePageSize() {
+  const intptr_t page_size = getpagesize();
+  ASSERT(page_size != 0);
+  ASSERT(Utils::IsPowerOfTwo(page_size));
+  return page_size;
+}
+
 void VirtualMemory::Init() {
-  page_size_ = getpagesize();
+  page_size_ = CalculatePageSize();
 }
 
 static void Unmap(zx_handle_t vmar, uword start, uword end) {
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index 87cbc04..bf4fed7 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -42,8 +42,20 @@
 
 uword VirtualMemory::page_size_ = 0;
 
+intptr_t VirtualMemory::CalculatePageSize() {
+  const intptr_t page_size = getpagesize();
+  ASSERT(page_size != 0);
+  ASSERT(Utils::IsPowerOfTwo(page_size));
+  return page_size;
+}
+
 void VirtualMemory::Init() {
-  page_size_ = getpagesize();
+  if (page_size_ != 0) {
+    // Already initialized.
+    return;
+  }
+
+  page_size_ = CalculatePageSize();
 
 #if defined(DUAL_MAPPING_SUPPORTED)
 // Perf is Linux-specific and the flags aren't defined in Product.
@@ -62,7 +74,7 @@
   // such as on docker containers, and disable dual mapping in this case.
   // Also detect for missing support of memfd_create syscall.
   if (FLAG_dual_map_code) {
-    intptr_t size = page_size_;
+    intptr_t size = PageSize();
     intptr_t alignment = 256 * 1024;  // e.g. heap page size.
     VirtualMemory* vm = AllocateAligned(size, alignment, true, NULL);
     if (vm == NULL) {
@@ -167,10 +179,10 @@
   //
   // If FLAG_dual_map_code is active, the executable mapping will be mapped RX
   // immediately and never changes protection until it is eventually unmapped.
-  ASSERT(Utils::IsAligned(size, page_size_));
+  ASSERT(Utils::IsAligned(size, PageSize()));
   ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(Utils::IsAligned(alignment, page_size_));
-  const intptr_t allocated_size = size + alignment - page_size_;
+  ASSERT(Utils::IsAligned(alignment, PageSize()));
+  const intptr_t allocated_size = size + alignment - PageSize();
 #if defined(DUAL_MAPPING_SUPPORTED)
   int fd = -1;
   const bool dual_mapping =
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 33d4edbc..d52ea07 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -18,10 +18,17 @@
 
 uword VirtualMemory::page_size_ = 0;
 
-void VirtualMemory::Init() {
+intptr_t VirtualMemory::CalculatePageSize() {
   SYSTEM_INFO info;
   GetSystemInfo(&info);
-  page_size_ = info.dwPageSize;
+  const intptr_t page_size = info.dwPageSize;
+  ASSERT(page_size != 0);
+  ASSERT(Utils::IsPowerOfTwo(page_size));
+  return page_size;
+}
+
+void VirtualMemory::Init() {
+  page_size_ = CalculatePageSize();
 }
 
 bool VirtualMemory::DualMappingEnabled() {
@@ -35,10 +42,10 @@
   // When FLAG_write_protect_code is active, code memory (indicated by
   // is_executable = true) is allocated as non-executable and later
   // changed to executable via VirtualMemory::Protect.
-  ASSERT(Utils::IsAligned(size, page_size_));
+  ASSERT(Utils::IsAligned(size, PageSize()));
   ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(Utils::IsAligned(alignment, page_size_));
-  intptr_t reserved_size = size + alignment - page_size_;
+  ASSERT(Utils::IsAligned(alignment, PageSize()));
+  intptr_t reserved_size = size + alignment - PageSize();
   int prot = (is_executable && !FLAG_write_protect_code)
                  ? PAGE_EXECUTE_READWRITE
                  : PAGE_READWRITE;
diff --git a/sdk/bin/dartdevc_sdk b/sdk/bin/dartdevc_sdk
index 60d2fe1..6cba7d8 100755
--- a/sdk/bin/dartdevc_sdk
+++ b/sdk/bin/dartdevc_sdk
@@ -25,4 +25,14 @@
 
 # We are running the snapshot in the built SDK.
 DART="$BIN_DIR/dart"
-exec "$DART" "$SNAPSHOT" "$@"
+
+unset EXTRA_VM_OPTIONS
+declare -a EXTRA_VM_OPTIONS
+
+# We allow extra vm options to be passed in through an environment variable.
+if [[ $DART_VM_OPTIONS ]]; then
+  read -a OPTIONS <<< "$DART_VM_OPTIONS"
+  EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
+fi
+
+exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "$@"
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
index 5dbf707..ce027a9 100644
--- a/sdk/bin/dartdevc_sdk.bat
+++ b/sdk/bin/dartdevc_sdk.bat
@@ -22,7 +22,14 @@
 
 set SDK_ARG=--dart-sdk=%SDK_DIR%
 
-"%DART%" "%SNAPSHOT%" "%SDK_ARG%" %*
+set EXTRA_VM_OPTIONS=
+
+rem We allow extra vm options to be passed in through an environment variable.
+if not "_%DART_VM_OPTIONS%_" == "__" (
+  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
+)
+
+"%DART%" %EXTRA_VM_OPTIONS% "%SNAPSHOT%" "%SDK_ARG%" %*
 
 endlocal
 
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 83421ab..49c7df3 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
@@ -523,6 +523,7 @@
 ///
 /// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
+  if (!dart.isDartFunction(f)) return f;
   var ret = _interopExpando[f];
   if (ret == null) {
     ret = JS(
@@ -547,6 +548,7 @@
 ///
 /// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
+  if (!dart.isDartFunction(f)) return f;
   var ret = _interopCaptureThisExpando[f];
   if (ret == null) {
     ret = JS(
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 3175eeb..f59c330 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -92,6 +92,10 @@
   return f;
 }
 
+bool isDartFunction(obj) =>
+    JS<bool>('!', '# instanceof Function', obj) &&
+    JS<bool>('!', '#[#] != null', obj, _runtimeType);
+
 /// The Dart type that represents a JavaScript class(/constructor) type.
 ///
 /// The JavaScript type may not exist, either because it's not loaded yet, or
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 780f6c0..15d13e2 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -363,6 +363,11 @@
 @pragma('dart2js:noInline')
 Rti instantiatedGenericFunctionType(
     Rti genericFunctionRti, Rti instantiationRti) {
+  // If --lax-runtime-type-to-string is enabled and we never check the function
+  // type, then the function won't have a signature, so its RTI will be null. In
+  // this case, there is nothing to instantiate, so we return `null` and the
+  // instantiation appears to be an interface type instead.
+  if (genericFunctionRti == null) return null;
   var bounds = Rti._getGenericFunctionBounds(genericFunctionRti);
   var typeArguments = Rti._getInterfaceTypeArguments(instantiationRti);
   assert(_Utils.arrayLength(bounds) == _Utils.arrayLength(typeArguments));
diff --git a/sdk/lib/_internal/vm/lib/wasm_patch.dart b/sdk/lib/_internal/vm/lib/wasm_patch.dart
index f0c2794..1637384 100644
--- a/sdk/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk/lib/_internal/vm/lib/wasm_patch.dart
@@ -60,6 +60,7 @@
   }
 
   void _init(Uint8List data) native 'Wasm_initModule';
+  String describe() native 'Wasm_describeModule';
 }
 
 class _NativeWasmImports extends NativeFieldWrapperClass1
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 95a8b97..66df3dc 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1096,9 +1096,9 @@
    * When subscribing using [drain], cancelOnError will be true. This means
    * that the future will complete with the first error on this stream and then
    * cancel the subscription.
-   * If this stream emits an error, or the call to [combine] throws,
-   * the returned future is completed with that error,
-   * and processing is stopped.
+   *
+   * If this stream emits an error, the returned future is completed with
+   * that error, and processing is stopped.
    *
    * In case of a `done` event the future completes with the given
    * [futureValue].
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index ce522be..7ebd1d5 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -35,18 +35,18 @@
 
 /// Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
 ///
-/// Shorthand for [base64.encode]. Useful if a local variable shadows the global
+/// Shorthand for `base64.encode`. Useful if a local variable shadows the global
 /// [base64] constant.
 String base64Encode(List<int> bytes) => base64.encode(bytes);
 
 /// Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding.
 ///
-/// Shorthand for [base64url.encode].
+/// Shorthand for `base64url.encode`.
 String base64UrlEncode(List<int> bytes) => base64Url.encode(bytes);
 
 /// Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes.
 ///
-/// Shorthand for [base64.decode]. Useful if a local variable shadows the
+/// Shorthand for `base64.decode`. Useful if a local variable shadows the
 /// global [base64] constant.
 Uint8List base64Decode(String source) => base64.decode(source);
 
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index 5746e52..97216f7 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.dart
@@ -74,10 +74,10 @@
 /// If [toEncodable] is omitted, it defaults to a function that returns the
 /// result of calling `.toJson()` on the unencodable object.
 ///
-/// Shorthand for [json.encode]. Useful if a local variable shadows the global
+/// Shorthand for `json.encode`. Useful if a local variable shadows the global
 /// [json] constant.
-String jsonEncode(Object object, {Object toEncodable(Object nonEncodable)}) =>
-    json.encode(object, toEncodable: toEncodable);
+String jsonEncode(Object value, {Object toEncodable(Object nonEncodable)}) =>
+    json.encode(value, toEncodable: toEncodable);
 
 /// Parses the string and returns the resulting Json object.
 ///
@@ -88,7 +88,7 @@
 ///
 /// The default [reviver] (when not provided) is the identity function.
 ///
-/// Shorthand for [json.decode]. Useful if a local variable shadows the global
+/// Shorthand for `json.decode`. Useful if a local variable shadows the global
 /// [json] constant.
 dynamic jsonDecode(String source, {Object reviver(Object key, Object value)}) =>
     json.decode(source, reviver: reviver);
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index f914fe1..21d3945 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -83,7 +83,7 @@
    * Creates an identity map with the default implementation, [LinkedHashMap].
    *
    * An identity map uses [identical] for equality and [identityHashCode]
-   * for hash codes of keys instead of the intrinsic [Object.operator==] and
+   * for hash codes of keys instead of the intrinsic [Object.==] and
    * [Object.hashCode] of the keys.
    *
    * The returned map allows `null` as a key.
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index b3046cc..9bd68ba 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -152,7 +152,7 @@
    * character is a line terminator. When true, then the "." character will
    * match any single character including line terminators.
    *
-   * This feature is distinct from [isMultiline], as they affect the behavior
+   * This feature is distinct from [isMultiLine], as they affect the behavior
    * of different pattern characters, and so they can be used together or
    * separately.
    */
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 303ec9e..a8ce5d6 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -25457,15 +25457,7 @@
 @Native("RTCIceCandidate,mozRTCIceCandidate")
 class RtcIceCandidate extends Interceptor {
   factory RtcIceCandidate(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS(
-        '',
-        'window[#]',
-        Device.isFirefox
-            ? '${Device.propertyPrefix}RTCIceCandidate'
-            : 'RTCIceCandidate');
+    var constructorName = JS('', 'window[#]', 'RTCIceCandidate');
     return JS('RtcIceCandidate', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
@@ -25511,8 +25503,8 @@
 @Native("RTCPeerConnection,webkitRTCPeerConnection,mozRTCPeerConnection")
 class RtcPeerConnection extends EventTarget {
   factory RtcPeerConnection(Map rtcIceServers, [Map mediaConstraints]) {
-    var constructorName = JS('RtcPeerConnection', 'window[#]',
-        '${Device.propertyPrefix}RTCPeerConnection');
+    var constructorName =
+        JS('RtcPeerConnection', 'window[#]', 'RTCPeerConnection');
     if (mediaConstraints != null) {
       return JS(
           'RtcPeerConnection',
@@ -25847,15 +25839,7 @@
 @Native("RTCSessionDescription,mozRTCSessionDescription")
 class RtcSessionDescription extends Interceptor {
   factory RtcSessionDescription(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS(
-        '',
-        'window[#]',
-        Device.isFirefox
-            ? '${Device.propertyPrefix}RTCSessionDescription'
-            : 'RTCSessionDescription');
+    var constructorName = JS('', 'window[#]', 'RTCSessionDescription');
     return JS('RtcSessionDescription', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
@@ -34974,7 +34958,7 @@
     // always dealing with pixels in this method.
     var styles = _element.getComputedStyle();
 
-    var val = 0;
+    num val = 0;
 
     for (String measurement in dimensions) {
       // The border-box and default box model both exclude margin in the regular
diff --git a/sdk/lib/html/html_sources.gni b/sdk/lib/html/html_sources.gni
new file mode 100644
index 0000000..524b6dd
--- /dev/null
+++ b/sdk/lib/html/html_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+html_sdk_sources = [ "dart2js/html_dart2js.dart" ]
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index df60490..d51c616 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -406,16 +406,16 @@
   IPPROTO_UDP, // 6
 }
 
-/// The [RawSocketOption] is used as a parameter to [Socket.setRawOption] and
-/// [RawSocket.setRawOption] to set customize the behaviour of the underlying
-/// socket.
+/// The [RawSocketOption] is used as a parameter to [Socket.setRawOption],
+/// [RawSocket.setRawOption], and [RawDatagramSocket.setRawOption] to customize
+/// the behaviour of the underlying socket.
 ///
-/// It allows for fine grained control of the socket options, and its values will
-/// be passed to the underlying platform's implementation of setsockopt and
-/// getsockopt.
+/// It allows for fine grained control of the socket options, and its values
+/// will be passed to the underlying platform's implementation of `setsockopt`
+/// and `getsockopt`.
 @Since("2.2")
 class RawSocketOption {
-  /// Creates a RawSocketOption for getRawOption andSetRawOption.
+  /// Creates a [RawSocketOption] for `getRawOption` and `setRawOption`.
   ///
   /// All arguments are required and must not be null.
   ///
@@ -425,10 +425,10 @@
   /// The value argument and its length correspond to the optval and length
   /// arguments on the native call.
   ///
-  /// For a [getRawOption] call, the value parameter will be updated after a
+  /// For a `getRawOption` call, the value parameter will be updated after a
   /// successful call (although its length will not be changed).
   ///
-  /// For a [setRawOption] call, the value parameter will be used set the
+  /// For a `setRawOption` call, the value parameter will be used set the
   /// option.
   const RawSocketOption(this.level, this.option, this.value);
 
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 4086f08..cc8c7df 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -39,7 +39,7 @@
    * Blocks until a full line is available.
    *
    * Lines my be terminated by either `<CR><LF>` or `<LF>`. On Windows in cases
-   * where the [stdioType] of stdin is [StdioType.termimal] the terminator may
+   * where the [stdioType] of stdin is [StdioType.terminal] the terminator may
    * also be a single `<CR>`.
    *
    * Input bytes are converted to a string by [encoding].
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 23656d7..9c37ea8 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -56,7 +56,7 @@
 /// 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.
+/// [JsFunction], which has a [JsFunction.apply] method to invoke it.
 ///
 /// The following types are transferred directly and not proxied:
 ///
diff --git a/sdk/lib/js/js_sources.gni b/sdk/lib/js/js_sources.gni
new file mode 100644
index 0000000..91f6d0c
--- /dev/null
+++ b/sdk/lib/js/js_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+js_sdk_sources = [ "dart2js/js_dart2js.dart" ]
diff --git a/sdk/lib/js_util/js_util_sources.gni b/sdk/lib/js_util/js_util_sources.gni
new file mode 100644
index 0000000..3b7c1b1
--- /dev/null
+++ b/sdk/lib/js_util/js_util_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+js_util_sdk_sources = [ "dart2js/js_util_dart2js.dart" ]
diff --git a/sdk/lib/math/random.dart b/sdk/lib/math/random.dart
index 80e588b..e2e9d91 100644
--- a/sdk/lib/math/random.dart
+++ b/sdk/lib/math/random.dart
@@ -9,7 +9,7 @@
 /// The default implementation supplies a stream of pseudo-random bits that are
 /// not suitable for cryptographic purposes.
 ///
-/// Use the [Random.secure]() constructor for cryptographic purposes.
+/// Use the [Random.secure] constructor for cryptographic purposes.
 abstract class Random {
   /// Creates a random number generator.
   ///
diff --git a/sdk/lib/wasm/wasm.dart b/sdk/lib/wasm/wasm.dart
index a9a09cc..9fe5ba1 100644
--- a/sdk/lib/wasm/wasm.dart
+++ b/sdk/lib/wasm/wasm.dart
@@ -30,6 +30,9 @@
 
   // Instantiate the module with the given imports.
   WasmInstance instantiate(WasmImports imports);
+
+  // Describes the imports and exports that the module expects, for debugging.
+  String describe();
 }
 
 // WasmImports holds all the imports for a WasmInstance.
diff --git a/sdk_nnbd/BUILD.gn b/sdk_nnbd/BUILD.gn
index 9a4a1c5..6d96000 100644
--- a/sdk_nnbd/BUILD.gn
+++ b/sdk_nnbd/BUILD.gn
@@ -9,8 +9,8 @@
 #
 # Warning:
 # If you need to copy something into dart-sdk/lib/foo in addition to the stuff
-# copied there by :copy_libraries, then you must depend on ":copy_libraries",
-# or ":copy_libraries" may delete/overwrite your addition, and the build will
+# copied there by :copy_libraries_nnbd, then you must depend on ":copy_libraries_nnbd",
+# or ":copy_libraries_nnbd" may delete/overwrite your addition, and the build will
 # fail.
 
 import("../build/dart/copy_tree.gni")
@@ -18,12 +18,15 @@
 
 declare_args() {
   # Build a SDK with less stuff. It excludes dart2js, ddc, and web libraries.
-  dart_platform_sdk = true
+  dart_platform_sdk_nnbd = true
 
   # Path to stripped dart binaries relative to build output directory.
-  dart_stripped_binary = "dart"
-  dartaotruntime_stripped_binary = "dartaotruntime"
-  gen_snapshot_stripped_binary = "gen_snapshot"
+  # TODO(rnystrom): These should use different filenames once the runtime's
+  # BUILD.gn file has additional rules to generate the NNBD versions of these
+  # executables.
+  dart_stripped_binary_nnbd = "dart"
+  dartaotruntime_stripped_binary_nnbd = "dartaotruntime"
+  gen_snapshot_stripped_binary_nnbd = "gen_snapshot"
 }
 
 # The directory layout of the SDK is as follows:
@@ -252,10 +255,10 @@
 # bin/resources/dartdoc/templates
 copy_tree_specs += [
   {
-    target = "copy_dartdoc_templates"
-    visibility = [ ":copy_dartdoc_files" ]
+    target = "copy_dartdoc_templates_nnbd"
+    visibility = [ ":copy_dartdoc_files_nnbd" ]
     source = "../third_party/pkg/dartdoc/lib/templates"
-    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/templates"
+    dest = "$root_out_dir/dart-sdk-nnbd/bin/resources/dartdoc/templates"
     ignore_patterns = "{}"
   },
 ]
@@ -264,10 +267,10 @@
 # bin/resources/dartdoc/resources
 copy_tree_specs += [
   {
-    target = "copy_dartdoc_resources"
-    visibility = [ ":copy_dartdoc_files" ]
+    target = "copy_dartdoc_resources_nnbd"
+    visibility = [ ":copy_dartdoc_files_nnbd" ]
     source = "../third_party/pkg/dartdoc/lib/resources"
-    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/resources"
+    dest = "$root_out_dir/dart-sdk-nnbd/bin/resources/dartdoc/resources"
     ignore_patterns = "{}"
   },
 ]
@@ -276,13 +279,13 @@
 foreach(library, _full_sdk_libraries) {
   copy_tree_specs += [
     {
-      target = "copy_${library}_library"
+      target = "copy_${library}_library_nnbd"
       visibility = [
-        ":copy_platform_sdk_libraries",
-        ":copy_full_sdk_libraries",
+        ":copy_platform_sdk_libraries_nnbd",
+        ":copy_full_sdk_libraries_nnbd",
       ]
       source = "lib/$library"
-      dest = "$root_out_dir/dart-sdk/lib/$library"
+      dest = "$root_out_dir/dart-sdk-nnbd/lib/$library"
       ignore_patterns = "*.svn,doc,*.py,*.gypi,*.sh,.gitignore"
     },
   ]
@@ -291,13 +294,13 @@
 if (is_win) {
   copy_tree_specs += [
     {
-      target = "copy_7zip"
-      visibility = [ ":create_common_sdk" ]
+      target = "copy_7zip_nnbd"
+      visibility = [ ":create_common_sdk_nnbd" ]
       deps = [
-        ":copy_libraries",
+        ":copy_libraries_nnbd",
       ]
       source = "../third_party/7zip"
-      dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
+      dest = "$root_out_dir/dart-sdk-nnbd/lib/_internal/pub/asset/7zip"
       ignore_patterns = ".svn"
     },
   ]
@@ -306,23 +309,23 @@
 if (target_cpu == "x64") {
   copy_tree_specs += [
     {
-      target = "copy_language_model"
-      visibility = [ ":create_common_sdk" ]
+      target = "copy_language_model_nnbd"
+      visibility = [ ":create_common_sdk_nnbd" ]
       deps = [
-        ":copy_libraries",
+        ":copy_libraries_nnbd",
       ]
       source = "../pkg/analysis_server/language_model"
-      dest = "$root_out_dir/dart-sdk/model"
+      dest = "$root_out_dir/dart-sdk-nnbd/model"
       ignore_patterns = "{}"
     },
     {
-      target = "copy_libtensorflowlite_c"
-      visibility = [ ":create_common_sdk" ]
+      target = "copy_libtensorflowlite_c_nnbd"
+      visibility = [ ":create_common_sdk_nnbd" ]
       deps = [
-        ":copy_libraries",
+        ":copy_libraries_nnbd",
       ]
       source = "../third_party/pkg/tflite_native/lib/src/blobs"
-      dest = "$root_out_dir/dart-sdk/bin/snapshots"
+      dest = "$root_out_dir/dart-sdk-nnbd/bin/snapshots"
       ignore_patterns = "{}"
     },
   ]
@@ -330,7 +333,7 @@
 
 # This generates targets for everything in copy_tree_specs. The targets have the
 # same name as the "target" fields in the scopes of copy_tree_specs.
-copy_trees("copy_trees") {
+copy_trees("copy_trees_nnbd") {
   sources = copy_tree_specs
 }
 
@@ -348,18 +351,19 @@
   # make a link to the symlink rather than the symlink's target, and the
   # relative symlink interpreted from a different containing directory
   # will not find the actual binary.
-  action("copy_dart") {
-    visibility = [ ":create_common_sdk" ]
+  action("copy_dart_nnbd") {
+    visibility = [ ":create_common_sdk_nnbd" ]
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     dart_label = "../runtime/bin:dart"
     deps = [
       dart_label,
     ]
     dart_out = get_label_info(dart_label, "root_out_dir")
     sources = [
-      "$dart_out/$dart_stripped_binary",
+      "$dart_out/$dart_stripped_binary_nnbd",
     ]
     outputs = [
-      "$root_out_dir/dart-sdk/bin/$dart_stripped_binary",
+      "$root_out_dir/dart-sdk-nnbd/bin/$dart_stripped_binary_nnbd",
     ]
     script = "/bin/ln"
     args = [
@@ -369,31 +373,33 @@
     ]
   }
 } else {
-  copy("copy_dart") {
-    visibility = [ ":create_common_sdk" ]
+  copy("copy_dart_nnbd") {
+    visibility = [ ":create_common_sdk_nnbd" ]
     deps = [
+      # TODO(rnystrom): This probably needs to be forked for NNBD.
       "../runtime/bin:dart",
     ]
     dart_out = get_label_info("../runtime/bin:dart", "root_out_dir")
     if (is_win) {
       sources = [
+        # TODO(rnystrom): This probably needs to be forked for NNBD.
         "$dart_out/dart.exe",
       ]
     } else {
       sources = [
-        "$dart_out/$dart_stripped_binary",
+        "$dart_out/$dart_stripped_binary_nnbd",
       ]
     }
     if (is_win) {
       sources += [ "$dart_out/dart.lib" ]
     }
     outputs = [
-      "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
+      "$root_out_dir/dart-sdk-nnbd/bin/{{source_file_part}}",
     ]
   }
 }
 
-copy("copy_dartaotruntime") {
+copy("copy_dartaotruntime_nnbd") {
   deps = [
     "../runtime/bin:dartaotruntime",
   ]
@@ -405,38 +411,40 @@
     ]
   } else {
     sources = [
-      "$dartaotruntime_out/$dartaotruntime_stripped_binary",
+      "$dartaotruntime_out/$dartaotruntime_stripped_binary_nnbd",
     ]
   }
   if (is_win) {
     sources += [ "$dartaotruntime_out/dartaotruntime.lib" ]
   }
   outputs = [
-    "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/bin/{{source_file_part}}",
   ]
 }
 
-copy("copy_gen_snapshot") {
+copy("copy_gen_snapshot_nnbd") {
   deps = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "../runtime/bin:gen_snapshot",
   ]
   gen_snapshot_out =
       get_label_info("../runtime/bin:gen_snapshot", "root_out_dir")
   if (is_win) {
     sources = [
+      # TODO(rnystrom): This probably needs to be forked for NNBD.
       "$gen_snapshot_out/gen_snapshot.exe",
     ]
   } else {
     sources = [
-      "$gen_snapshot_out/$gen_snapshot_stripped_binary",
+      "$gen_snapshot_out/$gen_snapshot_stripped_binary_nnbd",
     ]
   }
   outputs = [
-    "$root_out_dir/dart-sdk/bin/utils/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/bin/utils/{{source_file_part}}",
   ]
 }
 
-copy("copy_dart2aot") {
+copy("copy_dart2aot_nnbd") {
   ext = ""
   if (is_win) {
     ext = ".bat"
@@ -445,14 +453,14 @@
     "bin/dart2aot$ext",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/bin/{{source_file_part}}",
   ]
 }
 
-copy("copy_dart2native") {
+copy("copy_dart2native_nnbd") {
   deps = [
-    ":copy_gen_kernel_snapshot",
-    ":copy_gen_snapshot",
+    ":copy_gen_kernel_snapshot_nnbd",
+    ":copy_gen_snapshot_nnbd",
   ]
   ext = ""
   if (is_win) {
@@ -462,26 +470,27 @@
     "bin/dart2native$ext",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/bin/{{source_file_part}}",
   ]
 }
 
-copy("copy_gen_kernel_snapshot") {
+copy("copy_gen_kernel_snapshot_nnbd") {
   deps = [
     "../utils/gen_kernel",
   ]
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$root_gen_dir/gen_kernel.dart.snapshot",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/bin/snapshots/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/bin/snapshots/{{source_file_part}}",
   ]
 }
 
 # A template for copying the things in _platform_sdk_scripts and
 # _full_sdk_scripts into bin/
-template("copy_sdk_script") {
-  assert(defined(invoker.name), "copy_sdk_script must define 'name'")
+template("copy_sdk_script_nnbd") {
+  assert(defined(invoker.name), "copy_sdk_script_nnbd must define 'name'")
   name = invoker.name
   ext = ""
   if (is_win) {
@@ -489,29 +498,29 @@
   }
   copy(target_name) {
     visibility = [
-      ":copy_platform_sdk_scripts",
-      ":copy_full_sdk_scripts",
+      ":copy_platform_sdk_scripts_nnbd",
+      ":copy_full_sdk_scripts_nnbd",
     ]
     sources = [
       "bin/${name}_sdk$ext",
     ]
     outputs = [
-      "$root_out_dir/dart-sdk/bin/$name$ext",
+      "$root_out_dir/dart-sdk-nnbd/bin/$name$ext",
     ]
   }
 }
 
 foreach(sdk_script, _full_sdk_scripts) {
-  copy_sdk_script("copy_${sdk_script}_script") {
+  copy_sdk_script_nnbd("copy_${sdk_script}_script_nnbd") {
     name = sdk_script
   }
 }
 
 foreach(script, _scripts) {
-  copy("copy_${script}_script") {
+  copy("copy_${script}_script_nnbd") {
     visibility = [
-      ":copy_platform_sdk_scripts",
-      ":copy_full_sdk_scripts",
+      ":copy_platform_sdk_scripts_nnbd",
+      ":copy_full_sdk_scripts_nnbd",
     ]
     ext = ""
     if (is_win) {
@@ -521,159 +530,164 @@
       "bin/$script$ext",
     ]
     outputs = [
-      "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
+      "$root_out_dir/dart-sdk-nnbd/bin/{{source_file_part}}",
     ]
   }
 }
 
 # This is the main target for copying scripts in _platform_sdk_scripts to bin/
-group("copy_platform_sdk_scripts") {
-  visibility = [ ":create_platform_sdk" ]
+group("copy_platform_sdk_scripts_nnbd") {
+  visibility = [ ":create_platform_sdk_nnbd" ]
   public_deps = []
   foreach(sdk_script, _platform_sdk_scripts) {
-    public_deps += [ ":copy_${sdk_script}_script" ]
+    public_deps += [ ":copy_${sdk_script}_script_nnbd" ]
   }
   foreach(script, _scripts) {
-    public_deps += [ ":copy_${script}_script" ]
+    public_deps += [ ":copy_${script}_script_nnbd" ]
   }
 }
 
 # This is the main target for copying scripts in _full_sdk_scripts to bin/
-group("copy_full_sdk_scripts") {
-  visibility = [ ":create_full_sdk" ]
+group("copy_full_sdk_scripts_nnbd") {
+  visibility = [ ":create_full_sdk_nnbd" ]
   public_deps = []
   foreach(sdk_script, _full_sdk_scripts) {
-    public_deps += [ ":copy_${sdk_script}_script" ]
+    public_deps += [ ":copy_${sdk_script}_script_nnbd" ]
   }
   foreach(script, _scripts) {
-    public_deps += [ ":copy_${script}_script" ]
+    public_deps += [ ":copy_${script}_script_nnbd" ]
   }
 }
 
 # This loop generates "copy" targets that put snapshots into bin/snapshots
 foreach(snapshot, _full_sdk_snapshots) {
-  copy("copy_${snapshot[0]}_snapshot") {
+  copy("copy_${snapshot[0]}_snapshot_nnbd") {
     visibility = [
-      ":copy_platform_sdk_snapshots",
-      ":copy_full_sdk_snapshots",
+      ":copy_platform_sdk_snapshots_nnbd",
+      ":copy_full_sdk_snapshots_nnbd",
     ]
     deps = [
       snapshot[1],
     ]
     sources = [
+      # TODO(rnystrom): This probably needs to be forked for NNBD.
       "$root_gen_dir/${snapshot[0]}.dart.snapshot",
     ]
     outputs = [
-      "$root_out_dir/dart-sdk/bin/snapshots/{{source_file_part}}",
+      "$root_out_dir/dart-sdk-nnbd/bin/snapshots/{{source_file_part}}",
     ]
   }
 }
 
 # This is the main rule for copying snapshots from _platform_sdk_snapshots to
 # bin/snapshots
-group("copy_platform_sdk_snapshots") {
-  visibility = [ ":create_platform_sdk" ]
+group("copy_platform_sdk_snapshots_nnbd") {
+  visibility = [ ":create_platform_sdk_nnbd" ]
   public_deps = []
   foreach(snapshot, _platform_sdk_snapshots) {
-    public_deps += [ ":copy_${snapshot[0]}_snapshot" ]
+    public_deps += [ ":copy_${snapshot[0]}_snapshot_nnbd" ]
   }
 }
 
 # This is the main rule for copying snapshots from _full_sdk_snapshots to
 # bin/snapshots
-group("copy_full_sdk_snapshots") {
-  visibility = [ ":create_full_sdk" ]
+group("copy_full_sdk_snapshots_nnbd") {
+  visibility = [ ":create_full_sdk_nnbd" ]
   public_deps = []
   foreach(snapshot, _full_sdk_snapshots) {
-    public_deps += [ ":copy_${snapshot[0]}_snapshot" ]
+    public_deps += [ ":copy_${snapshot[0]}_snapshot_nnbd" ]
   }
 }
 
 # This rule writes the .packages file for dartdoc resources.
-write_file("$root_out_dir/dart-sdk/bin/resources/dartdoc/.packages",
+write_file("$root_out_dir/dart-sdk-nnbd/bin/resources/dartdoc/.packages",
            "dartdoc:.")
 
 # This is the main rule for copying the files that dartdoc needs.
-group("copy_dartdoc_files") {
-  visibility = [ ":create_common_sdk" ]
+group("copy_dartdoc_files_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   public_deps = [
-    ":copy_dartdoc_resources",
-    ":copy_dartdoc_templates",
+    ":copy_dartdoc_resources_nnbd",
+    ":copy_dartdoc_templates_nnbd",
   ]
 }
 
 # This rule copies analyzer summaries to lib/_internal
-copy("copy_analysis_summaries") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_analysis_summaries_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
     "../utils/dartanalyzer:generate_summary_strong",
   ]
   sources = [
     "$root_gen_dir/strong.sum",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/{{source_file_part}}",
   ]
 }
 
 # This rule copies dill files to lib/_internal.
-copy("copy_vm_dill_files") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_vm_dill_files_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
     "../runtime/vm:kernel_platform_files",
   ]
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$root_out_dir/vm_platform_strong.dill",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/{{source_file_part}}",
   ]
 }
 
-copy("copy_abi_dill_files") {
-  visibility = [ ":create_sdk_with_abi_versions" ]
+copy("copy_abi_dill_files_nnbd") {
+  visibility = [ ":create_sdk_with_abi_versions_nnbd" ]
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "../tools/abiversions",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/abiversions",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/abiversions",
   ]
 }
 
-copy("copy_dart2js_dill_files") {
-  visibility = [ ":create_full_sdk" ]
+copy("copy_dart2js_dill_files_nnbd") {
+  visibility = [ ":create_full_sdk_nnbd" ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
     "../utils/compiler:compile_dart2js_platform",
     "../utils/compiler:compile_dart2js_server_platform",
   ]
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$root_out_dir/dart2js_platform.dill",
     "$root_out_dir/dart2js_server_platform.dill",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/{{source_file_part}}",
   ]
 }
 
 # This rule copies ddc summaries to lib/_internal
-copy("copy_dev_compiler_summary") {
-  visibility = [ ":copy_dev_compiler_sdk" ]
+copy("copy_dev_compiler_summary_nnbd") {
+  visibility = [ ":copy_dev_compiler_sdk_nnbd" ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
     "../utils/dartdevc:dartdevc_kernel_sdk_outline",
     "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     # TODO(vsm): Remove post CFE.
     "$gen_dir/ddc_sdk.sum",
     "$gen_dir/kernel/ddc_sdk.dill",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/{{source_file_part}}",
   ]
 }
 
@@ -681,129 +695,135 @@
 # DDC to Kernel (DDK) migration.
 
 # This rule copies DDC's JS SDK and require.js to lib/dev_compiler/amd.
-copy("copy_dev_compiler_js_amd") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_amd_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/js/amd/dart_sdk.js",
     "$gen_dir/js/amd/dart_sdk.js.map",
     "../third_party/requirejs/require.js",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/amd/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/amd/{{source_file_part}}",
   ]
 }
 
 # This rule copies DDC's JS SDK and run.js to lib/dev_compiler/common.
-copy("copy_dev_compiler_js_common") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_common_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/js/common/dart_sdk.js",
     "$gen_dir/js/common/dart_sdk.js.map",
     "../pkg/dev_compiler/lib/js/common/run.js",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/common/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/common/{{source_file_part}}",
   ]
 }
 
 # This rule copies DDC's JS SDK to lib/dev_compiler/es6.
-copy("copy_dev_compiler_js_es6") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_es6_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/js/es6/dart_sdk.js",
     "$gen_dir/js/es6/dart_sdk.js.map",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/es6/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/es6/{{source_file_part}}",
   ]
 }
 
 # This rule copies DDK's JS SDK and require.js to lib/dev_compiler/kernel/amd.
-copy("copy_dev_compiler_js_amd_kernel") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_amd_kernel_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
   gen_dir =
       get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/kernel/amd/dart_sdk.js",
     "$gen_dir/kernel/amd/dart_sdk.js.map",
     "../third_party/requirejs/require.js",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/kernel/amd/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/kernel/amd/{{source_file_part}}",
   ]
 }
 
 # This rule copies DDK's JS SDK to lib/dev_compiler/kernel/common.
-copy("copy_dev_compiler_js_common_kernel") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_common_kernel_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
   gen_dir =
       get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/kernel/common/dart_sdk.js",
     "$gen_dir/kernel/common/dart_sdk.js.map",
     "../pkg/dev_compiler/lib/js/common/run.js",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/kernel/common/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/kernel/common/{{source_file_part}}",
   ]
 }
 
 # This rule copies DDK's JS SDK to lib/dev_compiler/kernel/es6.
-copy("copy_dev_compiler_js_es6_kernel") {
-  visibility = [ ":copy_dev_compiler_js" ]
+copy("copy_dev_compiler_js_es6_kernel_nnbd") {
+  visibility = [ ":copy_dev_compiler_js_nnbd" ]
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
   gen_dir =
       get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
+    # TODO(rnystrom): This probably needs to be forked for NNBD.
     "$gen_dir/kernel/es6/dart_sdk.js",
     "$gen_dir/kernel/es6/dart_sdk.js.map",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/kernel/es6/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/kernel/es6/{{source_file_part}}",
   ]
 }
 
 # Copies all of the JS artifacts needed by DDC.
-group("copy_dev_compiler_js") {
+group("copy_dev_compiler_js_nnbd") {
   visibility = [
-    ":copy_dev_compiler_sdk",
-    ":copy_dev_compiler_tools",
+    ":copy_dev_compiler_sdk_nnbd",
+    ":copy_dev_compiler_tools_nnbd",
   ]
   public_deps = [
-    ":copy_dev_compiler_js_amd",
-    ":copy_dev_compiler_js_amd_kernel",
-    ":copy_dev_compiler_js_common",
-    ":copy_dev_compiler_js_common_kernel",
-    ":copy_dev_compiler_js_es6",
-    ":copy_dev_compiler_js_es6_kernel",
+    ":copy_dev_compiler_js_amd_nnbd",
+    ":copy_dev_compiler_js_amd_kernel_nnbd",
+    ":copy_dev_compiler_js_common_nnbd",
+    ":copy_dev_compiler_js_common_kernel_nnbd",
+    ":copy_dev_compiler_js_es6_nnbd",
+    ":copy_dev_compiler_js_es6_kernel_nnbd",
   ]
 }
 
 # This rule copies tools to go along with ddc.
-copy("copy_dev_compiler_tools") {
-  visibility = [ ":copy_dev_compiler_sdk" ]
+copy("copy_dev_compiler_tools_nnbd") {
+  visibility = [ ":copy_dev_compiler_sdk_nnbd" ]
   deps = [
-    ":copy_dev_compiler_js",
+    ":copy_dev_compiler_js_nnbd",
     "../utils/dartdevc:dartdevc_web",
     "../utils/dartdevc:stack_trace_mapper",
   ]
@@ -813,91 +833,91 @@
     "$dart_out/dev_compiler/build/web/ddc_web_compiler.js",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/web/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/dev_compiler/web/{{source_file_part}}",
   ]
 }
 
 # This is the main rule for copying ddc's dependencies to lib/
-group("copy_dev_compiler_sdk") {
-  visibility = [ ":create_full_sdk" ]
+group("copy_dev_compiler_sdk_nnbd") {
+  visibility = [ ":create_full_sdk_nnbd" ]
   public_deps = [
-    ":copy_dev_compiler_js",
-    ":copy_dev_compiler_summary",
-    ":copy_dev_compiler_tools",
+    ":copy_dev_compiler_js_nnbd",
+    ":copy_dev_compiler_summary_nnbd",
+    ":copy_dev_compiler_tools_nnbd",
   ]
 }
 
 # This rule copies header files to include/
-copy("copy_headers") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_headers_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   sources = [
     "../runtime/include/dart_api.h",
     "../runtime/include/dart_native_api.h",
     "../runtime/include/dart_tools_api.h",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/include/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/include/{{source_file_part}}",
   ]
 }
 
 # This rule copies libraries.json files to lib/
-copy("copy_libraries_specification") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_libraries_specification_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   sources = [
     "lib/libraries.json",
   ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/{{source_file_part}}",
   ]
 }
 
 # This is the main rule to copy libraries in _platform_sdk_libraries to lib/
-group("copy_platform_sdk_libraries") {
+group("copy_platform_sdk_libraries_nnbd") {
   visibility = [
-    ":create_platform_sdk",
-    ":copy_libraries",
+    ":create_platform_sdk_nnbd",
+    ":copy_libraries_nnbd",
   ]
   public_deps = []
   foreach(library, _platform_sdk_libraries) {
-    public_deps += [ ":copy_${library}_library" ]
+    public_deps += [ ":copy_${library}_library_nnbd" ]
   }
 }
 
 # This is the main rule to copy libraries in _full_sdk_libraries to lib/
-group("copy_full_sdk_libraries") {
+group("copy_full_sdk_libraries_nnbd") {
   visibility = [
-    ":create_full_sdk",
-    ":copy_libraries",
+    ":create_full_sdk_nnbd",
+    ":copy_libraries_nnbd",
   ]
   public_deps = []
   foreach(library, _full_sdk_libraries) {
-    public_deps += [ ":copy_${library}_library" ]
+    public_deps += [ ":copy_${library}_library_nnbd" ]
   }
 }
 
-group("copy_libraries") {
-  if (dart_platform_sdk) {
+group("copy_libraries_nnbd") {
+  if (dart_platform_sdk_nnbd) {
     public_deps = [
-      ":copy_platform_sdk_libraries",
+      ":copy_platform_sdk_libraries_nnbd",
     ]
   } else {
     public_deps = [
-      ":copy_full_sdk_libraries",
+      ":copy_full_sdk_libraries_nnbd",
     ]
   }
 }
 
 # This rule writes the version file.
-action("write_version_file") {
-  visibility = [ ":create_common_sdk" ]
+action("write_version_file_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   inputs = [
     "../tools/VERSION",
     "../.git/logs/HEAD",
   ]
-  output = "$root_out_dir/dart-sdk/version"
+  output = "$root_out_dir/dart-sdk-nnbd/version"
   outputs = [
     output,
   ]
@@ -909,12 +929,12 @@
 }
 
 # This rule writes the revision file.
-action("write_revision_file") {
-  visibility = [ ":create_common_sdk" ]
+action("write_revision_file_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   inputs = [
     "../.git/logs/HEAD",
   ]
-  output = "$root_out_dir/dart-sdk/revision"
+  output = "$root_out_dir/dart-sdk-nnbd/revision"
   outputs = [
     output,
   ]
@@ -932,48 +952,48 @@
 # of the analyzer package do not support the new location of this file. We
 # should be able to remove the old file once we release a newer version of
 # analyzer and popular frameworks have migrated to use it.
-copy("copy_libraries_dart") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_libraries_dart_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   deps = [
-    ":copy_libraries",
+    ":copy_libraries_nnbd",
   ]
   sources = [
     "lib/_internal/sdk_library_metadata/lib/libraries.dart",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
+    "$root_out_dir/dart-sdk-nnbd/lib/_internal/{{source_file_part}}",
   ]
 }
 
 # This rule copies the README file.
-copy("copy_readme") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_readme_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   sources = [
     "../README.dart-sdk",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/README",
+    "$root_out_dir/dart-sdk-nnbd/README",
   ]
 }
 
 # This rule copies the LICENSE file.
-copy("copy_license") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_license_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   sources = [
     "../LICENSE",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/LICENSE",
+    "$root_out_dir/dart-sdk-nnbd/LICENSE",
   ]
 }
 
 # This rule generates a custom dartdoc_options.yaml file.
-action("write_dartdoc_options") {
-  visibility = [ ":create_common_sdk" ]
+action("write_dartdoc_options_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   inputs = [
     "../.git/logs/HEAD",
   ]
-  output = "$root_out_dir/dart-sdk/dartdoc_options.yaml"
+  output = "$root_out_dir/dart-sdk-nnbd/dartdoc_options.yaml"
   outputs = [
     output,
   ]
@@ -985,85 +1005,85 @@
 }
 
 # This rule copies the API readme file to lib/
-copy("copy_api_readme") {
-  visibility = [ ":create_common_sdk" ]
+copy("copy_api_readme_nnbd") {
+  visibility = [ ":create_common_sdk_nnbd" ]
   sources = [
     "api_readme.md",
   ]
   outputs = [
-    "$root_out_dir/dart-sdk/lib/api_readme.md",
+    "$root_out_dir/dart-sdk-nnbd/lib/api_readme.md",
   ]
 }
 
 # Parts common to both platform and full SDKs.
-group("create_common_sdk") {
-  visibility = [ ":create_sdk" ]
+group("create_common_sdk_nnbd") {
+  visibility = [ ":create_sdk_nnbd" ]
   public_deps = [
-    ":copy_analysis_summaries",
-    ":copy_api_readme",
-    ":copy_dart",
-    ":copy_dart2native",
-    ":copy_dartdoc_files",
-    ":copy_headers",
-    ":copy_libraries_dart",
-    ":copy_libraries_specification",
-    ":copy_license",
-    ":copy_readme",
-    ":copy_vm_dill_files",
-    ":write_dartdoc_options",
-    ":write_revision_file",
-    ":write_version_file",
+    ":copy_analysis_summaries_nnbd",
+    ":copy_api_readme_nnbd",
+    ":copy_dart_nnbd",
+    ":copy_dart2native_nnbd",
+    ":copy_dartdoc_files_nnbd",
+    ":copy_headers_nnbd",
+    ":copy_libraries_dart_nnbd",
+    ":copy_libraries_specification_nnbd",
+    ":copy_license_nnbd",
+    ":copy_readme_nnbd",
+    ":copy_vm_dill_files_nnbd",
+    ":write_dartdoc_options_nnbd",
+    ":write_revision_file_nnbd",
+    ":write_version_file_nnbd",
   ]
   if (is_win) {
-    public_deps += [ ":copy_7zip" ]
+    public_deps += [ ":copy_7zip_nnbd" ]
   }
   if (target_cpu == "x64") {
     public_deps += [
-      ":copy_language_model",
-      ":copy_libtensorflowlite_c",
+      ":copy_language_model_nnbd",
+      ":copy_libtensorflowlite_c_nnbd",
     ]
   }
 }
 
 # Parts specific to the platform SDK.
-group("create_platform_sdk") {
-  visibility = [ ":create_sdk" ]
+group("create_platform_sdk_nnbd") {
+  visibility = [ ":create_sdk_nnbd" ]
   public_deps = [
-    ":copy_platform_sdk_libraries",
-    ":copy_platform_sdk_scripts",
-    ":copy_platform_sdk_snapshots",
+    ":copy_platform_sdk_libraries_nnbd",
+    ":copy_platform_sdk_scripts_nnbd",
+    ":copy_platform_sdk_snapshots_nnbd",
   ]
 }
 
 # Parts specific to the full SDK.
-group("create_full_sdk") {
-  visibility = [ ":create_sdk" ]
+group("create_full_sdk_nnbd") {
+  visibility = [ ":create_sdk_nnbd" ]
 
   public_deps = [
-    ":copy_dart2js_dill_files",
-    ":copy_dev_compiler_sdk",
-    ":copy_full_sdk_libraries",
-    ":copy_full_sdk_scripts",
-    ":copy_full_sdk_snapshots",
+    ":copy_dart2js_dill_files_nnbd",
+    ":copy_dev_compiler_sdk_nnbd",
+    ":copy_full_sdk_libraries_nnbd",
+    ":copy_full_sdk_scripts_nnbd",
+    ":copy_full_sdk_snapshots_nnbd",
   ]
 }
 
 # The main target to depend on from ../BUILD.gn
-group("create_sdk") {
+group("create_sdk_nnbd") {
   public_deps = [
-    ":create_common_sdk",
+    ":create_common_sdk_nnbd",
   ]
-  if (dart_platform_sdk) {
-    public_deps += [ ":create_platform_sdk" ]
+  if (dart_platform_sdk_nnbd) {
+    public_deps += [ ":create_platform_sdk_nnbd" ]
   } else {
-    public_deps += [ ":create_full_sdk" ]
+    public_deps += [ ":create_full_sdk_nnbd" ]
   }
 }
 
 # Same as create_sdk, but with abi version files.
-group("create_sdk_with_abi_versions") {
+group("create_sdk_with_abi_versions_nnbd") {
   public_deps = [
-    ":copy_abi_dill_files",
-    ":create_sdk",
+    ":copy_abi_dill_files_nnbd",
+    ":create_sdk_nnbd",
   ]
-}
+}
\ No newline at end of file
diff --git a/sdk_nnbd/bin/dartdevc_sdk b/sdk_nnbd/bin/dartdevc_sdk
index 60d2fe1..6cba7d8 100755
--- a/sdk_nnbd/bin/dartdevc_sdk
+++ b/sdk_nnbd/bin/dartdevc_sdk
@@ -25,4 +25,14 @@
 
 # We are running the snapshot in the built SDK.
 DART="$BIN_DIR/dart"
-exec "$DART" "$SNAPSHOT" "$@"
+
+unset EXTRA_VM_OPTIONS
+declare -a EXTRA_VM_OPTIONS
+
+# We allow extra vm options to be passed in through an environment variable.
+if [[ $DART_VM_OPTIONS ]]; then
+  read -a OPTIONS <<< "$DART_VM_OPTIONS"
+  EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
+fi
+
+exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "$@"
diff --git a/sdk_nnbd/bin/dartdevc_sdk.bat b/sdk_nnbd/bin/dartdevc_sdk.bat
index 5dbf707..ce027a9 100644
--- a/sdk_nnbd/bin/dartdevc_sdk.bat
+++ b/sdk_nnbd/bin/dartdevc_sdk.bat
@@ -22,7 +22,14 @@
 
 set SDK_ARG=--dart-sdk=%SDK_DIR%
 
-"%DART%" "%SNAPSHOT%" "%SDK_ARG%" %*
+set EXTRA_VM_OPTIONS=
+
+rem We allow extra vm options to be passed in through an environment variable.
+if not "_%DART_VM_OPTIONS%_" == "__" (
+  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
+)
+
+"%DART%" %EXTRA_VM_OPTIONS% "%SNAPSHOT%" "%SDK_ARG%" %*
 
 endlocal
 
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 42d4c42..b194781 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
@@ -525,6 +525,7 @@
 ///
 /// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
+  if (!dart.isDartFunction(f)) return f;
   var ret = _interopExpando[f];
   if (ret == null) {
     ret = JS(
@@ -549,6 +550,7 @@
 ///
 /// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
+  if (!dart.isDartFunction(f)) return f;
   var ret = _interopCaptureThisExpando[f];
   if (ret == null) {
     ret = JS(
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 5dbff7f..7451365 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
@@ -94,6 +94,10 @@
   return f;
 }
 
+bool isDartFunction(obj) =>
+    JS<bool>('!', '# instanceof Function', obj) &&
+    JS<bool>('!', '#[#] != null', obj, _runtimeType);
+
 /// The Dart type that represents a JavaScript class(/constructor) type.
 ///
 /// The JavaScript type may not exist, either because it's not loaded yet, or
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 5ad56dc..67f1d0b 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -365,6 +365,11 @@
 @pragma('dart2js:noInline')
 Rti instantiatedGenericFunctionType(
     Rti genericFunctionRti, Rti instantiationRti) {
+  // If --lax-runtime-type-to-string is enabled and we never check the function
+  // type, then the function won't have a signature, so its RTI will be null. In
+  // this case, there is nothing to instantiate, so we return `null` and the
+  // instantiation appears to be an interface type instead.
+  if (genericFunctionRti == null) return null;
   var bounds = Rti._getGenericFunctionBounds(genericFunctionRti);
   var typeArguments = Rti._getInterfaceTypeArguments(instantiationRti);
   assert(_Utils.arrayLength(bounds) == _Utils.arrayLength(typeArguments));
diff --git a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
index fc33afa..8339229 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
@@ -62,6 +62,7 @@
   }
 
   void _init(Uint8List data) native 'Wasm_initModule';
+  String describe() native 'Wasm_describeModule';
 }
 
 class _NativeWasmImports extends NativeFieldWrapperClass1
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index b5afe53..64aa8ab 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -25459,15 +25459,7 @@
 @Native("RTCIceCandidate,mozRTCIceCandidate")
 class RtcIceCandidate extends Interceptor {
   factory RtcIceCandidate(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS(
-        '',
-        'window[#]',
-        Device.isFirefox
-            ? '${Device.propertyPrefix}RTCIceCandidate'
-            : 'RTCIceCandidate');
+    var constructorName = JS('', 'window[#]', 'RTCIceCandidate');
     return JS('RtcIceCandidate', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
@@ -25513,8 +25505,8 @@
 @Native("RTCPeerConnection,webkitRTCPeerConnection,mozRTCPeerConnection")
 class RtcPeerConnection extends EventTarget {
   factory RtcPeerConnection(Map rtcIceServers, [Map mediaConstraints]) {
-    var constructorName = JS('RtcPeerConnection', 'window[#]',
-        '${Device.propertyPrefix}RTCPeerConnection');
+    var constructorName =
+        JS('RtcPeerConnection', 'window[#]', 'RTCPeerConnection');
     if (mediaConstraints != null) {
       return JS(
           'RtcPeerConnection',
@@ -25849,15 +25841,7 @@
 @Native("RTCSessionDescription,mozRTCSessionDescription")
 class RtcSessionDescription extends Interceptor {
   factory RtcSessionDescription(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS(
-        '',
-        'window[#]',
-        Device.isFirefox
-            ? '${Device.propertyPrefix}RTCSessionDescription'
-            : 'RTCSessionDescription');
+    var constructorName = JS('', 'window[#]', 'RTCSessionDescription');
     return JS('RtcSessionDescription', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
@@ -34976,7 +34960,7 @@
     // always dealing with pixels in this method.
     var styles = _element.getComputedStyle();
 
-    var val = 0;
+    num val = 0;
 
     for (String measurement in dimensions) {
       // The border-box and default box model both exclude margin in the regular
diff --git a/sdk_nnbd/lib/html/html_common/conversions.dart b/sdk_nnbd/lib/html/html_common/conversions.dart
index ca118a9..64c7cb8 100644
--- a/sdk_nnbd/lib/html/html_common/conversions.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions.dart
@@ -78,6 +78,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);
@@ -136,6 +139,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_nnbd/lib/html/html_common/conversions_dart2js.dart b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
index 08ce947..c973a55 100644
--- a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
@@ -55,6 +55,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_nnbd/lib/html/html_common/html_common_dart2js.dart b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
index 3a91281..710d1f1 100644
--- a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
@@ -15,7 +15,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_nnbd/lib/html/html_sources.gni b/sdk_nnbd/lib/html/html_sources.gni
new file mode 100644
index 0000000..524b6dd
--- /dev/null
+++ b/sdk_nnbd/lib/html/html_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+html_sdk_sources = [ "dart2js/html_dart2js.dart" ]
diff --git a/sdk_nnbd/lib/js/js_sources.gni b/sdk_nnbd/lib/js/js_sources.gni
new file mode 100644
index 0000000..91f6d0c
--- /dev/null
+++ b/sdk_nnbd/lib/js/js_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+js_sdk_sources = [ "dart2js/js_dart2js.dart" ]
diff --git a/sdk_nnbd/lib/js_util/js_util_sources.gni b/sdk_nnbd/lib/js_util/js_util_sources.gni
new file mode 100644
index 0000000..3b7c1b1
--- /dev/null
+++ b/sdk_nnbd/lib/js_util/js_util_sources.gni
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+js_util_sdk_sources = [ "dart2js/js_util_dart2js.dart" ]
diff --git a/sdk_nnbd/lib/wasm/wasm.dart b/sdk_nnbd/lib/wasm/wasm.dart
index 631dc22..3830d56 100644
--- a/sdk_nnbd/lib/wasm/wasm.dart
+++ b/sdk_nnbd/lib/wasm/wasm.dart
@@ -32,6 +32,9 @@
 
   // Instantiate the module with the given imports.
   WasmInstance instantiate(WasmImports imports);
+
+  // Describes the imports and exports that the module expects, for debugging.
+  String describe();
 }
 
 // WasmImports holds all the imports for a WasmInstance.
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 9afaf8b..28c1f67 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -6,17 +6,10 @@
 analyses/api_dynamic_test: Slow
 analyses/dart2js_dynamic_test: Slow
 closure/closure_test: Slow
-codegen/gvn_dynamic_field_get_test: Fail # Issue 18519
-codegen/list_tracer_length_test: Fail # Issue 33051
 codegen/load_elimination_test: Slow
-codegen/logical_expression_test: Fail # Issue 17027
 codegen/model_test: Slow
-codegen/side_effect_tdiv_regression_test: Fail # Issue 33050
-codegen/simple_function_subtype_test: Fail # simple_function_subtype_test is temporarily(?) disabled due to new method for building function type tests.
 deferred_loading/deferred_loading_test: Slow
 end_to_end/dump_info_test: Slow
-end_to_end/generate_code_with_compile_time_errors_test: RuntimeError # not supported yet with the new FE.
-end_to_end/show_package_warnings_test: RuntimeError # missing errors from the FE
 equivalence/id_equivalence1_test: Slow
 equivalence/id_equivalence2_test: Slow
 impact/impact_test: Slow
@@ -24,10 +17,7 @@
 inference/inference1_test: Slow
 inference/inference2_test: Slow
 inference/inference3_test: Slow
-inference/simple_inferrer_const_closure2_test: Fail # Issue 16507
-inference/simple_inferrer_const_closure_test: Fail # Issue 16507
-inference/simple_inferrer_global_field_closure_test: Fail # Issue 16507
-inference/swarm_test: Slow, Pass, Fail #
+inference/swarm_test: Slow #
 inlining/inlining_test: Slow
 model/native_test: Slow
 model/no_such_method_enabled_test: Slow
@@ -38,8 +28,6 @@
 rti/rti_need0_test: Slow
 rti/rti_need1_test: Slow
 serialization/serialization_test: Slow
-sourcemaps/d2js_validity_test: RuntimeError # Issue 33072
-sourcemaps/deferred_d2js_validity_test: RuntimeError # Issue 33072
 sourcemaps/source_mapping_invokes_test: Slow
 sourcemaps/source_mapping_operators_test: Slow
 sourcemaps/source_mapping_test: Slow
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/extension_method.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/extension_method.dart
new file mode 100644
index 0000000..fb4e466
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/extension_method.dart
@@ -0,0 +1,72 @@
+class MyClass {
+  MyClass();
+
+  @pragma('dart2js:noInline')
+  set internalSetter(int v) {
+    /*7:MyClass.internalSetter*/ throw "error";
+  }
+}
+
+int q = 3;
+
+extension Ext on MyClass {
+  @pragma('dart2js:noInline')
+  int method() {
+    this./*6:Ext.method*/ internalSetter = 1;
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 29) return 3;
+    return 2;
+  }
+
+  @pragma('dart2js:noInline')
+  int get propertyB {
+    /*5:Ext.propertyB*/ method();
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 29) return 3;
+    return 2;
+  }
+
+  @pragma('dart2js:noInline')
+  set propertyA(int v) {
+    /*4:Ext.propertyA*/ propertyB;
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 29) return null;
+    return null;
+  }
+
+  @pragma('dart2js:noInline')
+  int operator+(int v) {
+    this./*3:Ext.+*/ propertyA = 2;
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 30) return 1;
+    return 3;
+  }
+
+  @pragma('dart2js:noInline')
+  int operator[](int v) {
+    this /*2:Ext.[]*/ + 2;
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 30) return 1;
+    return 3;
+  }
+}
+
+extension on MyClass {
+  @pragma('dart2js:noInline')
+  int method2() {
+    this/*1:MyClass.<anonymous extension>.method2*/[0];
+    // TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
+    if (q > 29) return 3;
+    return 2;
+  }
+}
+
+@pragma('dart2js:noInline')
+confuse(x) => x;
+
+main() {
+  q++;
+  confuse(null);
+  MyClass x = confuse(new MyClass());
+  x. /*0:main*/method2();
+}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
index a4a6fa0..6ea1a2a 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -85,6 +85,7 @@
       '--libraries-spec=sdk/lib/libraries.json',
       '--packages=${Platform.packageConfig}',
       Flags.testMode,
+      '--enable-experiment=extension-methods',
       input,
     ]..addAll(options);
     print("Compiling dart2js ${arguments.join(' ')}");
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index efc2aea..29be72f 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -2,107 +2,40 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $compiler == dart2js ]
-bounds_check4a_test: RuntimeError # Issue 32741
-bounds_check4b_test: RuntimeError # Issue 32741
-generic_class_is_test: Fail # Issue 32004
-jsinterop_test/01: MissingCompileTimeError # Issue 34174
-jsinterop_test/02: MissingCompileTimeError # Issue 34174
-jsinterop_test/03: MissingCompileTimeError # Issue 34174
-jsinterop_test/04: MissingCompileTimeError # Issue 34174
-jsinterop_test/34: MissingCompileTimeError # Issue 33834
-jsinterop_test/35: MissingCompileTimeError # Issue 33834
-jsinterop_test/36: MissingCompileTimeError # Issue 33834
-jsinterop_test/37: MissingCompileTimeError # Issue 33834
-jsinterop_test/38: MissingCompileTimeError # Issue 34174
-jsinterop_test/42: MissingCompileTimeError # Issue 34174
-jsinterop_test/43: MissingCompileTimeError # Issue 34345
-jsinterop_test/44: MissingCompileTimeError # Issue 34345
-jsinterop_test/45: MissingCompileTimeError # Issue 34345
-jsinterop_test/46: MissingCompileTimeError # Issue 34174
-jsinterop_test/51: MissingCompileTimeError # Issue 34174
-jsinterop_test/52: MissingCompileTimeError # Issue 34345
-jsinterop_test/53: MissingCompileTimeError # Issue 34345
-jsinterop_test/54: MissingCompileTimeError # Issue 34345
-many_instantiations_test/01: Crash # Issue 33819
-no_such_method_test: Fail # Wrong Invocation.memberName.
-non_jsinterop_test/01: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/02: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/03: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/04: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/34: MissingCompileTimeError # Issue 33834
-non_jsinterop_test/35: MissingCompileTimeError # Issue 33834
-non_jsinterop_test/36: MissingCompileTimeError # Issue 33834
-non_jsinterop_test/37: MissingCompileTimeError # Issue 33834
-non_jsinterop_test/38: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/42: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/43: MissingCompileTimeError # Issue 34345
-non_jsinterop_test/44: MissingCompileTimeError # Issue 34345
-non_jsinterop_test/45: MissingCompileTimeError # Issue 34345
-non_jsinterop_test/46: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/51: MissingCompileTimeError # Issue 34174
-non_jsinterop_test/52: MissingCompileTimeError # Issue 34345
-non_jsinterop_test/53: MissingCompileTimeError # Issue 34345
-non_jsinterop_test/54: MissingCompileTimeError # Issue 34345
-
 [ $compiler != dart2js ]
 dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
 
 [ $runtime == jsshell ]
 deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
-timer_test: Fail # Issue 7728.
-
-[ $runtime == none ]
-timer_negative_test: Fail, OK # A negative runtime test.
 
 [ $compiler == dart2js && $mode == debug ]
 operator_test: Skip
 string_interpolation_test: Skip
 
 [ $compiler == dart2js && $runtime == chrome && $system == windows ]
-class_test: Pass, Slow # Issue 25940
-closure_capture3_test: Pass, Slow # Issue 25940
-closure_capture5_test: Pass, Slow # Issue 25940
-conditional_test: Pass, Slow # Issue 25940
-consistent_codeUnitAt_error_test: Pass, Slow # Issue 25940
-constant_javascript_semantics2_test: Pass, Slow # Issue 25940
-deferred_split_test: Pass, Slow # Issue 25940
+class_test: Slow # Issue 25940
+closure_capture3_test: Slow # Issue 25940
+closure_capture5_test: Slow # Issue 25940
+conditional_test: Slow # Issue 25940
+consistent_codeUnitAt_error_test: Slow # Issue 25940
+constant_javascript_semantics2_test: Slow # Issue 25940
+deferred_split_test: Slow # Issue 25940
 
 [ $compiler == dart2js && $runtime == chrome && $csp ]
 deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval`
 
-[ $compiler == dart2js && $runtime == d8 ]
-deferred_fail_and_retry_test: RuntimeError # Uses XHR in dart:html
-deferred_with_csp_nonce_test: RuntimeError # Uses dart:html
-
 [ $compiler == dart2js && $runtime == ff && $system == windows ]
-consistent_index_error_string_test: Pass, Slow # Issue 25940
-
-[ $compiler == dart2js && $runtime == none ]
-*: Fail, Pass # TODO(ahe): Triage these tests.
+consistent_index_error_string_test: Slow # Issue 25940
 
 [ $compiler == dart2js && $csp ]
 deferred_custom_loader_test: SkipByDesign # Issue 25683
 deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
-js_interop_optional_arg_test: RuntimeError # Issue 31082
-js_interop_test: RuntimeError # Issue 31082
 
 [ $compiler == dart2js && !$host_checked ]
-dummy_compiler_test: RuntimeError, Slow # Issue 32439. self-hosting doesn't work with CFE yet.
+dummy_compiler_test: Slow # Issue 32439. self-hosting doesn't work with CFE yet.
 
 [ $compiler == dart2js && $minified ]
-closure_capture2_test: Pass # Passes for the wrong reason
 code_motion_exception_test: Skip # Requires unminified operator names.
-deferred/reflect_multiple_annotations_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
-deferred/reflect_multiple_default_arg_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
-mirrors_used_warning_test/minif: Fail, OK # Tests warning that minified code will be broken.
-runtime_type_test: Fail, OK # Tests extected output of Type.toString().
-to_string_test: Fail # Issue 7179.
-type_literal_test: Fail, OK # Tests expected output of Type.toString().
-typevariable_typedef_test: Fail, OK # Tests expected output of Type.toString().
-
-[ $compiler == dart2js && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == ff || $runtime == safari) ]
-isolate2_test/01: Fail # Issue 14458.
 
 [ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == safari) ]
 code_motion_exception_test: Skip # Required V8 specific format of JavaScript errors.
@@ -111,6 +44,5 @@
 dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
 
 [ $compiler == none && $runtime == vm ]
-invalid_annotation_test/01: MissingCompileTimeError, OK # vm is lazy
 new_from_env_test: SkipByDesign # dart2js only test
 unconditional_dartio_import_test: SkipByDesign # dart2js only test
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index ad3e21a..fd86b1b 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -2,18 +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.
 
-[ $compiler == dart2js ]
-fake_thing_test: RuntimeError # Issue 13010
-field_type2_test: CompileTimeError # Issue 33762
-field_type_test: CompileTimeError # Issue 33762
-native_exceptions1_frog_test: CompileTimeError # Issue 33762
-native_mixin_with_plain_test: CompileTimeError # Issue 33762
-native_window1_frog_test: CompileTimeError # Issue 33762
-native_window2_frog_test: CompileTimeError # Issue 33762
-subclassing_constructor_1_test: CompileTimeError # Issue 33762
-
 [ $browser ]
 *: Skip
 
-[ $compiler == dart2js && $minified ]
-optimization_hints_test: RuntimeError, OK # Test relies on unminified names.
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index a6caf81..868f098 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -5,15 +5,6 @@
 [ $arch == simdbc || $arch == simdbc64 ]
 *: Skip # SIMDBC will be deleted soon.
 
-# Issue 37295, not yet supported in blobs snapshots at present.
-[ $compiler == dartkp && $system == windows ]
-function_callbacks_test: Skip
-regress_37511_callbacks_test: Skip
-stacktrace_regress_37910_test: Skip
-
-[ $compiler != dartkp || $system != windows ]
-function_callbacks_unsupported_test: SkipByDesign # See above
-
 [ $builder_tag == asan ]
 data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose.
 
diff --git a/tests/ffi/function_callbacks_unsupported_test.dart b/tests/ffi/function_callbacks_unsupported_test.dart
deleted file mode 100644
index 5ac1b5d..0000000
--- a/tests/ffi/function_callbacks_unsupported_test.dart
+++ /dev/null
@@ -1,19 +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.
-//
-// Dart test program for testing that FFI callbacks report an appropriate
-// runtime error for unsupported snapshot formats.
-
-import 'dart:ffi';
-
-import 'package:expect/expect.dart';
-
-bool checkError(UnsupportedError err) {
-  return "$err".contains("callbacks are not yet supported in blobs");
-}
-
-void main() {
-  Expect.throws<UnsupportedError>(
-      () => Pointer.fromFunction<Void Function()>(main), checkError);
-}
diff --git a/tests/language_2/extension_methods/basic_static_extension_test.dart b/tests/language_2/extension_methods/basic_static_extension_test.dart
index ce4fb5f..39bb377 100644
--- a/tests/language_2/extension_methods/basic_static_extension_test.dart
+++ b/tests/language_2/extension_methods/basic_static_extension_test.dart
@@ -89,7 +89,7 @@
   UnnamedGeneric<num> unnamedGenericNull = null;
 
   Expect.equals("unnamed generic(non-null)", unnamedGeneric.name);
-  Expect.equals("unnamed generic(null)", unnamedGeneric.name);
+  Expect.equals("unnamed generic(null)", unnamedGenericNull.name);
   Expect.type<List<num>>(unnamedGeneric.list);
   Expect.notType<List<int>>(unnamedGeneric.list);
   Expect.type<List<num>>(unnamedGenericNull.list);
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 c24bc36..664916f 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
@@ -11,19 +11,21 @@
 class C0 {
   int get m1 => 0;
   void set m2(int x) {}
+  int operator[](int index) => 0;
 }
 
 extension E0 on C0 {
   void set m1(int x) {}
   int get m2 => 0;
+  void operator[]=(int index, int value) {}
 }
 
 void test0() {
   C0 c0 = C0();
   c0.m1;
   c0.m1 = 0;
-  // ^^^^^^
-  // [analyzer] unspecified
+  // ^^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_NO_SETTER
   // [cfe] unspecified
   E0(c0).m1 = 0;
   E0(c0).m1;
@@ -32,20 +34,59 @@
   // [cfe] unspecified
 
   c0.m1 += 0;
-  // ^^^^^^
-  // [analyzer] unspecified
+  // ^^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_NO_SETTER
+  // [cfe] unspecified
+
+  c0.m1++;
+  // ^^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_NO_SETTER
   // [cfe] unspecified
 
   c0.m2 = 0;
   c0.m2;
   // ^^
-  // [analyzer] unspecified
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
   // [cfe] unspecified
   c0.m2 += 0;
-  // ^^^^^^^
+  // ^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] unspecified
+  c0.m2++;
+  // ^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] unspecified
+
+  E0(c0).m2;
+
+  c0[0];
+  c0[0] = 0;
+  // ^^^^^^
   // [analyzer] unspecified
   // [cfe] unspecified
-  E0(c0).m2;
+  E0(c0)[0];
+  // ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  E0(c0)[0] = 0;
+
+  c0[0] += 0;
+  // ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  c0[0]++;
+  // ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  E0(c0)[0] += 0;
+  // ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  E0(c0)[0]++;
+  // ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
 }
 
 // Conflicting extensions.
@@ -55,11 +96,13 @@
 extension E1A<T> on C1<T> {
   int get m1 => 0;
   void set m2(int x) {}
+  int operator[](int index) => 0;
 }
 
 extension E1B on C1<Object> {
   void set m1(int x) {}
   int get m2 => 0;
+  void operator[]=(int index, int value) {}
 }
 
 void test1() {
@@ -78,6 +121,23 @@
 
   c1a.m2 = 0;
 
+  c1a[0] = 0;
+  //  ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1a[0] += 0;
+  //  ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1a[0]++;
+  //  ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1a[0];
+
   C1<Object> c1b = C1<Null>(); // Neither extension is more specific.
 
   c1b.m1;
@@ -90,14 +150,40 @@
   // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // [cfe] unspecified
 
+  c1b.m1 += 0;
+  //  ^^
+  // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+  // [cfe] unspecified
+
+  c1b.m1++;
+  //  ^^
+  // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+  // [cfe] unspecified
+
   c1b.m2;
   //  ^^
   // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // [cfe] unspecified
 
-  c1b.m2 = 0;
+
+  c1b[0];
   //  ^^
-  // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1b[0] = 0;
+  //  ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1b[0] += 0;
+  //  ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  c1b[0]++;
+  //  ^^
+  // [analyzer] unspecified
   // [cfe] unspecified
 }
 
@@ -106,12 +192,15 @@
   int get m1 => 0;
   void set m2(int x) {}
   int get mc => 0;
+  void operator[]=(int index, int value) {}
 }
 
 extension E2 on C2 {
   void set m1(int x) {}
   int get m2 => 0;
   String get me => "";
+  int operator[](int index) => 0;
+
 
   void test2() {
     // Using `this.member` means using the `on` type.
@@ -128,6 +217,22 @@
     // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
     // [cfe] unspecified
 
+    this[0] = 0;
+    this[0];
+    //   ^^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+
+    this[0] += 0;
+    //   ^^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+
+    this[0] ++;
+    //   ^^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+
     // Check that `this.mc` refers to `C2.mc`.
     this.mc.toRadixString(16);
     // Check that `this.me` refers to `E2.me`.
diff --git a/tests/language_2/extension_methods/static_extension_resolution_failures_test.dart b/tests/language_2/extension_methods/static_extension_resolution_failures_test.dart
index 0a70b9b..dc9b18c 100644
--- a/tests/language_2/extension_methods/static_extension_resolution_failures_test.dart
+++ b/tests/language_2/extension_methods/static_extension_resolution_failures_test.dart
@@ -62,8 +62,8 @@
   // Both EIT.e1 and ELO.e1 apply, but their instantiated on
   // types are incomparable, and hence this is an error.
   ln.e1();
-  // ^
-  // [analyzer] unspecified
+  // ^^
+  // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // [cfe] The method 'e1' isn't defined for the class 'List<num>'.
 }
 
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index fb8135f..64bc2b8 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -4,75 +4,7 @@
 # Sections in this file should contain "$compiler == dart2js".
 
 [ $compiler == dart2js ]
-arithmetic_int64_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-async_star_cancel_while_paused_test: RuntimeError # Issue 22853
-bit_operations_test: RuntimeError, OK # non JS number semantics
-bit_operations_test/03: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-bit_operations_test/04: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-bit_operations_test/none: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-call_method_must_not_be_field_test/03: RuntimeError # Issue 32155
-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
-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
-const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
-covariant_subtyping_test: Crash # Unsupported operation: Unsupported type parameter type node E.
-deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
-deopt_inlined_function_lazy_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-deopt_smi_op_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-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
-full_stacktrace1_test: RuntimeError # Issue 12698
-full_stacktrace2_test: RuntimeError # Issue 12698
-full_stacktrace3_test: RuntimeError # Issue 12698
-guess_cid_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-identical_closure2_test: RuntimeError # non JS number semantics
-identical_closure2_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-infinity_test: RuntimeError # non JS number semantics - Issue 4984
-int2_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/01: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/02: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/04: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/05: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/06: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/11: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/12: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/14: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/16: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/17: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/19: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/none: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-integer_division_by_zero_test: RuntimeError # Issue 8301
-issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
-left_shift_test: RuntimeError # non JS number semantics
-library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
-library_env_test/has_mirror_support: Fail # mirrors not supported on web
-library_env_test/has_no_mirror_support: Pass # fails for the wrong reason.
-mint_arithmetic_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-mint_arithmetic_test: RuntimeError # non JS number semantics
-mint_compares_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-mint_identical_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 mixin_method_override_test/G5: Skip # Issue 34354
-mock_writable_final_field_test: RuntimeError # Issue 30847
-modulo_test: RuntimeError # non JS number semantics
-nan_identical_test: RuntimeError # Issue 11551
-number_identity_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-numbers_test: RuntimeError, OK # non JS number semantics
-partial_instantiation_eager_bounds_check_test: RuntimeError # Issue #34295
-partial_tearoff_instantiation_test/05: Pass # for the wrong reason.
-partial_tearoff_instantiation_test/06: Pass # for the wrong reason.
-partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
-partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
-regress_24283_test: RuntimeError, OK # non JS number semantics
-stacktrace_demangle_ctors_test: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
-stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
-truncdiv_zero_test: RuntimeError # non JS number semantics - Issue 15246
-type_constants_test/none: RuntimeError # Issue 35052
 vm/*: SkipByDesign # Tests for the VM.
 
 [ $compiler != dart2js ]
@@ -81,108 +13,19 @@
 [ $builder_tag == dart2js_production && $compiler == dart2js ]
 control_flow_collections/for_non_bool_condition_test: Crash # Issue 36442
 
-[ $compiler == dart2js && $runtime == chrome && $system == macos ]
-await_future_test: Pass, Timeout # Issue 26735
-
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
-override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
+override_field_test/02: Slow # TODO(kasperl): Please triage.
 
 [ $compiler == dart2js && $runtime == d8 ]
 conditional_import_string_test: SkipByDesign # No XHR in d8
 conditional_import_test: SkipByDesign # No XHR in d8
 
-[ $compiler == dart2js && $runtime == ff ]
-round_test: Pass, Fail, OK # Fixed in ff 35. Common JavaScript engine Math.round bug.
-
 [ $compiler == dart2js && $runtime == jsshell ]
-async_call_test: RuntimeError # Timer interface not supported: Issue 7728.
-async_star_await_pauses_test: RuntimeError # Need triage
-async_star_no_cancel2_test: RuntimeError # Need triage
-async_star_no_cancel_test: RuntimeError # Need triage
 await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
-regress_23996_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
-
-[ $compiler == dart2js && $runtime != none && $checked ]
-syncstar_covariant_type_test: RuntimeError # dart2js misplaces check in Iterator, not Iterable.
-syncstar_dcall_type_test: RuntimeError # dart2js misplaces check in Iterator, not Iterable.
-
-[ $compiler == dart2js && $runtime == safari ]
-round_test: Fail, OK # Common JavaScript engine Math.round bug.
 
 [ $compiler == dart2js && $system == windows ]
 canonicalization_hashing_memoize_array_test: Skip # Issue 37631
 canonicalization_hashing_memoize_instance_test: Skip # Issue 37631
 canonicalization_hashing_shallow_collision_array_test: Skip # Issue 37631
 canonicalization_hashing_shallow_collision_instance_test: Skip # Issue 37631
-string_literals_test: Pass, RuntimeError # Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be
 
-[ $compiler == dart2js && $checked ]
-canonical_const2_test: RuntimeError, OK # non JS number semantics
-const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
-const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
-deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
-double_int_to_string_test: RuntimeError, OK # non JS number semantics
-expect_test: RuntimeError, OK # Issue 13080
-full_stacktrace1_test: RuntimeError # Issue 12698
-full_stacktrace2_test: RuntimeError # Issue 12698
-full_stacktrace3_test: RuntimeError # Issue 12698
-generalized_void_syntax_test: CompileTimeError # Issue #30176.
-generic_function_dcall_test/01: Crash # Unsupported operation: Unsupported type parameter type node T.
-generic_tearoff_test: Crash # Unsupported operation: Unsupported type parameter type node T.
-identical_closure2_test: RuntimeError # non JS number semantics
-infinity_test: RuntimeError # non JS number semantics - Issue 4984
-integer_division_by_zero_test: RuntimeError # Issue 8301
-invocation_mirror2_test: RuntimeError # mirrors not supported
-left_shift_test: RuntimeError # non JS number semantics
-mint_arithmetic_test: RuntimeError # non JS number semantics
-mock_writable_final_field_test: RuntimeError # Issue 30847
-modulo_test: RuntimeError # non JS number semantics
-nan_identical_test: RuntimeError # Issue 11551
-numbers_test: RuntimeError, OK # non JS number semantics
-regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
-regress_31057_test: Crash # Unsupported operation: Unsupported type parameter type node B.
-stacktrace_demangle_ctors_test: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
-stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
-stacktrace_test: RuntimeError # Issue 12698
-truncdiv_zero_test: RuntimeError # non JS number semantics - Issue 15246
-type_parameter_test/06: Crash # Internal Error: Unexpected type variable in static context.
-type_parameter_test/09: Crash # Internal Error: Unexpected type variable in static context.
-type_variable_scope_test/03: Crash # Internal Error: Unexpected type variable in static context.
-
-[ $compiler == dart2js && $host_checked ]
-async_return_types_test/nestedFuture: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
-async_star_cancel_while_paused_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
-await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
-closure_self_reference_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.
-issue23244_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
-partial_tearoff_instantiation_test/05: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-partial_tearoff_instantiation_test/06: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-partial_tearoff_instantiation_test/07: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-partial_tearoff_instantiation_test/08: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-
-[ $compiler == dart2js && $minified ]
-async_return_types_test/nestedFuture: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
-async_star_cancel_while_paused_test: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
-await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
-cyclic_type2_test: RuntimeError # Issue 31054
-cyclic_type_test/0*: RuntimeError # Issue 31054
-f_bounded_quantification4_test: RuntimeError # Issue 31054
-f_bounded_quantification5_test: RuntimeError # Issue 31054
-generic_closure_test/01: RuntimeError # Uses runtimeType.toString()
-invocation_mirror2_test: RuntimeError # mirrors not supported
-issue23244_test: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
-mixin_generic_test: RuntimeError # Issue 12605
-mixin_mixin2_test: RuntimeError # Issue 31054
-mixin_mixin3_test: RuntimeError # Issue 31054
-mixin_mixin4_test: RuntimeError # Issue 31054
-mixin_mixin5_test: RuntimeError # Issue 31054
-mixin_mixin6_test: RuntimeError # Issue 31054
-mixin_mixin_bound2_test: RuntimeError # Issue 31054
-mixin_mixin_bound_test: RuntimeError # Issue 31054
-mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
-regress_21795_test: RuntimeError # Issue 12605
-runtime_type_function_test: RuntimeError # Uses runtimeType.toString()
-stack_trace_test: RuntimeError, OK # Stack trace not preserved in minified code.
-symbol_conflict_test: RuntimeError # Issue 23857
diff --git a/tests/language_2/setter_no_getter_test.dart b/tests/language_2/setter_no_getter_test.dart
index 756ccb0..f2ea3e3 100644
--- a/tests/language_2/setter_no_getter_test.dart
+++ b/tests/language_2/setter_no_getter_test.dart
@@ -16,7 +16,7 @@
 
   Example ex = new Example();
   print(ex.foo++);
-  //       ^
-  // [analyzer] unspecified
+  //       ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
   // [cfe] The getter 'foo' isn't defined for the class 'Example'.
 }
diff --git a/tests/language_2/variance/syntax/variance_disabled_keyword_identifier_syntax_test.dart b/tests/language_2/variance/syntax/variance_disabled_keyword_identifier_syntax_test.dart
new file mode 100644
index 0000000..0d6828c
--- /dev/null
+++ b/tests/language_2/variance/syntax/variance_disabled_keyword_identifier_syntax_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 A<out> {}
+
+class B<inout> {}
+
+class C<out, inout> {}
+
+F<inout, out>() {}
+
+mixin G<out, inout> {}
+
+typedef H<inout, out> = out Function(inout);
+
+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/variance/syntax/variance_disabled_syntax_test.dart b/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
index 9230532..0ae03df 100644
--- a/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
+++ b/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
@@ -2,40 +2,75 @@
 // for 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.
+// Tests with `variance` flag 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.
+import 'package:expect/expect.dart';
+
+abstract class A<in X> {
+//               ^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+  int foo(X bar);
+}
 
 class B<out X, in Y, inout Z> {}
-//          ^
-// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
-// [cfe] Expected ',' before this.
+//      ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
 //             ^^
-// [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.
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+//                   ^^^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
 
-mixin C<inout T> {}
-//            ^
-// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
-// [cfe] Expected ',' before this.
+class C<in T> extends A<T> {
+//      ^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+  @override
+  int foo(T bar) {
+    return 2;
+  }
+}
 
-typedef D<out T> = T Function();
-//            ^
-// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
-// [cfe] Expected ',' before this.
+mixin D<out T> {}
+//      ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+
+class E1 {}
+
+mixin E<in T extends E1> {}
+//      ^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+
+class F<out T> = Object with D<T>;
+//      ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+
+class G<out out> {}
+//      ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+
+class H<out inout> {}
+//      ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] This requires the 'variance' experiment to be enabled.
+
+main() {
+  B<int, String, bool> b = B();
+
+  C<int> c = C();
+  Expect.equals(2, c.foo(3));
+
+  F<int> f = F();
+
+  G<int> g = G();
+
+  H<int> h = H();
+}
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
index 5028b51..a0bf3d7 100644
--- a/tests/language_2/variance/syntax/variance_keyword_identifier_syntax_test.dart
+++ b/tests/language_2/variance/syntax/variance_keyword_identifier_syntax_test.dart
@@ -2,10 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Tests identifier usage of keywords `out` and `inout`, correct usage of `in`.
+// Tests identifier usage of keywords `out` and `inout`, correct usage of `in`
+// with the experimental flag `variance` enabled.
+
+// SharedOptions=--enable-experiment=variance
 
 import "package:expect/expect.dart";
 
+class A<out> {}
+
+class B<inout> {}
+
+class C<out, inout> {}
+
+F<inout, out>() {}
+
+mixin G<out, inout> {}
+
+typedef H<inout, out> = out Function(inout);
+
 class OutParameter {
   var out = 3;
   int func(int out) {
diff --git a/tests/language_2/variance/syntax/variance_syntax_test.dart b/tests/language_2/variance/syntax/variance_syntax_test.dart
new file mode 100644
index 0000000..9a40965
--- /dev/null
+++ b/tests/language_2/variance/syntax/variance_syntax_test.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.
+
+// SharedOptions=--enable-experiment=variance
+
+import 'package:expect/expect.dart';
+
+abstract class A<in X> {
+  int foo(X bar);
+}
+
+class B<out X, in Y, inout Z> {}
+
+class C<in T> extends A<T> {
+  @override
+  int foo(T bar) {
+    return 2;
+  }
+}
+
+mixin D<out T> {}
+
+class E1 {}
+
+mixin E<in T extends E1> {}
+
+class F<out T> = Object with D<T>;
+
+class G<out out> {}
+
+class H<out inout> {}
+
+main() {
+  B<int, String, bool> b = B();
+
+  C<int> c = C();
+  Expect.equals(2, c.foo(3));
+
+  F<int> f = F();
+
+  G<int> g = G();
+
+  H<int> h = H();
+}
diff --git a/tests/language_2/variance/syntax/variance_type_parameter_error_syntax_test.dart b/tests/language_2/variance/syntax/variance_type_parameter_error_syntax_test.dart
new file mode 100644
index 0000000..a2503b8
--- /dev/null
+++ b/tests/language_2/variance/syntax/variance_type_parameter_error_syntax_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests erroneous usages of variance in unapplicable type parameters.
+
+// SharedOptions=--enable-experiment=variance
+
+void A(out int foo) {
+//     ^^^
+// [analyzer] COMPILE_TIME_ERROR.BUILT_IN_IDENTIFIER_AS_TYPE
+// [cfe] 'out' isn't a type.
+//     ^
+// [cfe] Type 'out' not found.
+//             ^^^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ')' before this.
+  List<out String> bar;
+  //  ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The method '<' isn't defined for the class 'Type'.
+  //   ^^^
+  // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+  // [cfe] Expected ';' after this.
+  //   ^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Getter not found: 'out'.
+  //             ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The method '>' isn't defined for the class 'Type'.
+  //               ^^^
+  // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+  // [cfe] Getter not found: 'bar'.
+}
+
+void B(out foo) {}
+//     ^^^
+// [analyzer] COMPILE_TIME_ERROR.BUILT_IN_IDENTIFIER_AS_TYPE
+// [cfe] 'out' isn't a type.
+//     ^
+// [cfe] Type 'out' not found.
+
+class C<in out X, out out Y> {}
+//         ^^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+//                    ^^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+
+class D<in out inout in out X> {}
+//         ^^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+//             ^^^^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+//                   ^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+//                      ^^^
+// [analyzer] SYNTACTIC_ERROR.MULTIPLE_VARIANCE_MODIFIERS
+// [cfe] Each type parameter can have at most one variance modifier.
+
+typedef E<out T> = T Function(T a);
+//            ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
diff --git a/tests/language_2/vm/regression_38436.dart b/tests/language_2/vm/regression_38436.dart
new file mode 100644
index 0000000..ea5fafd
--- /dev/null
+++ b/tests/language_2/vm/regression_38436.dart
@@ -0,0 +1,2362 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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";
+
+// Found by DartFuzzing: would sometimes crash on OSR
+// https://github.com/dart-lang/sdk/issues/38436
+
+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';
+
+String var0 = '';
+bool var1 = true;
+int var2 = -30;
+double var3 = 0.895077679110543;
+String var4 = '';
+List<int> var5 = [55, -70];
+Set<int> var6 = {
+  1024,
+  for (int loc0 in [
+    79,
+    ...[23],
+    ...[90, -89, -24],
+    -90,
+    11,
+    -19,
+    -91
+  ])
+    -55,
+  67,
+  -80,
+  for (int loc0 = 0; loc0 < 29; loc0++) 20,
+  for (int loc0 = 0; loc0 < 24; loc0++) ...{23, -41},
+  ...{
+    -75,
+    128,
+    9223372034707292159,
+    -56,
+    -59,
+    for (int loc0 in {
+      -67,
+      for (int loc1 in [-27, -59, 31, 32, -66, -87]) -9223372036854775680,
+      85,
+      -45,
+      if (false) 70,
+      13,
+      43,
+      48
+    })
+      if (true) 63,
+    ...{-90, -24, -9223372036854743041, -9223372032559808383, 86},
+    -25
+  }
+};
+Map<int, String> var7 = {
+  6: '',
+  ...{56: 'B\u2665pwO', 73: 'ZJDi\u{1f600}m'},
+  ...{73: ')', 14: '93Q'},
+  98: 'xA0jQL',
+  21: ')\u2665TOy',
+  for (int loc0 = 0; loc0 < 82; loc0++) 34: 'Q3\u2665#61',
+  ...{70: 'XXRXl3O', 56: '\u2665lda2Zy', 38: 'Dr#mtz', 6: 'nx'},
+  27: '('
+};
+
+Set<int> foo0() {
+  var3 += ((((var0 + var7[var5[88]])).isEmpty ? true : var1)
+      ? (var1 ? (var3 ?? var3) : var3)
+      : (var1 ? 0.24414824314186978 : var3));
+  var1 ??= true;
+  return {(var2--), Duration.secondsPerHour, var5[var2]};
+}
+
+Map<int, String> foo1(List<int> par1, bool par2) {
+  throw ((-(var3)) * (-(0.943305664017911)));
+}
+
+List<int> foo2(Set<int> par1, List<int> par2, Map<int, String> par3) {
+  switch (-49) {
+    case 4149672951:
+      {
+        for (int loc0 in foo0()) {
+          var6 = var6;
+          try {
+            for (int loc1 = 0; loc1 < 70; loc1++) {
+              switch (((var1
+                      ? ((var1 ? var1 : true) ? Float32x4.xzzw : (--var2))
+                      : (4295032831 % (loc1 + 93))))
+                  .floor()) {
+                case 3294548737:
+                  {
+                    var5[Int32x4.xxwy] ^=
+                        (loc0 * ('!').compareTo(((!(true)) ? var4 : 'S')));
+                  }
+                  break;
+                case 3294548738:
+                  {
+                    var0 = var4;
+                    loc0 <<= Int32x4.zwxz;
+                  }
+                  break;
+              }
+              {
+                int loc2 = 0;
+                do {
+                  var1 = ('Ncb\u2665P9K').isEmpty;
+                  var1 ??= (!(true));
+                } while (++loc2 < 91);
+              }
+            }
+            par3 ??= {
+              44: ((false
+                      ? false
+                      : ((true
+                              ? var7
+                              : {
+                                  17: par3[(var5[-73] - -20)],
+                                  80: var7[
+                                      ((++loc0) ~/ ((!(false)) ? 47 : var2))],
+                                  30: '8Qvz3',
+                                  36: '',
+                                  10: (('@B!0bW6' + var4)).toLowerCase(),
+                                  89: var7[-9223372036854775296],
+                                  4: ') '
+                                }) !=
+                          var7))
+                  ? ((var1 || (!(var1))) ? var7[Float32x4.wxzw] : var7[-7])
+                  : '8h'),
+              for (int loc1 in [
+                (false
+                    ? ((([
+                                  var2,
+                                  -39,
+                                  -74,
+                                  Float32x4.zzxy,
+                                  (~(var5[(67 + -86)])),
+                                  -53
+                                ] +
+                                [(var2++), var5[par2[(--loc0)]]]) !=
+                            [
+                              var5[var5[var5[(loc0++)]]],
+                              loc0,
+                              loc0,
+                              -55,
+                              -69,
+                              loc0
+                            ])
+                        ? (loc0--)
+                        : loc0)
+                    : var2),
+                (75 ^ 93),
+                (false ? var5[Float32x4.xzyw] : (loc0++)),
+                ...[
+                  for (int loc2 in {
+                    -22,
+                    (loc0 ^ 2),
+                    var5[(-((par2[-79] * 86)))],
+                    (++loc0),
+                    ((par2[var5[-45]] ?? 55) >> (true ? Int32x4.wyww : -45)),
+                    (~((++var2))),
+                    par2[var2]
+                  })
+                    (loc0--),
+                  if ((var7[(false ? (-(loc0)) : 19)]).endsWith(var4))
+                    (++var2)
+                  else
+                    (var1 ? loc0 : 39),
+                  (((var2++) & var2) & -26),
+                  if (false) (var1 ? Float32x4.wzzw : var5[129]),
+                  for (int loc2 in {
+                    (loc0--),
+                    (true ? loc0 : loc0),
+                    var2,
+                    var5[(0.4452451921266031).floor()],
+                    (~(-4294967196)),
+                    (loc0--),
+                    (--var2)
+                  })
+                    (var1 ? -30 : (loc0++)),
+                  (~((var1 ? 51 : var2))),
+                  (((var3 ?? pi) < 0.9098824013356337)
+                      ? ((true ? 57 : -48) << (--var2))
+                      : par2[-59])
+                ]
+              ])
+                84: var4,
+              57: var4
+            };
+          } catch (exception, stackTrace) {
+            /**
+           ** Multi-line
+           ** documentation comment.
+           */
+            for (int loc1 = 0; loc1 < 89; loc1++) {
+              switch ((var2--)) {
+                case 3807258589:
+                  {
+                    print(({
+                          (-34 ^
+                              ((false || var1)
+                                  ? 24
+                                  : (-(((-((var1
+                                          ? par2[(-(71))]
+                                          : 9223372032559808768))) +
+                                      (~(loc1))))))),
+                          (~((true ? loc0 : (false ? -75 : 33)))),
+                          Float32x4.zxwz,
+                          (false ? (15 * -83) : (var2--)),
+                          ((var7 !=
+                                  ((true ? var1 : false)
+                                      ? var7
+                                      : {
+                                          99: (true ? 'TobD' : var0),
+                                          59: (var4 ?? var4),
+                                          13: var4,
+                                          58: Uri.encodeFull(var4),
+                                          99: var7[loc1]
+                                        }))
+                              ? loc1
+                              : (var1
+                                  ? ((72 >> -15) ~/ (loc0--))
+                                  : -9223372030412324864)),
+                          32
+                        } ??
+                        par1));
+                  }
+                  break;
+                case 3807258592:
+                  {
+                    var1 ??= true;
+                    try {
+                      var7 = {9: (var1 ? 'ON' : 'f\u{1f600}b')};
+                      par2 = (true
+                          ? var5
+                          : [
+                              DateTime.january,
+                              (40 - (~(var2))),
+                              (var1 ? (--loc0) : 23),
+                              var5[(--var2)]
+                            ]);
+                    } catch (exception, stackTrace) {
+                      var3 /= 0.9998663372091022;
+                    } finally {
+                      par2 ??= ((var1
+                              ? false
+                              : (((par1 ??
+                                          {
+                                            -68,
+                                            86,
+                                            -33,
+                                            var5[(-9223372034707292159 - 90)],
+                                            (24 - (++var2)),
+                                            (-(var2)),
+                                            (loc1 * Int32x4.wyxx)
+                                          }))
+                                      .difference({
+                                    (var1 ? Float32x4.yzyw : (loc1 % loc0)),
+                                    6,
+                                    22,
+                                    91,
+                                    loc0,
+                                    (true ? loc1 : loc1)
+                                  }) ==
+                                  foo0()))
+                          ? par2
+                          : [
+                              (var2--),
+                              (-((++loc0))),
+                              ((-(var5[-52])) ~/
+                                  (true ? Int32x4.wyyy : (loc0--))),
+                              (var3).toInt()
+                            ]);
+                      var5[99] += (~(Float32x4.ywxw));
+                    }
+                  }
+                  break;
+              }
+              var5 = (par2 ??
+                  [
+                    ...[72],
+                    for (int loc2 in {Float32x4.xxwz, loc1})
+                      ((loc0--) ~/ (var2++)),
+                    par2[(++var2)],
+                    (-((--var2))),
+                    (var2++),
+                    -56,
+                    (~((~(loc0)))),
+                    for (int loc2 in {
+                      (-((~(17)))),
+                      Float32x4.zzzw,
+                      Float32x4.zyyz,
+                      (var2--),
+                      (Int32x4.wzwz % 78),
+                      loc0
+                    })
+                      Int32x4.xzzy
+                  ]);
+            }
+            {
+              int loc1 = 0;
+              do {
+                loc0 &= (-(4295000065));
+              } while (++loc1 < 94);
+            }
+          } finally {
+            var3 -= 0.020483900923215503;
+            try {
+              return [
+                ...[
+                  (loc0--),
+                  for (int loc1 in {Float32x4.yxyz})
+                    if (var1) (~(-35)) else loc0,
+                  (++loc0),
+                  for (int loc1 = 0; loc1 < 43; loc1++)
+                    (var5[var5[par2[var5[-9223372032559808384]]]] &
+                        Int32x4.yzxy),
+                  for (int loc1 = 0; loc1 < 98; loc1++) (-((~(Int32x4.xwwy)))),
+                  Float32x4.yzzz
+                ],
+                (-(Int32x4.xzxz))
+              ];
+            } catch (exception, stackTrace) {
+              for (int loc1
+                  in (((((!((((0.13101852551635873 == 0.4825498460563603)
+                                          ? var7
+                                          : var7) !=
+                                      var7)))
+                                  ? 1
+                                  : par2[var2]))
+                              .isEven
+                          ? {
+                              (var2++),
+                              (-48 | -54),
+                              (~(par2[loc0])),
+                              par2[var5[Int32x4.zyzz]],
+                              -2,
+                              (true ? (~((-(((!(false)) ? -11 : var2))))) : 73),
+                              if ((0.15992181539430828).isInfinite) (++var2)
+                            }
+                          : (false ? {-6} : {((++loc0) % 27), 92})) ??
+                      Set.identity())) {
+                var6 ??= foo0();
+              }
+              var5[(~(((true ? -10 : Float32x4.zzwy) -
+                  Duration.millisecondsPerSecond)))] = (~((var2--)));
+            }
+          }
+        }
+        par3.forEach((loc0, loc1) {
+          // Single-line comment.
+          var6 = (var6 ?? foo0());
+          par1 = {
+            if (('X2yPgV').endsWith('b'))
+              Float32x4.yxxy
+            else if (true)
+              Int32x4.xzyw
+            else
+              for (int loc2 = 0; loc2 < 9; loc2++) (++loc0),
+            (4294967551 ?? (-((loc0--)))),
+            (-69 ~/
+                ((!(false))
+                    ? ((((par2[Int32x4.zwzw]).isEven
+                                ? (var3).truncateToDouble()
+                                : 0.14035347150303745))
+                            .isInfinite
+                        ? Int32x4.yzxx
+                        : par2[loc0])
+                    : (var2++))),
+            ((loc0++) - ((++var2) >> (~(par2[(var2--)]))))
+          };
+        });
+      }
+      break;
+    case 4149672955:
+      {
+        par2[((var2 ^ (~((--var2)))) | -98)] *= -62;
+        {
+          int loc0 = 0;
+          do {
+            var0 = par3[(var5[4294967808] >> Float32x4.wwyx)];
+          } while (++loc0 < 46);
+        }
+      }
+      break;
+  }
+  var1 ??= (!((var3).isNaN));
+  return (var1
+      ? par2
+      : Uri.parseIPv6Address(
+          (var1 ? '' : '26DgiI'), (ZLibOption.maxMemLevel % 65), 68));
+}
+
+class X0 {
+  bool fld0_0 = true;
+  Set<int> fld0_1 = {
+    31,
+    if (true) ...{
+      -93,
+      -4294967041,
+      -4294934527,
+      if (false) 92,
+      if (true) 69
+    } else
+      85,
+    ...{
+      ...{73, 27},
+      for (int loc0 in {
+        for (int loc1 = 0; loc1 < 56; loc1++) -36,
+        -23,
+        -99,
+        20,
+        16,
+        11,
+        if (false) -24,
+        if (true) 14
+      })
+        if (false) 69,
+      -9223372032559808513,
+      -9223372036854775553,
+      -9223372036854774784,
+      -22
+    },
+    81,
+    ...{16, if (false) 67 else -30, if (true) 21 else -61, -84},
+    -69
+  };
+
+  List<int> foo0_0(Map<int, String> par1) {
+    if ((var1 ? ((!(fld0_0)) ? true : false) : true)) {
+      return ((var4).trim()).codeUnits;
+    } else {
+      for (int loc0 in var6) {
+        fld0_0 ??= var1;
+        for (int loc1 = 0; loc1 < 57; loc1++) {
+          {
+            Map<int, String> loc2 = Map.identity();
+            par1 ??= Map.unmodifiable(Map.unmodifiable(Map.unmodifiable((true
+                ? loc2
+                : ((true
+                        ? loc2
+                        : foo1(
+                            [var5[-60], loc0, var5[-48], -80, var5[var5[37]]],
+                            var1)) ??
+                    {
+                      60: var0,
+                      93: ((false ? var0 : '') + 'r\u{1f600}2B#p')
+                    })))));
+            var4 = ' ';
+          }
+          try {
+            var5 = foo2(
+                ({loc0, 37, Float32x4.wwyw} ?? var6),
+                ((fld0_0
+                        ? [
+                            for (int loc2 = 0; loc2 < 1; loc2++)
+                              (~(Float32x4.zyzz)),
+                            (~((true
+                                ? (Float32x4.yyzw >> (48 - (-((var2--)))))
+                                : (~(loc0))))),
+                            ((var4 ==
+                                    String.fromEnvironment(
+                                        (var1 ? 'l9FM' : par1[var5[loc0]])))
+                                ? (++loc0)
+                                : 4),
+                            ...[
+                              (~((var5[-9223372032559808448] - (++var2)))),
+                              ...[
+                                for (int loc2 in [
+                                  ((-12 <= 55) ? 9223372032559841280 : loc0),
+                                  var5[var5[(~(var5[var5[loc1]]))]],
+                                  (var1 ? 67 : -74)
+                                ])
+                                  (var5[var2]).sign,
+                                var5[-65],
+                                if (fld0_0)
+                                  var5[(var5[var5[-90]] ~/ 22)]
+                                else
+                                  (-9223372036854775679 + var5[16]),
+                                76,
+                                7
+                              ],
+                              (++var2),
+                              -9223372034707292160,
+                              (var2--),
+                              var5[(var2--)]
+                            ],
+                            loc1,
+                            Float32x4.ywxz,
+                            ((++loc0) + (--loc0)),
+                            for (int loc2 in [
+                              for (int loc3 = 0; loc3 < 4; loc3++) loc1,
+                              ...[
+                                Float32x4.zxwy,
+                                Float32x4.xzwx,
+                                var2,
+                                (++var2),
+                                Int32x4.xzyy,
+                                (var5[loc1] | (true ? -97 : -93)),
+                                Float32x4.xwyz,
+                                ((true || var1)
+                                    ? (~((--loc0)))
+                                    : (~((var5[18] % (-55 + loc0)))))
+                              ],
+                              (~((++loc0))),
+                              -85,
+                              (~((var2++))),
+                              (true
+                                  ? ZLibOption.maxMemLevel
+                                  : var5[var5[var5[var5[var2]]]]),
+                              ((true
+                                      ? ((!((false
+                                              ? (true ? fld0_0 : (!(false)))
+                                              : fld0_0)))
+                                          ? fld0_0
+                                          : (({
+                                                96: var4,
+                                                60: '(0yBGn\u{1f600}',
+                                                57: var4,
+                                                73: var7[-43],
+                                                38: var0
+                                              })
+                                                  .isNotEmpty ||
+                                              ({
+                                                67: var4,
+                                                14: 'M\u{1f600}1HNbP',
+                                                6: 's',
+                                                85: 'uyq',
+                                                95: var7[(-(Int32x4.wwxw))],
+                                                33: ''
+                                              })
+                                                  .isNotEmpty))
+                                      : false)
+                                  ? var2
+                                  : (++var2))
+                            ]) ...[-27]
+                          ]
+                        : [
+                            for (int loc2 = 0; loc2 < 87; loc2++)
+                              (-47 * (~((((--var2) ^ loc0) ?? 78)))),
+                            (-(((({
+                                  14: (var3).toStringAsExponential(
+                                      (false ? var5[-62] : 33)),
+                                  16: '',
+                                  71: var4,
+                                  78: (([var5[(-(91))]] == var5) ? var4 : var0),
+                                  9: par1[loc1],
+                                  51: '-8ht',
+                                  26: ('(2l3\u2665h' ?? var0),
+                                  79: var4
+                                })
+                                        .isNotEmpty
+                                    ? var5[(var2 % loc0)]
+                                    : var2) %
+                                ((!(NetworkInterface.listSupported))
+                                    ? -22
+                                    : ((var1
+                                            ? ([
+                                                  ZLibOption.STRATEGY_DEFAULT,
+                                                  21,
+                                                  loc1,
+                                                  loc1,
+                                                  loc0,
+                                                  5,
+                                                  loc0,
+                                                  98
+                                                ] ==
+                                                Uri.parseIPv4Address(
+                                                    var7[loc1]))
+                                            : var1)
+                                        ? (~((-20 %
+                                            (var5).removeAt(Float32x4.wyxw))))
+                                        : var5[var5[82]]))))),
+                            (-(Float32x4.wwwz)),
+                            Int32x4.wxxz,
+                            ...[
+                              (loc0++),
+                              ...[
+                                (--loc0),
+                                -2,
+                                ZLibOption.DEFAULT_WINDOW_BITS,
+                                -42,
+                                for (int loc2 = 0; loc2 < 2; loc2++) (-(-22)),
+                                (~(-81))
+                              ],
+                              (--var2)
+                            ],
+                            (++var2),
+                            ((!(false)) ? (--var2) : (((~(34)) >> 48) << 79)),
+                            loc1
+                          ]) +
+                    foo2(
+                        foo0(),
+                        ([
+                              (((~(var5[(-(var5[(87 % var5[(++var2)])]))])) ??
+                                      -11) ~/
+                                  (var2++)),
+                              ((((!(var1)) && true) ? loc1 : 98) <<
+                                  ((!((true != (var4 == par1[var5[(~(-83))]]))))
+                                      ? -44
+                                      : var5[88])),
+                              Float32x4.yyyz,
+                              -44,
+                              Int32x4.xzyx,
+                              (++loc0)
+                            ] ??
+                            [
+                              ((foo1([((!(var1)) ? 24 : 81), -93], true))
+                                      .isEmpty
+                                  ? 52
+                                  : (~(Int32x4.zyww))),
+                              Int32x4.xxwz,
+                              (-(-11)),
+                              (loc0--),
+                              ((!(bool.fromEnvironment('U\u2665')))
+                                  ? (loc0++)
+                                  : (++var2))
+                            ]),
+                        {
+                          70: var7[7],
+                          18: '\u2665(#&c\u{1f600}-',
+                          58: 'KuNr',
+                          96: '\u{1f600}2\u2665YY',
+                          94: var0,
+                          28: 'l-'
+                        })),
+                par1);
+            {
+              double loc2 = double.infinity;
+              /*
+               * Multi-line
+               * comment.
+               */
+              return ('a!wNh!').codeUnits;
+            }
+          } catch (exception, stackTrace) {
+            continue;
+          } finally {
+            fld0_0 = (!(fld0_0));
+            var5 ??= ((Uri.parseIPv4Address('H') ??
+                    (foo2({
+                          loc1,
+                          ([
+                                if (((true ? loc0 : (loc0++)) <
+                                    ((!(var1)) ? -90 : Int32x4.yyzx)))
+                                  (~(var2))
+                                else
+                                  for (int loc2 in {
+                                    if (SecurityContext.alpnSupported)
+                                      var2
+                                    else
+                                      Int32x4.wzzy,
+                                    -9223372036754112763,
+                                    (-((var1
+                                        ? var5[62]
+                                        : (-(Float32x4.wzwz))))),
+                                    (~(Float32x4.yxzy))
+                                  })
+                                    ((((true && (false ? fld0_0 : var1))
+                                                ? fld0_0
+                                                : false)
+                                            ? true
+                                            : (fld0_0 && var1))
+                                        ? (true ? (~(loc1)) : var5[-16])
+                                        : loc0),
+                                for (int loc2 = 0; loc2 < 1; loc2++)
+                                  ((false && var1) ? Float32x4.yzyy : 50)
+                              ][var2] *
+                              [
+                                ...[
+                                  (((-10 >> Int32x4.wxzw) *
+                                          ((0.42979687169554437 >=
+                                                  0.17848133910264385)
+                                              ? -4
+                                              : var5[-15])) |
+                                      var5[(loc0++)]),
+                                  ...[
+                                    (('@jcNl\u2665P')
+                                            .compareTo(var7[(loc0--)]) &
+                                        (~((~(loc0))))),
+                                    if ((!(((!(true)) && true)))) 2,
+                                    loc1,
+                                    ((var5[(loc0--)] | -38) & (loc0++)),
+                                    var2,
+                                    (~(-22)),
+                                    if (false) loc0 else 80,
+                                    (--loc0)
+                                  ],
+                                  ...[15],
+                                  ((~((~(-5)))) ^ Int32x4.xxxz),
+                                  79,
+                                  for (int loc2 in [
+                                    (fld0_0 ? -0 : (loc0++)),
+                                    -49,
+                                    for (int loc3 in [
+                                      -16,
+                                      (var2--),
+                                      35,
+                                      ((14 * -68) ~/ Int32x4.wwyy)
+                                    ])
+                                      var5[(fld0_0 ? 28 : (-41 ?? 19))],
+                                    loc0,
+                                    (var3).round(),
+                                    if ((!((!((!(false))))))) loc1,
+                                    (loc0++),
+                                    Int32x4.wyww
+                                  ])
+                                    ((--var2) * var5[(6 & var5[(~(-53))])]),
+                                  (loc0++),
+                                  Float32x4.xwxx
+                                ],
+                                Int32x4.ywyw,
+                                (-(ZLibOption.strategyFixed)),
+                                (80 % (loc0--)),
+                                var5[Int32x4.zxww]
+                              ][var5[50]]),
+                          (false ? -71 : 39),
+                          (var5[-61]).toSigned(loc0),
+                          -50,
+                          4294967296
+                        }, [
+                          (16 *
+                              (~(((var1 ? ZLibOption.STRATEGY_FIXED : -66) *
+                                  4)))),
+                          Float32x4.wwwx
+                        ], {
+                          63: var0,
+                          52: (fld0_0 ? 'uG\u2665V@4' : '62'),
+                          98: var7[var5[-83]],
+                          70: (false
+                              ? 'bSg'
+                              : base64UrlEncode(([
+                                    (~(var2)),
+                                    -52,
+                                    68,
+                                    [
+                                      10,
+                                      loc1,
+                                      92,
+                                      53,
+                                      Int32x4.zzyw,
+                                      (true ? 12 : 19),
+                                      (~(var5[(++var2)]))
+                                    ][-64],
+                                    (++loc0),
+                                    (loc0 << -26)
+                                  ] +
+                                  [
+                                    var5[(--loc0)],
+                                    (((var1 ? var5[var5[(var2--)]] : loc1) +
+                                            (--var2)) <<
+                                        Int32x4.wyyx)
+                                  ]))),
+                          16: 'YsD\u2665\u2665K',
+                          0: var0,
+                          93: var7[(-(var5[-43]))]
+                        }) ??
+                        var5)) ??
+                [
+                  if (fld0_0) -90,
+                  (--var2),
+                  ...[
+                    for (int loc2 in [
+                      (false ? (~(-9)) : -4294901760),
+                      (-(-7)),
+                      -51,
+                      (var1 ? -75 : [Float32x4.wwxw, Int32x4.zxyx][-7]),
+                      Float32x4.xyww,
+                      Int32x4.wwzx,
+                      (loc0++),
+                      (NetworkInterface.listSupported
+                          ? [1000][Float32x4.zzyx]
+                          : -71)
+                    ])
+                      -27,
+                    Float32x4.wyzy,
+                    (++var2)
+                  ]
+                ]);
+          }
+        }
+      }
+      throw Map.unmodifiable(foo1(
+          (MapBase.mapToString(foo1((false ? [var2] : var5), false))).codeUnits,
+          true));
+    }
+  }
+
+  void run() {}
+}
+
+class X1 extends X0 {
+  double fld1_0 = 0.47694301047645304;
+  bool fld1_1 = true;
+
+  Map<int, String> foo1_0(
+      Map<int, String> par1, Map<int, String> par2, double par3) {
+    // Single-line comment.
+    for (int loc0 = 0; loc0 < 91; loc0++) {
+      par2.forEach((loc1, loc2) {
+        {
+          bool loc3 = (fld1_1 || ('U\u2665').isEmpty);
+          var3 /= 0.8504341352135224;
+        }
+      });
+      {
+        int loc1 = 66;
+        while (--loc1 > 0) {
+          if (((!((true || fld1_1))) == true)) {
+            var0 ??= par2[var5[(~((false ? ((!(var1)) ? -95 : var2) : -37)))]];
+            /**
+             ** Multi-line
+             ** documentation comment.
+             */
+            return Map.unmodifiable({
+              55: var4,
+              73: 'c#',
+              17: (fld1_1
+                  ? '7\u{1f600}e'
+                  : ((!(var1)) ? '8E7AK2e' : 'Fm\u{1f600} F')),
+              40: 'mb(\u{1f600}\u2665l',
+              36: Uri.decodeFull((true ? par2[-32769] : var7[Float32x4.zyxz])),
+              51: ((false &&
+                      (((var1 ? true : true) || false)
+                          ? (var7[(var2--)]).isEmpty
+                          : true))
+                  ? (fld1_1
+                      ? (fld1_1 ? (var1).toString() : 'r9M')
+                      : ((true ? (0.2863696758528199 != par3) : false)
+                          ? (fld1_1 ? par1[Int32x4.zwyz] : var4)
+                          : var4))
+                  : var4),
+              8: '6G',
+              62: '+z@Gp'
+            });
+          } else {
+            var5[Int32x4.zzyy] ??= (-(var5[((!(false)) ? loc1 : -34)]));
+            {
+              int loc2 = (-(7));
+              var3 /= (true
+                  ? (-(((-9223372032459145467).isEven
+                      ? fld1_0
+                      : (-((-(0.7008573255099826)))))))
+                  : par3);
+            }
+          }
+          for (int loc2 in foo2(var6, var5, {
+            if (false) 11: par1[((var4).isEmpty ? 55 : -61)],
+            12: 'f5j2v\u{1f600}',
+            52: (((foo1(
+                            (((var1
+                                        ? {var5[-66], var2, 88, 12, 6, -96}
+                                        : (var1
+                                            ? {-25, 84, (var2--), var5[83]}
+                                            : {-36, var5[51], var2})) !=
+                                    {var5[(++var2)]})
+                                ? [-2147483648, 46, loc0, var5[loc0], -21]
+                                : foo2(
+                                    {var5[var5[loc0]]},
+                                    (true
+                                        ? var5
+                                        : [
+                                            -30,
+                                            var5[(-(-42))],
+                                            var2,
+                                            Float32x4.zywx,
+                                            loc1,
+                                            63,
+                                            -25,
+                                            -28
+                                          ]),
+                                    {30: 'j\u2665U', 98: var4})),
+                            false))
+                        .isNotEmpty
+                    ? (false ? fld1_0 : 0.3202297128057393)
+                    : 0.1301025669674245))
+                .toStringAsFixed(((fld1_1 ? 79 : -88) + Int32x4.xyzw)),
+            88: (false ? var7[(var2++)] : (var4 ?? '')),
+            31: (var1
+                ? (var1 ? par2[-87] : (true ? par2[-14] : var4))
+                : ((fld1_1 != true) ? '3nd9t&' : var4)),
+            22: ('(Czi' + '-Y')
+          })) {
+            var7[(loc2--)] = 's';
+          }
+        }
+      }
+    }
+    return par1;
+  }
+
+  String foo1_1(int par1) => var0;
+  Set<int> foo1_2(String par1) {
+    for (int loc0 = 0; loc0 < 58; loc0++) {
+      switch ((~(13))) {
+        case 746492976:
+          {
+            switch (Duration.millisecondsPerDay) {
+              case 3635015902:
+                {
+                  var7[var5[(var5[var2] * (-(var5[Float32x4.yxxz])))]] ??=
+                      (var7[-79] + '(O@');
+                  var7[loc0] ??= String.fromCharCode(var5[(true
+                      ? (var5[((var1 ? true : (false ? fld1_1 : var1))
+                              ? var5[Float32x4.wyyz]
+                              : 73)] ~/
+                          (-(84)))
+                      : -15)]);
+                }
+                break;
+              case 3635015905:
+                {
+                  var1 = (var1
+                      ? (foo1_0(
+                              (((!(false)) || fld1_1) ? var7 : var7),
+                              foo1_0(
+                                  {74: '\u2665e', 10: 'tw8jc0R'},
+                                  foo1_0(
+                                      var7,
+                                      foo1_0(
+                                          ({
+                                                17: var7[Int32x4.zyxy],
+                                                82: var7[64],
+                                                27: 'VEtj',
+                                                90: Uri.encodeQueryComponent(
+                                                    foo1_1(var2)),
+                                                68: 'wew0\u{1f600}'
+                                              } ??
+                                              foo1_0(var7, var7, var3)),
+                                          ({
+                                                65: 'mBeBfUj',
+                                                81: var4,
+                                                35: (var7[-43] + 'l'),
+                                                68: var4
+                                              } ??
+                                              {
+                                                33: ('N\u{1f600}xaY+' ?? par1),
+                                                44: var7[var5[var2]],
+                                                83: var4,
+                                                86: 'k'
+                                              }),
+                                          asin(0.4245871535895427)),
+                                      (-(0.2913717674787144))),
+                                  0.9439800024935644),
+                              (-((true
+                                  ? ((var1 ? false : var1)
+                                      ? 0.09441225978923817
+                                      : 0.42622157485045953)
+                                  : (-(0.29370792038584836)))))))
+                          .isNotEmpty
+                      : (false && true));
+                  var3 += (-(fld1_0));
+                }
+                break;
+            }
+          }
+          break;
+        case 746492979:
+          {
+            var4 = var0;
+            for (int loc1 = 0; loc1 < 88; loc1++) {
+              var2 += 32;
+            }
+          }
+          break;
+      }
+    }
+    {
+      int loc0 = 0;
+      do {
+        return foo0();
+      } while (++loc0 < 57);
+    }
+    return foo0();
+  }
+
+  String foo1_3() {
+    if ((0.42144855521066793).isNegative) {
+      print((false ? (-(fld1_0)) : (-((-((-(0.26854952952179667))))))));
+      switch (30) {
+        case 3830102525:
+          {
+            try {
+              var7.forEach((loc0, loc1) {
+                var1 = (!(true));
+                var6 = (foo1_2(var7[99]) ?? var6);
+              });
+              var6 ??= var6;
+            } catch (exception, stackTrace) {
+              var4 ??= ListBase.listToString([
+                (Duration.microsecondsPerSecond + -82),
+                (true
+                    ? var5[(var2 ~/ (false ? (~((var1 ? 46 : var2))) : var2))]
+                    : (-9223372034707292161 >> var5[var5[-86]])),
+                Float32x4.wxyx
+              ]);
+            } finally {
+              /**
+             ** Multi-line
+             ** documentation comment.
+             */
+              fld1_1 = (var5[var5[var2]]).isOdd;
+            }
+            /*
+           * Multi-line
+           * comment.
+           */
+            if ((SetBase.setToString((fld1_1
+                    ? {12, (fld1_1 ? (-(-22)) : (-(4395630341)))}
+                    : var6)))
+                .isNotEmpty) {
+              try {
+                {
+                  int loc0 = 86;
+                  while (--loc0 > 0) {
+                    {
+                      int loc1 = 0;
+                      do {
+                        var0 = var7[(-(((--var2) &
+                            ((var1 ? (fld1_0).isNaN : true)
+                                ? (-16 | -20)
+                                : ((0.7513819161190503).isNaN ? 45 : loc1)))))];
+
+                        /// Single-line documentation comment.
+                        var5[(true ? loc0 : Float32x4.zxzx)] %= loc0;
+                      } while (++loc1 < 17);
+                    }
+                    for (int loc1 = 0; loc1 < 25; loc1++) {
+                      var5[Float32x4.zywy] <<= Int32x4.ywwx;
+                    }
+                  }
+                }
+              } catch (exception, stackTrace) {
+                var7 = Map.from(foo1_0({
+                  81: (foo1_1(((++var2) * (-(var5[21])))) +
+                      (var7[8] + (var7[var5[53]] ?? var0))),
+                  for (int loc0 in [
+                    (true ? 58 : Float32x4.wyww),
+                    var5[(fld1_1 ? 46 : var2)]
+                  ])
+                    63: var7[(false
+                        ? var5[((24 >> -9223372036854710272) & var2)]
+                        : var5[(80 << var5[-31])])],
+                  67: var0,
+                  1: '3mlOA',
+                  30: ('OQbG').substring((var2--), (--var2)),
+                  93: ((var7[74] ?? var7[(++var2)])).toLowerCase(),
+                  ...{
+                    85: foo1_1(-21),
+                    if ((!((!(false))))) 86: var0,
+                    49: '62+v',
+                    59: foo1_1((--var2)),
+                    for (int loc0 in [
+                      -10,
+                      -65,
+                      (var2++),
+                      (var2++),
+                      ((({
+                                    ((var7[60] == var7[-30])
+                                        ? var5[(-((var2++)))]
+                                        : (var2--))
+                                  } ==
+                                  {var5[var2], -40, -81, (var2++), 93, 26})
+                              ? 38
+                              : (var1 ? var5[97] : -82)) *
+                          (--var2)),
+                      (~((true ? 5 : Float32x4.yxyy))),
+                      (var2++),
+                      ((++var2) << ((var2 % Int32x4.yxxw) >> (++var2)))
+                    ])
+                      54: (var0 + 'ANyqN'),
+                    94: (var1 ? '0T\u2665#w' : (var0).toUpperCase()),
+                    68: '@n',
+                    67: base64UrlEncode(((0.07857744084458451).isInfinite
+                        ? ([
+                              var2,
+                              var5[70],
+                              -32,
+                              Float32x4.yxwz,
+                              31,
+                              (~(var2)),
+                              (var2 ?? (-70 + 57)),
+                              -91
+                            ] +
+                            [
+                              var2,
+                              var5[((!(var1))
+                                  ? var5[(var2 ~/ Float32x4.zwyw)]
+                                  : var5[var5[(var5[(~(var2))] % var2)]])],
+                              (var2 | (false ? (-(var2)) : var5[80])),
+                              (var2--),
+                              DateTime.daysPerWeek,
+                              (var2 ~/ var2)
+                            ])
+                        : (var1 ? var5 : [(var2++)])))
+                  },
+                  if (false)
+                    if (false)
+                      26: (Uri.encodeComponent(foo1_1(var2)) + var7[var5[var2]])
+                    else ...{
+                      4: (double.negativeInfinity).toStringAsFixed(var2),
+                      46: Uri.decodeQueryComponent('bst3jz'),
+                      5: ((true
+                              ? (true ? '(-f' : var7[(-(Int32x4.yzxz))])
+                              : var7[(var5[(fld1_1 ? (var2--) : var2)] >>
+                                  (-((false ? 8589934591 : 33))))]) ??
+                          '4ov'),
+                      37: var7[var5[100663045]],
+                      13: '2B'
+                    }
+                }, {
+                  71: 'Hxbq',
+                  22: ('\u{1f600}Jtj').substring(
+                      (-36 | var5[(~((var2++)))]), 9223372032559874048)
+                }, 0.3710694748818374));
+                fld1_0 ??= 0.010604823956237519;
+              } finally {
+                for (int loc0 = 0; loc0 < 84; loc0++) {
+                  var5[Float32x4.xwwz] <<=
+                      ((((fld1_1 ? false : ('e\u{1f600}O+Vc').isNotEmpty) &&
+                                  (!(fld1_1)))
+                              ? (-73 | var5[Int32x4.yzwx])
+                              : Uint16List.bytesPerElement) ~/
+                          var2);
+                }
+              }
+            }
+          }
+          break;
+        case 3830102528:
+          {
+            fld1_1 ??= true;
+            throw (-((-17).ceilToDouble()));
+          }
+          break;
+      }
+    }
+    return var0;
+  }
+
+  void run() {
+    super.run();
+    {
+      int loc0 = 61;
+      while (--loc0 > 0) {
+        {
+          int loc1 = 77;
+          while (--loc1 > 0) {
+            {
+              int loc2 = 0;
+              do {
+                break;
+              } while (++loc2 < 84);
+            }
+          }
+        }
+        if (((var1 || fld1_1) && (!((!((!((!((!(true)))))))))))) {
+          switch (Int32x4.yyzx) {
+            case 900727295:
+              {
+                /// Single-line documentation comment.
+                fld1_1 ??= (!(true));
+                for (int loc1 in ((var5 ??
+                        Uri.parseIPv6Address(
+                            foo1_3(), var5[(loc0 + var5[4096])], -34)) ??
+                    var5)) {
+                  var7[(38 << (false ? (~(-58)) : Float32x4.yyxy))] =
+                      Uri.decodeFull(foo1_3());
+                  var5 ??= var5;
+                }
+              }
+              break;
+            case 900727304:
+              {
+                fld1_1 =
+                    (SecurityContext.alpnSupported ? (var3).isFinite : var1);
+                fld1_0 += 0.3154406798513474;
+              }
+              break;
+          }
+          var2 ^= var2;
+        } else {
+          if (((-(var3)) <= (-(fld1_0)))) {
+            var6 = foo1_2('0vsDWF9');
+          } else {
+            var6 ??= ((fld1_0 <= 0.16230005903410238)
+                ? ((!((0.5144029832155854 > (0.8199455895430549 / var3))))
+                    ? foo1_2('ken')
+                    : var6)
+                : (fld1_1 ? {56, 6442450945, 2} : {34}));
+          }
+          var5[Float32x4.zwzw] += (true ? var2 : (~(Float32x4.wyyx)));
+        }
+      }
+    }
+  }
+}
+
+class X2 extends X0 with X1 {
+  Set<int> fld2_0 = {for (int loc0 = 0; loc0 < 60; loc0++) -56, 29};
+
+  bool foo2_0(int par1) => var1;
+  bool foo2_1(bool par1) {
+    for (int loc0 in var6) {
+      var2 ~/= ((((((fld2_0 ?? (true ? var6 : var6)) ?? fld2_0))
+                      .union({(~(-21)), 10}) !=
+                  {(var5[90] ~/ (-(-90)))})
+              ? par1
+              : (var7[(~(82))]).isNotEmpty)
+          ? ((~(loc0)) *
+              ((true ? (-4294966272 ?? -21) : var2) +
+                  Duration.millisecondsPerMinute))
+          : (-9223372032559807488 ~/ 4294968296));
+    }
+    if (('DeAm#f' ==
+        ((Uri.encodeQueryComponent((0.3687340601979223).toString()) ??
+                var7[-23]) ??
+            foo1_3()))) {
+      throw (([Float32x4.wyyz, -9223372036854743039])
+              .sublist((--var2), (--var2)) +
+          ((true ? var1 : (!(false)))
+              ? foo2(
+                  foo1_2('JLXt'),
+                  [
+                    var5[Int32x4.zxzx],
+                    Int32x4.xxwy,
+                    (var2++),
+                    Float32x4.yzxx,
+                    (var2++),
+                    -15
+                  ],
+                  foo1_0(var7, var7, 0.7904389283184639))
+              : (var1
+                  ? [Float32x4.yzyz, Int32x4.wxxy, var2, (~(var5[-47]))]
+                  : var5)));
+    } else {
+      var7[var2] ??= ((({
+            ...{
+              for (int loc0 = 0; loc0 < 19; loc0++)
+                36: (var7[var2] ?? (par1 ? ('ccb9z' + 'iM') : var0)),
+              3: ('1sG' + var0),
+              for (int loc0 in {
+                (-(var5[var2])),
+                if (var1) Int32x4.zxxx,
+                -4294967168,
+                -61,
+                (~((par1 ? (~(-70)) : (var2--)))),
+                (-(7)),
+                -96,
+                Uint32List.bytesPerElement
+              })
+                85: var4
+            },
+            if (foo2_0(-91)) 38: (var3).toString() else 30: 'uI\u2665\u{1f600}',
+            72: '@'
+          }[(par1 ? 14 : var2)])
+                  .trim())
+              .substring((36 ~/ var5[(++var2)]), var5[((-(25)) * -53)]) ??
+          foo1_3());
+      /*
+       * Multi-line
+       * comment.
+       */
+      {
+        int loc0 = 0;
+        do {
+          {
+            String loc1 = 'jG7t';
+            /**
+             ** Multi-line
+             ** documentation comment.
+             */
+            {
+              int loc2 = 57;
+              while (--loc2 > 0) {
+                print((var6 ??
+                    (foo1_2(var0)).union(foo1_2(('n' + var7[(++var2)])))));
+              }
+            }
+          }
+        } while (++loc0 < 69);
+      }
+    }
+    return (!(((!((par1 && false)))
+        ? (true && foo2_0(-9223372036854771712))
+        : (!(par1)))));
+  }
+
+  double foo2_2(Map<int, String> par1, int par2) {
+    switch (var2) {
+      case 3816231196:
+        {
+          throw (-(Int32x4.xxwx));
+        }
+        break;
+      case 3816231204:
+        {
+          var7.forEach((loc0, loc1) {
+            switch ((-43 ^ (-(Float32x4.wwxx)))) {
+              case 2839002105:
+                {
+                  var0 ??= (SetBase.setToString(((var1 ? var1 : (true || var1))
+                          ? fld2_0
+                          : {
+                              Int32x4.yyzw,
+                              Int32x4.yyxy,
+                              (2 >> Int32x4.ywzx),
+                              (var1
+                                  ? ((foo2_1(var1) ? 17 : loc0) ~/
+                                      (-(var5[var2])))
+                                  : par2),
+                              Float32x4.zwwx,
+                              par2,
+                              Int32x4.wzzz,
+                              Int32x4.zyzw
+                            })) ??
+                      (loc1 +
+                          var7[((true
+                                  ? (var1 &&
+                                      bool.fromEnvironment(var7[(var2--)]))
+                                  : foo2_1(false))
+                              ? 35
+                              : (-(66)))]));
+                  for (int loc2 = 0; loc2 < 23; loc2++) {
+                    switch ((-73 ^ (Int32x4.xyzz >> Float32x4.yzzz))) {
+                      case 1710454916:
+                        {
+                          var3 = 0.3372913861348876;
+                          print(((-(var3)) * var3));
+                        }
+                        break;
+                      case 1710454922:
+                        {
+                          var4 ??= ((false
+                                  ? (var1
+                                      ? var1
+                                      : (fld2_0 ==
+                                          {
+                                            (false ? -27 : (-(92))),
+                                            loc2,
+                                            var5[loc2],
+                                            (var1
+                                                ? Float32x4.yywy
+                                                : (false ? -74 : 2)),
+                                            ((-(-50)) ^ 32),
+                                            (var2++)
+                                          }))
+                                  : var1)
+                              ? base64UrlEncode([
+                                  for (int loc3 in {
+                                    (-(par2)),
+                                    loc0,
+                                    (-((par2++))),
+                                    Float32x4.yyyx
+                                  })
+                                    (par2--),
+                                  (-((-(var5[var5[var5[-41]]])))),
+                                  if (({
+                                        loc2,
+                                        Duration.microsecondsPerSecond,
+                                        (([
+                                                  (par2++),
+                                                  (-90 ^ -5),
+                                                  var5[(~(0))],
+                                                  loc2
+                                                ] !=
+                                                var5)
+                                            ? -9223372032559808512
+                                            : (par2++))
+                                      } ==
+                                      {
+                                        (var1 ? (-((loc2 % loc2))) : loc2),
+                                        -94,
+                                        -62
+                                      }))
+                                    (++var2),
+                                  loc2,
+                                  for (int loc3 in {
+                                    55,
+                                    (~(var5[var5[(++par2)]])),
+                                    ((var1
+                                            ? (-((++var2)))
+                                            : var5[(true ? var5[68] : 10)]) -
+                                        par2),
+                                    (-(Float32x4.wzxx))
+                                  })
+                                    (Int32x4.yxzy | var5[-1]),
+                                  (foo2_1(false) ? (-(32)) : loc0),
+                                  (--par2),
+                                  if ((!(false))) (var1 ? var5[loc0] : 30)
+                                ])
+                              : ('b1TKp3' ??
+                                  (var4 +
+                                      var7[(~(var5[
+                                          ((var1 ? var2 : loc2) - 72)]))])));
+                        }
+                        break;
+                    }
+                    fld2_0 = ((!((false
+                            ? false
+                            : (false ? (!((var7[-28] != ''))) : var1))))
+                        ? (((var1
+                                    ? (true ? Set.identity() : var6)
+                                    : {
+                                        -63,
+                                        Int32x4.xxyx,
+                                        var5[((var1
+                                                ? (var5[-9223372032559808496] >>
+                                                    59)
+                                                : Int32x4.wxxy) ~/
+                                            var5[var5[-48]])],
+                                        (par2 ?? par2),
+                                        44,
+                                        var5[(var1 ? -26 : (-(par2)))]
+                                      }) ??
+                                ({
+                                      loc2,
+                                      var2,
+                                      ZLibOption.defaultMemLevel,
+                                      (true ? Int32x4.wyzz : 40),
+                                      (false ? loc2 : var5[42]),
+                                      -16
+                                    } ??
+                                    var6)))
+                            .union({loc0, (var2++), (-1 * (~(var2)))})
+                        : (bool.fromEnvironment((var3)
+                                .toStringAsFixed(Uint64List.bytesPerElement))
+                            ? fld2_0
+                            : {
+                                (par2++),
+                                (var1 ? loc2 : (++var2)),
+                                ((false || false) ? Int32x4.xyyz : (++par2)),
+                                var5[-98],
+                                Float32x4.zwwy,
+                                var5[var5[62]],
+                                (~(Float32x4.ywww))
+                              }));
+                  }
+                }
+                break;
+              case 2839002106:
+                {
+                  for (int loc2 = 0; loc2 < 13; loc2++) {
+                    {
+                      int loc3 = 0;
+                      do {
+                        switch ((loc3 | -76)) {
+                          case 2164097105:
+                            {
+                              var4 ??= (var1).toString();
+                              var5 = ((!(((true || var1) !=
+                                      (false ? var1 : (!(foo2_1(var1)))))))
+                                  ? foo2(
+                                      ((var6).union(foo1_2(loc1))).toSet(),
+                                      [
+                                        -67,
+                                        if (((var1
+                                                ? 59
+                                                : (-((false ? -97 : par2)))) !=
+                                            (false
+                                                ? ((var1 || var1)
+                                                    ? (-((par2++)))
+                                                    : 4)
+                                                : (--var2)))) ...[
+                                          ((92 ~/ Int32x4.yzwx) << 70),
+                                          Float32x4.xxyz,
+                                          Int8List.bytesPerElement
+                                        ] else
+                                          69
+                                      ],
+                                      var7)
+                                  : foo2(foo0(), Uri.parseIPv4Address(var0),
+                                      var7));
+                            }
+                            break;
+                          case 2164097111:
+                            {
+                              var4 ??= var7[Float32x4.zxzw];
+                            }
+                            break;
+                        }
+                      } while (++loc3 < 96);
+                    }
+                    fld2_0 = var6;
+                  }
+                }
+                break;
+            }
+          });
+          for (int loc0 in (foo2_1((var5 !=
+                  (false
+                      ? [par2]
+                      : foo2(
+                          var6,
+                          [20],
+                          ({
+                                21: var0,
+                                68: foo1_3(),
+                                24: ('1MF' + '8s\u2665yx+ ')
+                              } ??
+                              {
+                                9: var7[var2],
+                                48: 'mB(wW\u{1f600}',
+                                74: 'ojEw\u{1f600}\u{1f600}',
+                                80: '\u26655E-hj\u{1f600}',
+                                10: (false ? 'W7i5\u2665YX' : '! Ed9&'),
+                                88: (false ? var0 : 'N0D9(H\u{1f600}'),
+                                5: 'QZ'
+                              })))))
+              ? foo1_2('XP')
+              : {
+                  if ((foo2_1(var1)
+                      ? (foo2_1((fld2_0).add(-9223372036854774784)) || var1)
+                      : var1))
+                    (~(Float32x4.zyww)),
+                  Float32x4.xwyw,
+                  ((((var1 ? true : var1) ? 0.3447071353935154 : var3) >=
+                          0.5995056331958718)
+                      ? ZLibOption.MAX_LEVEL
+                      : 16),
+                  9223372032559841279,
+                  Int32x4.zwyy
+                })) {
+            for (int loc1 = 0; loc1 < 19; loc1++) {
+              var1 = (!(bool.fromEnvironment(MapBase.mapToString({
+                1: '4',
+                56: var0,
+                85: var0,
+                51: var7[-4],
+                42: ((!((!(false)))) ? par1[72] : MapBase.mapToString(var7))
+              }))));
+            }
+          }
+        }
+        break;
+    }
+    print((((var1 ? 'kP' : (var1 ? 'irjF' : var7[var5[90]])) ??
+            ((!(false)) ? 'vWa\u{1f600}' : var0)) +
+        'xzpK'));
+    return var3;
+  }
+
+  void run() {
+    super.run();
+    {
+      int loc0 = (~(-24));
+      var0 ??= ((false
+              ? foo2_1((true
+                  ? (var1 && (var2).isOdd)
+                  : (('dTYR' ?? 'G\u{1f600}P14\u{1f600}a')).isEmpty))
+              : ((var1 && true) || (!(var1))))
+          ? (var4 ?? 'I')
+          : 'QO');
+    }
+  }
+}
+
+class X3 extends X1 {
+  Map<int, String> fld3_0 = {
+    if (true) if (false) 45: 'ynEn\u2665nG' else 70: 'c\u{1f600}mN4\u2665a',
+    if (true) 30: '6\u2665P!Pbi',
+    81: 't',
+    82: '17fx#!',
+    92: 'H',
+    if (true) 69: ')Ls'
+  };
+  Set<int> fld3_1 = {27};
+  int fld3_2 = 34;
+
+  String foo1_1(int par1) {
+    throw (ListBase.listToString(foo2({
+          -4294967169,
+          par1
+        }, [
+          -97,
+          (var5[(var1 ? var5[87] : Int32x4.yxxy)] * Int32x4.yyxx),
+          var2,
+          (false ? 10 : var5[var5[(par1++)]])
+        ], var7)) ??
+        'o');
+  }
+
+  bool foo3_0(double par1) {
+    {
+      Set<int> loc0 = (true ? fld3_1 : var6);
+      {
+        Set<int> loc1 = (false
+            ? foo0()
+            : {
+                for (int loc2 in [var2, (-(Float32x4.xzzw))])
+                  if (false) Float32x4.wxyz else (++fld3_2),
+                ((var1
+                        ? 5
+                        : var5[(((var5[(true ? fld3_2 : fld3_2)] ~/ 48) | 56) %
+                            var5[-4])]) ??
+                    (var2++))
+              });
+        for (int loc2 = 0; loc2 < 90; loc2++) {
+          {
+            int loc3 = 95;
+            while (--loc3 > 0) {
+              return (((0.7073184699576396).isNaN
+                      ? var7
+                      : (Map.of(Map.from(var7)) ??
+                          Map.unmodifiable(Map.identity()))))
+                  .isEmpty;
+            }
+          }
+          try {
+            var1 = (((12 >= Int32x4.ywxx) ? true : true)
+                ? false
+                : (((var1 ? fld3_0[Int32x4.wyxy] : '') ?? var7[Float32x4.xwwx]))
+                    .isEmpty);
+            var2 |= ((fld3_2++) ?? (fld3_2--));
+          } catch (exception, stackTrace) {
+            var5 ??= var5;
+          } finally {
+            var4 = 'A';
+            break;
+          }
+        }
+        {
+          double loc2 = (-(exp((acos(0.06129144867031855) ?? var3))));
+          fld3_0 = (((({Int32x4.ywxw, 6442450943}).union(foo0()))
+                      .add((++fld3_2))
+                  ? false
+                  : false)
+              ? foo1_0(
+                  (foo1([var5[var2], var5[75], 42], false) ?? var7), var7, loc2)
+              : (var1
+                  ? {
+                      for (int loc3 = 0; loc3 < 48; loc3++) 78: 'dWek8',
+                      40: fld3_0[(var5[-81] & Int32x4.xzyw)],
+                      73: (' )G\u2665-d(').substring(
+                          (NetworkInterface.listSupported
+                              ? (~(((++var2) ?? (fld3_2 * fld3_2))))
+                              : var5[-75]),
+                          fld3_2),
+                      74: ('k9O\u2665').trimLeft(),
+                      88: var7[(++var2)],
+                      for (int loc3 = 0; loc3 < 27; loc3++)
+                        60: ((false || var1) ? var7[46] : var0),
+                      99: ((var3).isNaN
+                          ? (Uri.decodeComponent(foo1_3()) + var4)
+                          : var7[-77]),
+                      92: (true
+                          ? ('').padLeft(82, '')
+                          : ('' ?? var7[(false ? 94 : 58)]))
+                    }
+                  : var7));
+
+          /// Single-line documentation comment.
+          fld3_1 ??= ((loc1 ?? foo1_2(fld3_0[(var2--)])) ?? foo1_2(foo1_3()));
+        }
+      }
+    }
+    return (var1 ? (!(var1)) : var1);
+  }
+
+  String foo3_1(int par1, String par2, String par3) {
+    switch (var2) {
+      case 3768780679:
+        {
+          {
+            int loc0 = (++par1);
+            var0 ??= ListBase.listToString(var5);
+            if (true) {
+              var5 = [
+                Float32x4.xyxz,
+                (var1
+                    ? ((!(false)) ? Float32x4.xyyw : (++fld3_2))
+                    : var5[fld3_2]),
+                par1,
+                (~(Float32x4.zxwy)),
+                if ((foo3_0(var3)
+                    ? ([
+                          (++fld3_2),
+                          ...[
+                            ...[
+                              var5[(true ? Float32x4.xxzx : (--fld3_2))],
+                              54,
+                              (-((((foo3_0(var3)
+                                          ? (!(false))
+                                          : ((var1 ? (~(-63)) : var5[-40]))
+                                              .isOdd)
+                                      ? ((0.8329420640871532 != var3) && var1)
+                                      : var1)
+                                  ? 43
+                                  : (Float32x4.zxxy - Float32x4.zxxw)))),
+                              Int32x4.zzwx
+                            ],
+                            ...[
+                              (var5[-48] * (fld3_2++)),
+                              Int32x4.wyyw,
+                              (~(-76)),
+                              ((par1).isEven ? (--par1) : -13),
+                              Float32x4.wxyx
+                            ],
+                            for (int loc1 in [
+                              (++fld3_2),
+                              -15,
+                              (SecurityContext.alpnSupported
+                                  ? Int32x4.yxyw
+                                  : Float32x4.yxxw),
+                              if (true) var5[(var1 ? -32768 : par1)],
+                              ((--var2) ^ (++fld3_2))
+                            ])
+                              (fld3_2--),
+                            93,
+                            (~((-(ZLibOption.minMemLevel)))),
+                            ((Float32x4.zyzx >> -14) & Float32x4.yxxw)
+                          ],
+                          (var1
+                              ? (++par1)
+                              : ((var3).isInfinite ? Float32x4.zwww : -84)),
+                          var2
+                        ] ==
+                        [
+                          9223372032559808639,
+                          -85,
+                          Float32x4.wzyy,
+                          loc0,
+                          [
+                            ((-(36)) <<
+                                ((var1
+                                        ? var1
+                                        : ({
+                                            45: 'ay',
+                                            7: par3,
+                                            69: Uri.decodeFull(
+                                                (foo1_3() + 'LX+'))
+                                          })
+                                            .isEmpty)
+                                    ? (~((13 | 64)))
+                                    : (-(var2)))),
+                            (par1--),
+                            ((~((true ? (var2--) : -31))) >> 9),
+                            (-((35 % (~(var5[var5[39]]))))),
+                            4395630341,
+                            Int32x4.zxxy,
+                            if ((var1
+                                ? foo3_0(var3)
+                                : (0.6201792653929837).isInfinite)) ...[
+                              Int32x4.wxxx,
+                              (fld3_2 * (--fld3_2)),
+                              var5[((~(var5[var5[var5[(-(-23))]]])) +
+                                  (~(-4294966296)))],
+                              loc0,
+                              for (int loc1 in [var5[Float32x4.yzww]]) 17,
+                              (~(var5[(++par1)])),
+                              -58,
+                              ((!(('').isEmpty))
+                                  ? ((-(Float32x4.ywwx)) * (++par1))
+                                  : Int32x4.yxyz)
+                            ]
+                          ][((var1 ? var1 : var1) ? var5[0] : par1)],
+                          ((~(70)) +
+                              (par1 + (-77 | ZLibOption.MAX_WINDOW_BITS))),
+                          (-(Int32x4.zywy)),
+                          (~(Float32x4.zywz))
+                        ])
+                    : (var1 ? true : true)))
+                  fld3_2
+              ];
+            }
+          }
+          var3 *= ((var3 + 0.6761038672016147) ?? (-(double.minPositive)));
+        }
+        break;
+      case 3768780685:
+        {
+          {
+            int loc0 = 67;
+            while (--loc0 > 0) {
+              {
+                Map<int, String> loc1 = foo1(
+                    Uri.parseIPv4Address(('E Hu\u{1f600}' + '\u2665l&#!')),
+                    (!(false)));
+                var3 ??= var3;
+              }
+              var5 = (var5 +
+                  ((({
+                    79: (foo1_3() ?? 'eD'),
+                    73: (var1 ? par2 : ' xdXgW'),
+                    4: 'pUc(q',
+                    15: 'K\u{1f600}hmdZ\u2665',
+                    95: (var1 ? var4 : (var1 ? fld3_0[-45] : foo1_3()))
+                  })
+                              .isNotEmpty
+                          ? ((var1 ? var1 : (var1 ? var1 : foo3_0(var3))) ||
+                              foo3_0(var3))
+                          : (!(((false || true) ? var1 : false))))
+                      ? [
+                          (~((-61 ??
+                              (~((-(var5[(var1 ? fld3_2 : var5[34])]))))))),
+                          (var5[13] ^ (var1 ? 35 : -76)),
+                          (-(((~(-47)) ~/ (--par1))))
+                        ]
+                      : foo2({
+                          -36,
+                          ((0.3910802543332075).isNegative
+                              ? (~((var2++)))
+                              : (var2 &
+                                  (var1
+                                      ? [
+                                          -67,
+                                          (fld3_2++),
+                                          if ((!((!((var1
+                                              ? true
+                                              : (!(false))))))))
+                                            (false
+                                                ? (~(Float32x4.wyyy))
+                                                : (var1
+                                                    ? (1 ^ (-(16)))
+                                                    : var5[94])),
+                                          fld3_2,
+                                          var2,
+                                          67
+                                        ][-12]
+                                      : Float32x4.wwxw))),
+                          26,
+                          [
+                            (var1
+                                ? (--fld3_2)
+                                : (((!(var1))
+                                        ? (~((foo3_0(0.9959805940480148)
+                                            ? (33 ~/ loc0)
+                                            : Float32x4.xywx)))
+                                        : (15 % var5[var5[-47]])) <<
+                                    -86)),
+                            (-((~(RawSocketOption.levelIPv6))))
+                          ][var5[var5[(ZLibOption.maxMemLevel ^ -3)]]],
+                          -29
+                        }, [
+                          (var1 ? Float32x4.wxxw : (--par1)),
+                          ...[
+                            52,
+                            (-((true ? -12 : 44))),
+                            var5[((var5[34] * 30) >> 4294967360)],
+                            ((--var2) <<
+                                (true
+                                    ? var5[(-4 ~/ Int32x4.yyww)]
+                                    : (bool.fromEnvironment(var7[fld3_2])
+                                        ? (~((false ? loc0 : var5[(++par1)])))
+                                        : ((!(false))
+                                            ? (var5[var5[loc0]] ^ Int32x4.wxzz)
+                                            : par1)))),
+                            (((false ? var0 : '') !=
+                                    (true
+                                        ? MapBase.mapToString(({
+                                              7: 'WTT7\u{1f600}e3',
+                                              22: '',
+                                              36: (var1
+                                                  ? 'F'
+                                                  : (var1 ? fld3_0[var2] : '')),
+                                              37: 'l@a',
+                                              85: (var1 ? '' : par3),
+                                              82: 'eb',
+                                              37: '11',
+                                              41: var7[94]
+                                            } ??
+                                            var7))
+                                        : (var1 ? var4 : par2)))
+                                ? (~(var5[-71]))
+                                : 9),
+                            32,
+                            if (bool.fromEnvironment(
+                                fld3_0[var5[ZLibOption.MIN_MEM_LEVEL]]))
+                              var5[(--par1)],
+                            (par1--)
+                          ],
+                          for (int loc1 in {
+                            for (int loc2 in [
+                              ((!((Map.unmodifiable({
+                                        86: var4,
+                                        31: var0,
+                                        85: (par3 + ''),
+                                        91: (var1
+                                            ? fld3_0[4]
+                                            : '!M\u{1f600}!vOw'),
+                                        45: '7T',
+                                        19: 'fha+',
+                                        38: (false ? '' : fld3_0[70])
+                                      }) !=
+                                      {
+                                        92: '@4',
+                                        41: var7[loc0],
+                                        24: (foo3_0(0.06591134699771606)
+                                            ? '\u2665)\u2665NnO+'
+                                            : 'JM3Hn\u{1f600}'),
+                                        26: 'aQ51Yz',
+                                        64: var7[
+                                            (-((var5[18] & (36).bitLength)))]
+                                      })))
+                                  ? (89 ^
+                                      (((44 - par1) * -9223372034707292160) &
+                                          var5[128]))
+                                  : -46),
+                              (fld3_2++),
+                              ((([
+                                            -89,
+                                            var2,
+                                            (fld3_2++),
+                                            var5[-4294967264],
+                                            -25,
+                                            var2,
+                                            var5[((!(var1))
+                                                ? (var1 ? -3 : -81)
+                                                : var5[loc0])],
+                                            (var1
+                                                ? par1
+                                                : ((~((fld3_2++))) >>
+                                                    (-((-(-64))))))
+                                          ] ??
+                                          foo2(var6, [
+                                            4295032831
+                                          ], {
+                                            53: foo1_3(),
+                                            94: var7[13],
+                                            82: var7[-60],
+                                            30: fld3_0[-9223372032559742976],
+                                            98: foo1_3()
+                                          })) !=
+                                      var5)
+                                  ? (--par1)
+                                  : loc0),
+                              56,
+                              if (((var5[21]).isOdd ? true : false))
+                                ((++par1) -
+                                    (var1 ? var5[DateTime.january] : (par1--)))
+                              else
+                                fld3_2,
+                              if ((!(var1))) 74,
+                              (par1 ^ var5[26])
+                            ])
+                              (~(var2)),
+                            for (int loc2 in {
+                              6442450944,
+                              Float32x4.ywyw,
+                              -9223372032559804416,
+                              (~(var5[var5[26]])),
+                              Float32x4.xyxy,
+                              (--fld3_2),
+                              var5[98]
+                            })
+                              if (false) -26,
+                            (~((-((-((-48 - -9223372036854775680))))))),
+                            ...{
+                              (-((var2--))),
+                              if (true) -100663046 else var5[(~(par1))]
+                            },
+                            (~((~((fld3_2++))))),
+                            ...{
+                              ((List.filled(0, 26) ==
+                                      [
+                                        (-(-52)),
+                                        -29,
+                                        (--fld3_2),
+                                        (0.22302566014161784).floor(),
+                                        (par1 % -56)
+                                      ])
+                                  ? (var1
+                                      ? (var2++)
+                                      : ((!((!(true))))
+                                          ? ((var1 || foo3_0(var3)) ? 76 : par1)
+                                          : (-(-13))))
+                                  : ((foo1_0((var1 ? fld3_0 : var7), var7,
+                                              var3))
+                                          .isEmpty
+                                      ? 97
+                                      : (var1 ? var2 : -9223372036854774784))),
+                              (-(Float32x4.zyzw)),
+                              (--var2)
+                            }
+                          })
+                            ((var3 < (-(var3))) ? -9223372032559808000 : -71),
+                          -100663046,
+                          if ((var1
+                              ? bool.fromEnvironment('vV0')
+                              : (Map.from({
+                                  78: '',
+                                  49: '\u{1f600}\u{1f600}4Mz',
+                                  70: fld3_0[par1],
+                                  95: '\u{1f600}2tIYqE',
+                                  43: (true ? 'baf-\u2665' : var4),
+                                  30: var7[(-((-68 % ZLibOption.defaultLevel)))]
+                                }))
+                                  .isNotEmpty))
+                            -13
+                          else
+                            (var1 ? (-((-(var5[56])))) : (var2--)),
+                          (~((~((-((var2++)))))))
+                        ], {
+                          88: ('bV\u{1f600}iqO').toLowerCase(),
+                          42: '(hZ4S',
+                          37: var7[-79],
+                          36: var0
+                        })));
+            }
+          }
+          {
+            int loc0 = 0;
+            do {
+              try {
+                print(foo2(
+                    fld3_1,
+                    (fld3_0[var5[-12]]).codeUnits,
+                    (({
+                              36: var4,
+                              30: '0\u{1f600}EYWqr',
+                              66: 'S',
+                              3: '+J3Gj',
+                              71: '\u{1f600}-q',
+                              13: 'V3QN',
+                              34: ''
+                            } ??
+                            {
+                              54: fld3_0[(var2--)],
+                              74: (foo3_0(
+                                      ((-(var3)) * (0.8613045491468889 + var3)))
+                                  ? var7[78]
+                                  : (((var1 ? (47).isEven : var1) ? true : true)
+                                      ? (var4 ?? 'UzK')
+                                      : 'fH1smd')),
+                              12: '\u2665',
+                              18: 'V'
+                            }) ??
+                        var7)));
+              } catch (exception, stackTrace) {
+                fld3_1 = foo0();
+                for (int loc1 = 0; loc1 < 29; loc1++) {
+                  if (var1) {
+                    {
+                      int loc2 = 0;
+                      do {
+                        var5 = (foo3_0(var3)
+                            ? [
+                                ((--par1) ^ (~(93))),
+                                if ((var3).isFinite)
+                                  for (int loc3 in [
+                                    -5,
+                                    Int32x4.zxyy,
+                                    (true
+                                        ? var5[var5[(var1 ? -23 : var5[68])]]
+                                        : -99),
+                                    ((!(var1))
+                                        ? ((false
+                                                ? var1
+                                                : foo3_0(0.3133865362301862))
+                                            ? Float64List.bytesPerElement
+                                            : [
+                                                Float32x4.yxzx,
+                                                if (var1)
+                                                  (false ? 40 : 85)
+                                                else
+                                                  ((String.fromCharCode((foo3_0(
+                                                                  0.414460580942719)
+                                                              ? var5[-14]
+                                                              : var2)) ==
+                                                          'mII\u{1f600}zkM')
+                                                      ? var5[(~(-51))]
+                                                      : ((var1
+                                                              ? (!(var1))
+                                                              : var1)
+                                                          ? var5[0]
+                                                          : (-(var2))))
+                                              ][5])
+                                        : fld3_2),
+                                    (par1++),
+                                    -72,
+                                    Int32x4.zzxy
+                                  ])
+                                    Int32x4.zyww
+                                else
+                                  Int32x4.wxyz
+                              ]
+                            : [
+                                ...[
+                                  if ((false ? false : var1)) (-(52)),
+                                  (++par1),
+                                  (par1--),
+                                  (-((-([
+                                    (((var0 + fld3_0[(++var2)])).isNotEmpty
+                                        ? Float32x4.yzxw
+                                        : var5[35])
+                                  ][loc0])))),
+                                  (~(-17))
+                                ],
+                                38,
+                                ...[
+                                  (var1 ? (par1++) : -10),
+                                  if (true) -62 else var2,
+                                  if ((!((var3).isFinite)))
+                                    Int32x4.xxzz
+                                  else
+                                    -45
+                                ],
+                                if ((true || false)) (-(-93)),
+                                (--fld3_2),
+                                ([
+                                      (fld3_2--),
+                                      if ((base64UrlEncode(var5) == 'RY'))
+                                        (++fld3_2)
+                                      else
+                                        -9223372032559808383,
+                                      Float32x4.zyxy,
+                                      loc0,
+                                      -55,
+                                      if (('O \u{1f600}e\u2665').isNotEmpty)
+                                        if (var1)
+                                          (--var2)
+                                        else
+                                          for (int loc3 in {
+                                            loc0,
+                                            (~((--var2))),
+                                            (-(-35)),
+                                            Float32x4.xxyw,
+                                            65,
+                                            -4,
+                                            -4194304251,
+                                            -54
+                                          })
+                                            (((0.671280258888436 ==
+                                                        (0.16535430333243706 *
+                                                            0.18316039550464436)) ||
+                                                    var1)
+                                                ? var5[12]
+                                                : (~((--var2))))
+                                      else if (false)
+                                        if (var1) (-(Int32x4.zzwx)) else loc2
+                                      else
+                                        Int32x4.yzyw
+                                    ][loc1] *
+                                    (--par1)),
+                                (-71 * 38)
+                              ]);
+                      } while (++loc2 < 89);
+                    }
+                  } else {
+                    {
+                      int loc2 = 0;
+                      do {
+                        fld3_0 ??= ((((Map.unmodifiable(var7)).isEmpty ||
+                                    (!(({
+                                      11: 'v+MHeiB',
+                                      48: var7[(true
+                                          ? ((var2--) ?? fld3_2)
+                                          : var5[(fld3_2--)])],
+                                      52: '(('
+                                    })
+                                        .isEmpty)))
+                                ? fld3_0
+                                : {
+                                    39: foo1_3(),
+                                    21: 'IXzJ+',
+                                    76: 'K2C#',
+                                    16: ('\u{1f600}Gh' + '#i'),
+                                    62: foo1_3(),
+                                    19: foo1_3(),
+                                    32: par3,
+                                    for (int loc3 in [
+                                      (par1--),
+                                      -66,
+                                      -96,
+                                      -35,
+                                      Float32x4.zzyz
+                                    ])
+                                      72: 'y vxi'
+                                  }) ??
+                            {13: par2});
+                        switch (4096) {
+                          case 3159134388:
+                            {
+                              /// Single-line documentation comment.
+                              {
+                                int loc3 = 0;
+                                do {
+                                  fld3_0 ??= foo1(
+                                      var5,
+                                      ((((true ? par2 : var7[var5[loc1]]))
+                                                  .isNotEmpty
+                                              ? 9
+                                              : -55) !=
+                                          var5[-36]));
+                                  fld3_1 = foo0();
+                                } while (++loc3 < 79);
+                              }
+                            }
+                            break;
+                          case 3159134393:
+                            {
+                              throw Int32x4.zxxw;
+                            }
+                            break;
+                        }
+                      } while (++loc2 < 77);
+                    }
+                  }
+                }
+              }
+            } while (++loc0 < 98);
+          }
+        }
+        break;
+    }
+    /*
+     * Multi-line
+     * comment.
+     */
+    return ((0.7728524536008519).isNaN ? 'BjzeSsJ' : foo1_3());
+  }
+
+  void run() {
+    super.run();
+    var5 ??= var5;
+    print({4294968296});
+  }
+}
+
+main() {
+  int count = 0;
+  try {
+    foo0();
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    foo1(('  MQz').codeUnits, var1);
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    foo2(
+        (var6).toSet(),
+        (var1
+            ? [-9223372036854775681, -66, 9223372032559874047, -3, 74]
+            : var5),
+        Map.identity());
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X0().foo0_0(var7);
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X1().foo1_0(
+        (false
+            ? {
+                7: 'QMNg',
+                12: 'wzc5-Iq',
+                63: '29an-z',
+                86: 'sF5',
+                59: '\u2665L',
+                43: 'k',
+                62: 'NvF\u{1f600}k',
+                84: 'ZW 1-o'
+              }
+            : var7),
+        {
+          28: '@smXqKl',
+          66: 'oL',
+          if (false) 74: 'B' else 81: 'X',
+          if (false) 18: 'j' else 25: 'N',
+          44: '\u{1f600}lrx8m',
+          20: 'hC',
+          73: 'q',
+          63: '\u{1f600}nE'
+        },
+        0.18875619647922648);
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X1().foo1_1((-((++var2))));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X1().foo1_2((var1
+        ? (false
+            ? (true ? var7[((!(var1)) ? var5[Int32x4.xxyx] : 3)] : var4)
+            : Uri.encodeComponent(('yd' ?? (var0).padLeft(1, 'Q'))))
+        : var7[-2147483649]));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X1().foo1_3();
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X2().foo2_0(Int32x4.xyyw);
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X2().foo2_1((!(((!(var1)) && (!((var1 ? false : var1)))))));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X2().foo2_2(var7, ((-(var5[(--var2)])) << 98));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X3().foo3_0(0.37767598562234317);
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X3().foo3_1(
+        -6, var0, (Uri.decodeComponent('yQg') + ((var4 ?? var4) + var0)));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X3().foo1_0(
+        Map.unmodifiable({77: 'hG'}),
+        ((false
+                ? {
+                    88: 'Sv-EbnG',
+                    73: 'G',
+                    46: 'O#',
+                    16: 'm1nf(',
+                    91: 'F',
+                    11: 'Q+O@K',
+                    70: '3q\u2665BJ'
+                  }
+                : Map.identity()) ??
+            {
+              68: 'r',
+              56: 'IH&',
+              31: '9cqu',
+              49: '8ug',
+              84: 'mR2VyC',
+              41: 'gk&(asy'
+            }),
+        (var3 * sin(var3)));
+  } catch (e, st) {
+    count++;
+  }
+  try {
+    X3().run();
+  } catch (e, st) {
+    count++;
+  } finally {}
+  Expect.equals(-47639, var2);
+  Expect.equals(9, count);
+}
diff --git a/tests/legacy_status_dart2js.csv b/tests/legacy_status_dart2js.csv
new file mode 100644
index 0000000..5736318
--- /dev/null
+++ b/tests/legacy_status_dart2js.csv
@@ -0,0 +1,411 @@
+Condition,Test,Expectations,Comment,Issue,Issue state
+,codegen/gvn_dynamic_field_get_test,Fail,Issue 18519,https://dartbug.com/18519,open
+,codegen/list_tracer_length_test,Fail,Issue 33051,https://dartbug.com/33051,open
+,codegen/logical_expression_test,Fail,Issue 17027,https://dartbug.com/17027,open
+,codegen/side_effect_tdiv_regression_test,Fail,Issue 33050,https://dartbug.com/33050,open
+,codegen/simple_function_subtype_test,Fail,simple_function_subtype_test is temporarily(?) disabled due to new method for building function type tests.,,
+,end_to_end/generate_code_with_compile_time_errors_test,RuntimeError,not supported yet with the new FE.,,
+,end_to_end/show_package_warnings_test,RuntimeError,missing errors from the FE,,
+,inference/simple_inferrer_const_closure2_test,Fail,Issue 16507,https://dartbug.com/16507,open
+,inference/simple_inferrer_const_closure_test,Fail,Issue 16507,https://dartbug.com/16507,open
+,inference/simple_inferrer_global_field_closure_test,Fail,Issue 16507,https://dartbug.com/16507,open
+,sourcemaps/d2js_validity_test,RuntimeError,Issue 33072,https://dartbug.com/33072,open
+,sourcemaps/deferred_d2js_validity_test,RuntimeError,Issue 33072,https://dartbug.com/33072,open
+$compiler == dart2js,bounds_check4a_test,RuntimeError,Issue 32741,https://dartbug.com/32741,open
+$compiler == dart2js,bounds_check4b_test,RuntimeError,Issue 32741,https://dartbug.com/32741,open
+$compiler == dart2js,generic_class_is_test,Fail,Issue 32004,https://dartbug.com/32004,open
+$compiler == dart2js,jsinterop_test/01,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/02,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/03,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/04,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/34,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,jsinterop_test/35,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,jsinterop_test/36,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,jsinterop_test/37,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,jsinterop_test/38,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/42,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/43,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,jsinterop_test/44,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,jsinterop_test/45,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,jsinterop_test/46,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/51,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,jsinterop_test/52,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,jsinterop_test/53,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,jsinterop_test/54,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,many_instantiations_test/01,Crash,Issue 33819,https://dartbug.com/33819,open
+$compiler == dart2js,no_such_method_test,Fail,Wrong Invocation.memberName.,,
+$compiler == dart2js,non_jsinterop_test/01,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/02,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/03,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/04,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/34,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,non_jsinterop_test/35,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,non_jsinterop_test/36,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,non_jsinterop_test/37,MissingCompileTimeError,Issue 33834,https://dartbug.com/33834,open
+$compiler == dart2js,non_jsinterop_test/38,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/42,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/43,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,non_jsinterop_test/44,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,non_jsinterop_test/45,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,non_jsinterop_test/46,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/51,MissingCompileTimeError,Issue 34174,https://dartbug.com/34174,open
+$compiler == dart2js,non_jsinterop_test/52,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,non_jsinterop_test/53,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$compiler == dart2js,non_jsinterop_test/54,MissingCompileTimeError,Issue 34345,https://dartbug.com/34345,open
+$runtime == jsshell,timer_test,Fail,Issue 7728.,https://dartbug.com/7728,closed
+$runtime == none,timer_negative_test,"Fail, OK",A negative runtime test.,,
+$compiler == dart2js && $runtime == d8,deferred_fail_and_retry_test,RuntimeError,Uses XHR in dart:html,,
+$compiler == dart2js && $runtime == d8,deferred_with_csp_nonce_test,RuntimeError,Uses dart:html,,
+$compiler == dart2js && $runtime == none,*,"Fail, Pass",TODO(ahe): Triage these tests.,,
+$compiler == dart2js && $csp,js_interop_optional_arg_test,RuntimeError,Issue 31082,https://dartbug.com/31082,open
+$compiler == dart2js && $csp,js_interop_test,RuntimeError,Issue 31082,https://dartbug.com/31082,open
+$compiler == dart2js && $minified,closure_capture2_test,Pass,Passes for the wrong reason,,
+$compiler == dart2js && $minified,deferred/reflect_multiple_annotations_test,Crash,NoSuchMethodError: The getter 'closureClassEntity' was called on null.,,
+$compiler == dart2js && $minified,deferred/reflect_multiple_default_arg_test,Crash,NoSuchMethodError: The getter 'closureClassEntity' was called on null.,,
+$compiler == dart2js && $minified,mirrors_used_warning_test/minif,"Fail, OK",Tests warning that minified code will be broken.,,
+$compiler == dart2js && $minified,runtime_type_test,"Fail, OK",Tests extected output of Type.toString().,,
+$compiler == dart2js && $minified,to_string_test,Fail,Issue 7179.,https://dartbug.com/7179,closed
+$compiler == dart2js && $minified,type_literal_test,"Fail, OK",Tests expected output of Type.toString().,,
+$compiler == dart2js && $minified,typevariable_typedef_test,"Fail, OK",Tests expected output of Type.toString().,,
+$compiler == dart2js && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == ff || $runtime == safari),isolate2_test/01,Fail,Issue 14458.,https://dartbug.com/14458,closed
+$compiler == none && $runtime == vm,invalid_annotation_test/01,"MissingCompileTimeError, OK",vm is lazy,,
+$compiler == dart2js,fake_thing_test,RuntimeError,Issue 13010,https://dartbug.com/13010,open
+$compiler == dart2js,field_type2_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,field_type_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,native_exceptions1_frog_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,native_mixin_with_plain_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,native_window1_frog_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,native_window2_frog_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js,subclassing_constructor_1_test,CompileTimeError,Issue 33762,https://dartbug.com/33762,open
+$compiler == dart2js && $minified,optimization_hints_test,"RuntimeError, OK",Test relies on unminified names.,,
+$compiler == dart2js,arithmetic_int64_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,async_star_cancel_while_paused_test,RuntimeError,Issue 22853,https://dartbug.com/22853,open
+$compiler == dart2js,bit_operations_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js,bit_operations_test/03,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,bit_operations_test/04,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,bit_operations_test/none,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,call_method_must_not_be_field_test/03,RuntimeError,Issue 32155,https://dartbug.com/32155,closed
+$compiler == dart2js,call_method_must_not_be_getter_test/03,RuntimeError,Issue 32155,https://dartbug.com/32155,closed
+$compiler == dart2js,canonical_const2_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js,closure_type_arguments_test,Crash,Issue 34272,https://dartbug.com/34272,open
+$compiler == dart2js,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.",,
+$compiler == dart2js,config_import_test,RuntimeError,Test flag is not passed to the compiler.,,
+$compiler == dart2js,const_constructor3_test/04,MissingCompileTimeError,OK - Subtype check uses JS number semantics.,,
+$compiler == dart2js,const_dynamic_type_literal_test/03,Pass,but it shouldn't until we fix issue 17207,https://dartbug.com/17207,open
+$compiler == dart2js,const_switch_test/02,"RuntimeError, OK",constant identity based on JS constants,,
+$compiler == dart2js,const_switch_test/04,"RuntimeError, OK",constant identity based on JS constants,,
+$compiler == dart2js,covariant_subtyping_test,Crash,Unsupported operation: Unsupported type parameter type node E.,,
+$compiler == dart2js,deferred_not_loaded_check_test,RuntimeError,Test out of date. Issue 31933,https://dartbug.com/31933,open
+$compiler == dart2js,deopt_inlined_function_lazy_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,deopt_smi_op_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,double_identical_test,RuntimeError,"Negative and positive zero are distinct, but not in dart2js; bug #11551.",https://dartbug.com/11551,open
+$compiler == dart2js,double_int_to_string_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js,expect_test,"RuntimeError, OK",Issue 13080,https://dartbug.com/13080,closed
+$compiler == dart2js,external_test/10,CompileTimeError,External non-js-interop function are treated as compile-time errors.,,
+$compiler == dart2js,external_test/13,CompileTimeError,External non-js-interop function are treated as compile-time errors.,,
+$compiler == dart2js,external_test/20,CompileTimeError,External non-js-interop function are treated as compile-time errors.,,
+$compiler == dart2js,full_stacktrace1_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,full_stacktrace2_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,full_stacktrace3_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,guess_cid_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,identical_closure2_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js,identical_closure2_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,infinity_test,RuntimeError,non JS number semantics - Issue 4984,https://dartbug.com/4984,closed
+$compiler == dart2js,int2_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/01,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/02,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/04,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/05,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/06,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/11,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/12,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/14,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/16,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/17,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/19,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,int64_literal_test/none,"RuntimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,integer_division_by_zero_test,RuntimeError,Issue 8301,https://dartbug.com/8301,closed
+$compiler == dart2js,issue23244_test,RuntimeError,Isolates - enum canonicalization - Issue 23244,https://dartbug.com/23244,closed
+$compiler == dart2js,left_shift_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js,library_env_test/has_io_support,"RuntimeError, OK",dart2js doesn't support io when compiling on --categories=Client,,
+$compiler == dart2js,library_env_test/has_mirror_support,Fail,mirrors not supported on web,,
+$compiler == dart2js,library_env_test/has_no_mirror_support,Pass,fails for the wrong reason.,,
+$compiler == dart2js,mint_arithmetic_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,mint_arithmetic_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js,mint_compares_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,mint_identical_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,mock_writable_final_field_test,RuntimeError,Issue 30847,https://dartbug.com/30847,closed
+$compiler == dart2js,modulo_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js,nan_identical_test,RuntimeError,Issue 11551,https://dartbug.com/11551,open
+$compiler == dart2js,number_identity_test,"CompileTimeError, OK","Error if web int literal cannot be represented exactly, see http://dartbug.com/33351",https://dartbug.com/33351,closed
+$compiler == dart2js,numbers_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js,partial_instantiation_eager_bounds_check_test,RuntimeError,Issue #34295,https://dartbug.com/34295,open
+$compiler == dart2js,partial_tearoff_instantiation_test/05,Pass,for the wrong reason.,,
+$compiler == dart2js,partial_tearoff_instantiation_test/06,Pass,for the wrong reason.,,
+$compiler == dart2js,partial_tearoff_instantiation_test/07,Pass,for the wrong reason.,,
+$compiler == dart2js,partial_tearoff_instantiation_test/08,Pass,for the wrong reason.,,
+$compiler == dart2js,regress_24283_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js,stacktrace_demangle_ctors_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,stacktrace_rethrow_error_test/none,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,stacktrace_rethrow_error_test/withtraceparameter,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,stacktrace_rethrow_nonerror_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js,truncdiv_zero_test,RuntimeError,non JS number semantics - Issue 15246,https://dartbug.com/15246,closed
+$compiler == dart2js,type_constants_test/none,RuntimeError,Issue 35052,https://dartbug.com/35052,open
+$builder_tag == dart2js_production && $compiler == dart2js,control_flow_collections/for_non_bool_condition_test,Crash,Issue 36442,https://dartbug.com/36442,
+$compiler == dart2js && $runtime == chrome && $system == macos,await_future_test,"Pass, Timeout",Issue 26735,https://dartbug.com/26735,closed
+$compiler == dart2js && $runtime == ff,round_test,"Pass, Fail, OK",Fixed in ff 35. Common JavaScript engine Math.round bug.,,
+$compiler == dart2js && $runtime == jsshell,async_call_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async_star_await_pauses_test,RuntimeError,Need triage,,
+$compiler == dart2js && $runtime == jsshell,async_star_no_cancel2_test,RuntimeError,Need triage,,
+$compiler == dart2js && $runtime == jsshell,async_star_no_cancel_test,RuntimeError,Need triage,,
+$compiler == dart2js && $runtime == jsshell,regress_23996_test,RuntimeError,"Jsshell does not provide non-zero timers, Issue 7728",https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime != none && $checked,syncstar_covariant_type_test,RuntimeError,"dart2js misplaces check in Iterator, not Iterable.",,
+$compiler == dart2js && $runtime != none && $checked,syncstar_dcall_type_test,RuntimeError,"dart2js misplaces check in Iterator, not Iterable.",,
+$compiler == dart2js && $runtime == safari,round_test,"Fail, OK",Common JavaScript engine Math.round bug.,,
+$compiler == dart2js && $system == windows,string_literals_test,"Pass, RuntimeError",Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be,,
+$compiler == dart2js && $checked,canonical_const2_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js && $checked,const_switch_test/02,"RuntimeError, OK",constant identity based on JS constants,,
+$compiler == dart2js && $checked,const_switch_test/04,"RuntimeError, OK",constant identity based on JS constants,,
+$compiler == dart2js && $checked,deferred_not_loaded_check_test,RuntimeError,Test out of date. Issue 31933,https://dartbug.com/31933,open
+$compiler == dart2js && $checked,double_int_to_string_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js && $checked,expect_test,"RuntimeError, OK",Issue 13080,https://dartbug.com/13080,closed
+$compiler == dart2js && $checked,full_stacktrace1_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,full_stacktrace2_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,full_stacktrace3_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,generalized_void_syntax_test,CompileTimeError,Issue #30176.,https://dartbug.com/30176,open
+$compiler == dart2js && $checked,generic_function_dcall_test/01,Crash,Unsupported operation: Unsupported type parameter type node T.,,
+$compiler == dart2js && $checked,generic_tearoff_test,Crash,Unsupported operation: Unsupported type parameter type node T.,,
+$compiler == dart2js && $checked,identical_closure2_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js && $checked,infinity_test,RuntimeError,non JS number semantics - Issue 4984,https://dartbug.com/4984,closed
+$compiler == dart2js && $checked,integer_division_by_zero_test,RuntimeError,Issue 8301,https://dartbug.com/8301,closed
+$compiler == dart2js && $checked,invocation_mirror2_test,RuntimeError,mirrors not supported,,
+$compiler == dart2js && $checked,left_shift_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js && $checked,mint_arithmetic_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js && $checked,mock_writable_final_field_test,RuntimeError,Issue 30847,https://dartbug.com/30847,closed
+$compiler == dart2js && $checked,modulo_test,RuntimeError,non JS number semantics,,
+$compiler == dart2js && $checked,nan_identical_test,RuntimeError,Issue 11551,https://dartbug.com/11551,open
+$compiler == dart2js && $checked,numbers_test,"RuntimeError, OK",non JS number semantics,,
+$compiler == dart2js && $checked,regress_27617_test/1,Crash,Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant,,
+$compiler == dart2js && $checked,regress_30339_test,RuntimeError,Issue 26429,https://dartbug.com/26429,closed
+$compiler == dart2js && $checked,regress_31057_test,Crash,Unsupported operation: Unsupported type parameter type node B.,,
+$compiler == dart2js && $checked,stacktrace_demangle_ctors_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,stacktrace_rethrow_error_test/none,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,stacktrace_rethrow_error_test/withtraceparameter,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,stacktrace_rethrow_nonerror_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,stacktrace_test,RuntimeError,Issue 12698,https://dartbug.com/12698,closed
+$compiler == dart2js && $checked,truncdiv_zero_test,RuntimeError,non JS number semantics - Issue 15246,https://dartbug.com/15246,closed
+$compiler == dart2js && $checked,type_parameter_test/06,Crash,Internal Error: Unexpected type variable in static context.,,
+$compiler == dart2js && $checked,type_parameter_test/09,Crash,Internal Error: Unexpected type variable in static context.,,
+$compiler == dart2js && $checked,type_variable_scope_test/03,Crash,Internal Error: Unexpected type variable in static context.,,
+$compiler == dart2js && $host_checked,async_return_types_test/nestedFuture,Crash,file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||,,
+$compiler == dart2js && $host_checked,async_star_cancel_while_paused_test,Crash,file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||,,
+$compiler == dart2js && $host_checked,await_not_started_immediately_test,Crash,Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).,,
+$compiler == dart2js && $host_checked,closure_self_reference_test,Crash,file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.,,
+$compiler == dart2js && $host_checked,issue23244_test,Crash,file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||,,
+$compiler == dart2js && $host_checked,partial_tearoff_instantiation_test/05,Crash,"Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)",,
+$compiler == dart2js && $host_checked,partial_tearoff_instantiation_test/06,Crash,"Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)",,
+$compiler == dart2js && $host_checked,partial_tearoff_instantiation_test/07,Crash,"Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)",,
+$compiler == dart2js && $host_checked,partial_tearoff_instantiation_test/08,Crash,"Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)",,
+$compiler == dart2js && $minified,async_return_types_test/nestedFuture,Crash,"Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]",https://dartbug.com/1,closed
+$compiler == dart2js && $minified,async_star_cancel_while_paused_test,Crash,"Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]",https://dartbug.com/1,closed
+$compiler == dart2js && $minified,await_not_started_immediately_test,Crash,Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).,,
+$compiler == dart2js && $minified,cyclic_type2_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,cyclic_type_test/0*,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,f_bounded_quantification4_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,f_bounded_quantification5_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,generic_closure_test/01,RuntimeError,Uses runtimeType.toString(),,
+$compiler == dart2js && $minified,invocation_mirror2_test,RuntimeError,mirrors not supported,,
+$compiler == dart2js && $minified,issue23244_test,Crash,"Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]",https://dartbug.com/1,closed
+$compiler == dart2js && $minified,mixin_generic_test,RuntimeError,Issue 12605,https://dartbug.com/12605,closed
+$compiler == dart2js && $minified,mixin_mixin2_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin3_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin4_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin5_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin6_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin_bound2_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin_bound_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,mixin_mixin_type_arguments_test,RuntimeError,Issue 31054,https://dartbug.com/31054,open
+$compiler == dart2js && $minified,regress_21795_test,RuntimeError,Issue 12605,https://dartbug.com/12605,closed
+$compiler == dart2js && $minified,runtime_type_function_test,RuntimeError,Uses runtimeType.toString(),,
+$compiler == dart2js && $minified,stack_trace_test,"RuntimeError, OK",Stack trace not preserved in minified code.,,
+$compiler == dart2js && $minified,symbol_conflict_test,RuntimeError,Issue 23857,https://dartbug.com/23857,open
+$compiler == dart2js && $runtime == chrome,html/element_types_keygen_test,RuntimeError,Issue 29055,https://dartbug.com/29055,open
+$compiler == dart2js && $runtime == chrome,html/media_stream_test,RuntimeError,Please triage.,,
+$compiler == dart2js && $runtime == chrome,html/speechrecognition_test,RuntimeError,Please triage.,,
+$compiler == dart2js && $runtime == chrome && $csp,html/worker_test/functional,RuntimeError,Issue 32261,https://dartbug.com/32261,closed
+$compiler == dart2js && $runtime == chromeOnAndroid,html/audiobuffersourcenode_test/supported,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/audiocontext_test/supported,RuntimeError,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/canvasrenderingcontext2d_test/drawImage_video_element,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/canvasrenderingcontext2d_test/drawImage_video_element_dataUrl,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/canvasrenderingcontext2d_test/fillText,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/element_types_datalist_test,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/input_element_week_test,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/media_stream_test,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/rtc_test,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/speechrecognition_test,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,html/xhr_test/json,Fail,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,typed_data/setRange_2_test,RuntimeError,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime == chromeOnAndroid,typed_data/setRange_3_test,RuntimeError,TODO(dart2js-team): Please triage this failure.,,
+$compiler == dart2js && $runtime != d8,html/html_mock_test,RuntimeError,Issue 31038,https://dartbug.com/31038,open
+$compiler == dart2js && $runtime == ff,html/element_animate_test/timing_dict,RuntimeError,Issue 26730,https://dartbug.com/26730,open
+$compiler == dart2js && $runtime == ff,html/element_types_content_test,"Pass, RuntimeError","Issues 28983, 29922",,
+$compiler == dart2js && $runtime == ff,html/element_types_keygen_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ff,html/element_types_shadow_test,"Pass, RuntimeError","Issues 28983, 29922",,
+$compiler == dart2js && $runtime == ff,html/fontface_test,Fail,Fontface not supported on ff,,
+$compiler == dart2js && $runtime == ff,html/interactive_media_test,RuntimeError,Not supported in FF,,
+$compiler == dart2js && $runtime == ff,html/messageevent_test,"Pass, RuntimeError",Issue 28983,https://dartbug.com/28983,closed
+$compiler == dart2js && $runtime == ff,html/serialized_script_value_test,"Pass, RuntimeError",Issue 28983,https://dartbug.com/28983,closed
+$compiler == dart2js && $runtime == ff,html/speechrecognition_test,RuntimeError,Please triage.,,
+$compiler == dart2js && $runtime == ff,html/text_event_test,Fail,Issue 17893,https://dartbug.com/17893,closed
+$compiler == dart2js && $runtime == ff,html/webgl_1_test,"Pass, Fail",Issue 8219,https://dartbug.com/8219,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_content_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_datalist_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_details_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_embed_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_keygen_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_meter_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_object_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_output_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_progress_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_shadow_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_template_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == ie11,html/element_types_track_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors12_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors13_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors14_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors15_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors18_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors19_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors20_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors22_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors28_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/catch_errors8_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/future_constructor2_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/future_test,RuntimeError,Timer interface not supported; Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/multiple_timer_test,"RuntimeError, OK",Needs Timer to run.,,
+$compiler == dart2js && $runtime == jsshell,async/periodic_timer2_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/periodic_timer3_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/periodic_timer4_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/run_zoned7_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/run_zoned8_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/schedule_microtask_test,Fail,Preamble file does not correctly implement scheduleImmediate.,,
+$compiler == dart2js && $runtime == jsshell,async/slow_consumer2_test,RuntimeError,Timer interface not supported; Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/slow_consumer3_test,RuntimeError,Timer interface not supported; Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/slow_consumer_test,RuntimeError,Timer interface not supported; Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_controller_async_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_controller_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_from_iterable_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic2_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic3_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic4_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic5_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic6_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_periodic_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_state_nonzero_timer_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_subscription_cancel_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_take_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_timeout_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/stream_transformation_broadcast_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_cancel1_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_cancel2_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_cancel_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_isActive_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_repeat_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/timer_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/zone_bind_test,Fail,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/zone_create_periodic_timer_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/zone_create_timer2_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == jsshell,async/zone_empty_description2_test,RuntimeError,Timer interface not supported: Issue 7728.,https://dartbug.com/7728,closed
+$compiler == dart2js && $runtime == safari,html/css_test/functional/functional,RuntimeError,Issue 32576,https://dartbug.com/32576,closed
+$compiler == dart2js && $runtime == safari,html/element_types_content_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == safari,html/element_types_datalist_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == safari,html/element_types_shadow_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $runtime == safari,html/notification_test,"Pass, RuntimeError",Safari doesn't let us access the fields of the Notification to verify them.,,
+$compiler == dart2js && $runtime == safari,html/storage_promise_test,RuntimeError,Not supported on Safari,,
+$compiler == dart2js && $browser,html/notification_permission_test,"Timeout, Pass",Issue 32002,https://dartbug.com/32002,open
+$compiler == dart2js && $browser,js/null_test,RuntimeError,Issue 30652,https://dartbug.com/30652,open
+$compiler == dart2js && $browser && $csp,html/custom/element_upgrade_test,Fail,Issue 17298,https://dartbug.com/17298,closed
+$compiler == dart2js && $browser && $csp,html/custom/js_custom_test,Fail,Issue 14643,https://dartbug.com/14643,open
+$compiler == dart2js && !$csp && $minified,html/audiobuffersourcenode_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/audiocontext_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/cache_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/custom_element_method_clash_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/custom_element_name_clash_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/custom_elements_23127_test,Crash,"Assertion failure: Cannot find value local(B2T.created#a) in (type_variable_local(B2T.T), local(C2T.created#a), local(C2T.created#b), local(C2T.created#c), BoxLocal(_box_0)) for j:constructor(C2T.created).",,
+$compiler == dart2js && !$csp && $minified,html/custom_tags_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/dart_object_local_storage_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/datalistelement_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/document_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/documentfragment_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/dom_constructors_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/domparser_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_add_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_animate_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_constructor_1_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_dimensions_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_offset_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_constructors2_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_constructors3_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_constructors4_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_constructors5_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_constructors6_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/element_types_content_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_datalist_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_details_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_embed_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_meter_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_object_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_output_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_progress_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_shadow_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_template_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/element_types_track_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && !$csp && $minified,html/form_data_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/history_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/indexeddb_1_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/keyboard_event_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/mediasource_test,"RuntimeError, Crash",NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/mutationobserver_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/node_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/node_validator_important_if_you_suppress_make_the_bug_critical_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/notification_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/performance_api_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/range_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/request_animation_frame_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/rtc_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/shadow_dom_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/svg_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/svgelement_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/transition_event_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/trusted_html_tree_sanitizer_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/typed_arrays_1_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/webgl_extensions_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/websocket_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && !$csp && $minified,html/websql_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $host_checked,html/custom/mirrors_2_test,Crash,file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.,,
+$compiler == dart2js && $host_checked,html/custom/mirrors_test,Crash,file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.,,
+$compiler == dart2js && $host_checked,html/indexeddb_3_test,Crash,file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.,,
+$compiler == dart2js && $host_checked,html/indexeddb_5_test,Crash,file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.,,
+$compiler == dart2js && $host_checked,html/js_function_getter_test/call getter as function,Crash,FileSystemException(uri=file:///usr/local/google/home/efortuna/dart2/sdk/sdk/lib/_internal/dart2js_platform.dill; message=Error reading 'sdk/lib/_internal/dart2js_platform.dill'  (No such file or directory)),,
+$compiler == dart2js && $host_checked,html/js_typed_interop_side_cast_exp_test,Crash,file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.,,
+$compiler == dart2js && $ie,html/fontface_loaded_test,RuntimeError,FontFace polyfill?,,
+$compiler == dart2js && $ie,html/fontface_test,Fail,Fontface not supported on ie,,
+$compiler == dart2js && $minified,html/canvas_pixel_array_type_alias_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/canvas_pixel_array_type_alias_test/types2_runtimeTypeName,"Fail, OK",Issue 12605,https://dartbug.com/12605,closed
+$compiler == dart2js && $minified,html/custom/mirrors_2_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/custom/mirrors_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/custom_elements_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/element_classes_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/element_types_keygen_test,RuntimeError,Issue 29922,https://dartbug.com/29922,closed
+$compiler == dart2js && $minified,html/js_function_getter_trust_types_test,Crash,NoSuchMethodError: Class 'InterfaceType' has no instance getter 'isObject'.,,
+$compiler == dart2js && $minified,html/js_typed_interop_bind_this_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/js_typed_interop_side_cast_exp_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/js_typed_interop_window_property_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/js_util_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/media_stream_test,"RuntimeError, Crash",NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/postmessage_structured_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/speechrecognition_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && $minified,html/webgl_1_test,Crash,NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.,,
+$compiler == dart2js && ($runtime == ff || $runtime == safari || $ie),html/custom/attribute_changed_callback_test/unsupported_on_polyfill,Fail,Polyfill does not support,,
+$compiler == dart2js && ($runtime == ff || $runtime == safari || $ie),html/custom/entered_left_view_test/viewless_document,Fail,Polyfill does not handle this,,
diff --git a/tests/lib_2/html/rtc_test.dart b/tests/lib_2/html/rtc_test.dart
index 8819d22..6b3c3581 100644
--- a/tests/lib_2/html/rtc_test.dart
+++ b/tests/lib_2/html/rtc_test.dart
@@ -27,10 +27,7 @@
           ]
         });
         expect(pc is RtcPeerConnection, isTrue);
-        // TODO(efortuna): Uncomment this test when RTCPeerConnection correctly
-        // implements EventListener in Firefox (works correctly in nightly, so
-        // it's coming!).
-        //pc.onIceCandidate.listen((candidate) {});
+        pc.onIceCandidate.listen((candidate) {});
       });
 
       test('ice candidate', () {
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index e1c07ea..cc91517 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -23,6 +23,7 @@
 isolate/*: SkipByDesign # No support for dart:isolate in dart4web (http://dartbug.com/30538)
 mirrors/*: SkipByDesign # Mirrors not supported on web in Dart 2.0.
 profiler/metrics_num_test: Skip # Because of an int / double type test.
+wasm/*: SkipByDesign # dart:wasm not currently supported on web.
 
 [ $compiler != dart2js ]
 async/dart2js_uncaught_error_test: Skip # JS-integration only test
@@ -32,36 +33,14 @@
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_encode_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_utf8_decode_test: SkipSlow # Times out. Issue 22050
-html/element_types_keygen_test: RuntimeError # Issue 29055
-html/media_stream_test: RuntimeError # Please triage.
-html/speechrecognition_test: RuntimeError # Please triage.
-
-[ $compiler == dart2js && $runtime == chrome && $csp ]
-html/worker_test/functional: RuntimeError # Issue 32261
 
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
-html/audiobuffersourcenode_test/supported: Fail # TODO(dart2js-team): Please triage this failure.
-html/audiocontext_test/supported: RuntimeError # TODO(dart2js-team): Please triage this failure.
-html/canvasrenderingcontext2d_test/drawImage_video_element: Fail # TODO(dart2js-team): Please triage this failure.
-html/canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # TODO(dart2js-team): Please triage this failure.
-html/canvasrenderingcontext2d_test/fillText: Fail # TODO(dart2js-team): Please triage this failure.
-html/crypto_test/functional: Pass, Slow # TODO(dart2js-team): Please triage this failure.
-html/element_types_datalist_test: Fail # TODO(dart2js-team): Please triage this failure.
-html/input_element_datetime_test: Pass, Slow # TODO(dart2js-team): Please triage this failure.
-html/input_element_week_test: Fail # TODO(dart2js-team): Please triage this failure.
-html/media_stream_test: Fail # TODO(dart2js-team): Please triage this failure.
-html/rtc_test: Fail # TODO(dart2js-team): Please triage this failure.
-html/speechrecognition_test: Fail # TODO(dart2js-team): Please triage this failure.
-html/xhr_test/json: Fail # TODO(dart2js-team): Please triage this failure.
-typed_data/setRange_2_test: RuntimeError # TODO(dart2js-team): Please triage this failure.
-typed_data/setRange_3_test: RuntimeError # TODO(dart2js-team): Please triage this failure.
+html/crypto_test/functional: Slow # TODO(dart2js-team): Please triage this failure.
+html/input_element_datetime_test: Slow # TODO(dart2js-team): Please triage this failure.
 
 [ $compiler == dart2js && $runtime == d8 ]
 html/event_callback_test: Skip # Browser test
 
-[ $compiler == dart2js && $runtime != d8 ]
-html/html_mock_test: RuntimeError # Issue 31038
-
 [ $compiler == dart2js && $runtime == ff ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
@@ -73,110 +52,23 @@
 html/custom/created_callback_test: Skip # Times out
 html/custom/document_register_basic_test: Skip # Times out, or unittest times out
 html/dart_object_local_storage_test: Skip # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
-html/element_animate_test/timing_dict: RuntimeError # Issue 26730
-html/element_types_content_test: Pass, RuntimeError # Issues 28983, 29922
-html/element_types_keygen_test: RuntimeError # Issue 29922
-html/element_types_shadow_test: Pass, RuntimeError # Issues 28983, 29922
 html/file_sample_test: Skip # FileSystem not supported on FireFox.
 html/fileapi_supported_test: Skip # FileSystem not supported on FireFox.
 html/fileapi_supported_throws_test: Skip # FileSystem not supported on FireFox.
-html/fontface_test: Fail # Fontface not supported on ff
 html/history_test/history: Skip # Issue 22050
-html/interactive_media_test: RuntimeError # Not supported in FF
-html/messageevent_test: Pass, RuntimeError # Issue 28983
 html/request_animation_frame_test: Skip # Async test hangs.
-html/serialized_script_value_test: Pass, RuntimeError # Issue 28983
-html/speechrecognition_test: RuntimeError # Please triage.
-html/text_event_test: Fail # Issue 17893
-html/webgl_1_test: Pass, Fail # Issue 8219
-
-[ $compiler == dart2js && $runtime == ie11 ]
-html/element_types_content_test: RuntimeError # Issue 29922
-html/element_types_datalist_test: RuntimeError # Issue 29922
-html/element_types_details_test: RuntimeError # Issue 29922
-html/element_types_embed_test: RuntimeError # Issue 29922
-html/element_types_keygen_test: RuntimeError # Issue 29922
-html/element_types_meter_test: RuntimeError # Issue 29922
-html/element_types_object_test: RuntimeError # Issue 29922
-html/element_types_output_test: RuntimeError # Issue 29922
-html/element_types_progress_test: RuntimeError # Issue 29922
-html/element_types_shadow_test: RuntimeError # Issue 29922
-html/element_types_template_test: RuntimeError # Issue 29922
-html/element_types_track_test: RuntimeError # Issue 29922
-
-[ $compiler == dart2js && $runtime == jsshell ]
-async/catch_errors12_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors13_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors14_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors15_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors18_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors19_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors20_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors22_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/catch_errors28_test: Fail # Timer interface not supported: Issue 7728.
-async/catch_errors8_test: Fail # Timer interface not supported: Issue 7728.
-async/future_constructor2_test: Fail # Timer interface not supported: Issue 7728.
-async/future_test: RuntimeError # Timer interface not supported; Issue 7728.
-async/multiple_timer_test: RuntimeError, OK # Needs Timer to run.
-async/periodic_timer2_test: Fail # Timer interface not supported: Issue 7728.
-async/periodic_timer3_test: Fail # Timer interface not supported: Issue 7728.
-async/periodic_timer4_test: Fail # Timer interface not supported: Issue 7728.
-async/run_zoned7_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/run_zoned8_test: Fail # Timer interface not supported: Issue 7728.
-async/schedule_microtask_test: Fail # Preamble file does not correctly implement scheduleImmediate.
-async/slow_consumer2_test: RuntimeError # Timer interface not supported; Issue 7728.
-async/slow_consumer3_test: RuntimeError # Timer interface not supported; Issue 7728.
-async/slow_consumer_test: RuntimeError # Timer interface not supported; Issue 7728.
-async/stream_controller_async_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_controller_test: Fail # Timer interface not supported: Issue 7728.
-async/stream_from_iterable_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic2_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic3_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic4_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic5_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic6_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_periodic_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_state_nonzero_timer_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_subscription_cancel_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_take_test: Fail # Timer interface not supported: Issue 7728.
-async/stream_timeout_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/stream_transformation_broadcast_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_cancel1_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_cancel2_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_cancel_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_isActive_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_repeat_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/timer_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/zone_bind_test: Fail # Timer interface not supported: Issue 7728.
-async/zone_create_periodic_timer_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/zone_create_timer2_test: RuntimeError # Timer interface not supported: Issue 7728.
-async/zone_empty_description2_test: RuntimeError # Timer interface not supported: Issue 7728.
 
 [ $compiler == dart2js && $runtime == safari ]
 html/callback_list_test: SkipByDesign # FileSystem not supported in Safari.
-html/css_test/functional/functional: RuntimeError # Issue 32576
-html/element_types_content_test: RuntimeError # Issue 29922
-html/element_types_datalist_test: RuntimeError # Issue 29922
-html/element_types_shadow_test: RuntimeError # Issue 29922
 html/file_sample_test: Skip # FileSystem not supported on Safari.
 html/fileapi_supported_throws_test: Skip # FileSystem not supported on Safari
 html/interactive_media_test: SkipSlow
-html/notification_test: Pass, RuntimeError # Safari doesn't let us access the fields of the Notification to verify them.
-html/storage_promise_test: RuntimeError # Not supported on Safari
 
 [ $compiler == dart2js && $system == linux ]
 html/interactive_geolocation_test: Skip # Requires allowing geo location.
 
-[ $compiler == dart2js && $browser ]
-html/notification_permission_test: Timeout, Pass # Issue 32002
-js/null_test: RuntimeError # Issue 30652
-
-[ $compiler == dart2js && $browser && $csp ]
-html/custom/element_upgrade_test: Fail # Issue 17298
-html/custom/js_custom_test: Fail # Issue 14643
-
 [ $compiler == dart2js && $checked ]
-convert/utf85_test: Pass, Slow # Issue 12029.
+convert/utf85_test: Slow # Issue 12029.
 html/js_function_getter_trust_types_test: Skip # --trust-type-annotations incompatible with --checked
 
 [ $compiler == dart2js && $csp && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == ff || $runtime == safari) ]
@@ -198,101 +90,9 @@
 html/mirrors_js_typed_interop_test: SkipByDesign
 html/postmessage_structured_test: SkipByDesign
 
-[ $compiler == dart2js && !$csp && $minified ]
-html/audiobuffersourcenode_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/audiocontext_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/cache_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/custom_element_method_clash_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/custom_element_name_clash_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/custom_elements_23127_test: Crash # Assertion failure: Cannot find value local(B2T.created#a) in (type_variable_local(B2T.T), local(C2T.created#a), local(C2T.created#b), local(C2T.created#c), BoxLocal(_box_0)) for j:constructor(C2T.created).
-html/custom_tags_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/dart_object_local_storage_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/datalistelement_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/document_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/documentfragment_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/dom_constructors_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/domparser_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_add_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_animate_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_constructor_1_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_dimensions_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_offset_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_constructors2_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_constructors3_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_constructors4_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_constructors5_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_constructors6_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_content_test: RuntimeError # Issue 29922
-html/element_types_datalist_test: RuntimeError # Issue 29922
-html/element_types_details_test: RuntimeError # Issue 29922
-html/element_types_embed_test: RuntimeError # Issue 29922
-html/element_types_meter_test: RuntimeError # Issue 29922
-html/element_types_object_test: RuntimeError # Issue 29922
-html/element_types_output_test: RuntimeError # Issue 29922
-html/element_types_progress_test: RuntimeError # Issue 29922
-html/element_types_shadow_test: RuntimeError # Issue 29922
-html/element_types_template_test: RuntimeError # Issue 29922
-html/element_types_track_test: RuntimeError # Issue 29922
-html/form_data_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/history_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/indexeddb_1_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/keyboard_event_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/mediasource_test: RuntimeError, Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/mutationobserver_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/node_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/node_validator_important_if_you_suppress_make_the_bug_critical_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/notification_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/performance_api_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/range_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/request_animation_frame_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/rtc_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/shadow_dom_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/svg_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/svgelement_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/transition_event_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/trusted_html_tree_sanitizer_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/typed_arrays_1_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/webgl_extensions_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/websocket_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/websql_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-
-[ $compiler == dart2js && $host_checked ]
-html/custom/mirrors_2_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/custom/mirrors_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/indexeddb_3_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/indexeddb_5_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/js_function_getter_test/call getter as function: Crash # FileSystemException(uri=file:///usr/local/google/home/efortuna/dart2/sdk/sdk/lib/_internal/dart2js_platform.dill; message=Error reading 'sdk/lib/_internal/dart2js_platform.dill'  (No such file or directory))
-html/js_typed_interop_side_cast_exp_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-
-[ $compiler == dart2js && $ie ]
-html/fontface_loaded_test: RuntimeError # FontFace polyfill?
-html/fontface_test: Fail # Fontface not supported on ie
-
-[ $compiler == dart2js && $minified ]
-html/canvas_pixel_array_type_alias_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/canvas_pixel_array_type_alias_test/types2_runtimeTypeName: Fail, OK # Issue 12605
-html/custom/mirrors_2_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/custom/mirrors_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/custom_elements_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_classes_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/element_types_keygen_test: RuntimeError # Issue 29922
-html/js_function_getter_trust_types_test: Crash # NoSuchMethodError: Class 'InterfaceType' has no instance getter 'isObject'.
-html/js_typed_interop_bind_this_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/js_typed_interop_side_cast_exp_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/js_typed_interop_window_property_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/js_util_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/media_stream_test: RuntimeError, Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/postmessage_structured_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/speechrecognition_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-html/webgl_1_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
-
 [ $compiler == dart2js && ($runtime == chrome || $runtime == ff) ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_encode_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_utf8_decode_test: SkipSlow # Times out. Issue 22050
 
-[ $compiler == dart2js && ($runtime == ff || $runtime == safari || $ie) ]
-html/custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Polyfill does not support
-html/custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
diff --git a/tests/lib_2/wasm/fn_mismatch_error_test.dart b/tests/lib_2/wasm/fn_mismatch_error_test.dart
index 308a829..b12d515 100644
--- a/tests/lib_2/wasm/fn_mismatch_error_test.dart
+++ b/tests/lib_2/wasm/fn_mismatch_error_test.dart
@@ -34,4 +34,8 @@
       () => inst.lookupFunction<Void Function(Int64)>("square"));
   Expect.throwsArgumentError(
       () => inst.lookupFunction<Void Function(dynamic)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Float)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Float Function(Int64)>("square"));
 }
diff --git a/tests/lib_2/wasm/memory_test.dart b/tests/lib_2/wasm/memory_test.dart
new file mode 100644
index 0000000..1160aca
--- /dev/null
+++ b/tests/lib_2/wasm/memory_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.
+
+// Test that we can create a WasmMemory, edit it, and grow it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  var mem = WasmMemory(1000);
+  Expect.equals(1000, mem.lengthInPages);
+  Expect.equals(1000 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+
+  mem[123] = 45;
+  Expect.equals(45, mem[123]);
+
+  mem.grow(100);
+  Expect.equals(1100, mem.lengthInPages);
+  Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  Expect.equals(45, mem[123]);
+}
diff --git a/tests/modular/extension_methods/def.dart b/tests/modular/extension_methods/def.dart
index 665da3d8..d58df3b4 100644
--- a/tests/modular/extension_methods/def.dart
+++ b/tests/modular/extension_methods/def.dart
@@ -11,6 +11,8 @@
 extension Extension on Class {
   int method() => this.field;
 
+  int methodWithOptionals([int a = 42]) => a;
+
   int get property => this.field;
 
   void set property(int value) {
diff --git a/tests/modular/extension_methods/main.dart b/tests/modular/extension_methods/main.dart
index 760cc85..cb18018 100644
--- a/tests/modular/extension_methods/main.dart
+++ b/tests/modular/extension_methods/main.dart
@@ -24,10 +24,15 @@
 
 testImplicitAccess(Class c) {
   Expect.equals(c.field, c.method());
+  Expect.equals(42, c.methodWithOptionals());
+  Expect.equals(123, c.methodWithOptionals(123));
   Expect.equals(c.field, c.property);
   Expect.equals(123, c.property = 123);
   var f = c.method;
   Expect.equals(c.field, f());
+  var f2 = c.methodWithOptionals;
+  Expect.equals(42, f2());
+  Expect.equals(87, f2(87));
 }
 
 testStaticAccess() {
diff --git a/tests/standalone_2/dwarf_stack_trace_test.dart b/tests/standalone_2/dwarf_stack_trace_test.dart
index 23a35ef..32a80bb 100644
--- a/tests/standalone_2/dwarf_stack_trace_test.dart
+++ b/tests/standalone_2/dwarf_stack_trace_test.dart
@@ -66,7 +66,7 @@
     throw "'file' failed";
     return;
   }
-  if (!result.stdout.contains("shared object")) {
+  if (!result.stdout.contains("Mach-O")) {
     print("Skipping test because we are not running from a dylib");
     return;
   }
diff --git a/tools/VERSION b/tools/VERSION
index be73740..e6b0140 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 6
 PATCH 0
-PRERELEASE 2
+PRERELEASE 3
 PRERELEASE_PATCH 0
 ABI_VERSION 16
 OLDEST_SUPPORTED_ABI_VERSION 16
diff --git a/tools/bots/aot_smoke_tests.dart b/tools/bots/aot_smoke_tests.dart
index bb92379..a035361 100755
--- a/tools/bots/aot_smoke_tests.dart
+++ b/tools/bots/aot_smoke_tests.dart
@@ -13,57 +13,120 @@
 import 'dart:convert';
 
 import 'package:args/args.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
 
-get_dart2aot() {
-  if (Platform.isLinux) {
-    return 'out/ReleaseX64/dart-sdk/bin/dart2aot';
-  } else if (Platform.isMacOS) {
-    return 'xcodebuild/ReleaseX64/dart-sdk/bin/dart2aot';
-  } else if (Platform.isWindows) {
-    return 'out\\ReleaseX64\\dart-sdk\\bin\\dart2aot.bat';
-  } else {
-    throw 'Unsupported host platform!';
+final String newline = Platform.isWindows ? '\r\n' : '\n';
+final String scriptSuffix = Platform.isWindows ? ".bat" : "";
+final String executableSuffix = Platform.isWindows ? ".exe" : "";
+final String sdkBinDir = path.dirname(Platform.executable);
+final String dart2aot = path.join(sdkBinDir, 'dart2aot${scriptSuffix}');
+final String dartaotruntime =
+    path.join(sdkBinDir, 'dartaotruntime${executableSuffix}');
+final String dart2native = path.join(sdkBinDir, 'dart2native${scriptSuffix}');
+
+Future<void> withTempDir(Future fun(String dir)) async {
+  final Directory tempDir = Directory.systemTemp.createTempSync();
+  try {
+    await fun(tempDir.path);
+  } finally {
+    tempDir.deleteSync(recursive: true);
   }
 }
 
-get_dartaotruntime() {
-  if (Platform.isLinux) {
-    return 'out/ReleaseX64/dart-sdk/bin/dartaotruntime';
-  } else if (Platform.isMacOS) {
-    return 'xcodebuild/ReleaseX64/dart-sdk/bin/dartaotruntime';
-  } else if (Platform.isWindows) {
-    return 'out\\ReleaseX64\\dart-sdk\\bin\\dartaotruntime.exe';
-  } else {
-    throw 'Unsupported host platform!';
-  }
-}
+void main(List<String> args) {
+  test("dart2aot: Can compile and run AOT", () async {
+    await withTempDir((String tmp) async {
+      final String testCode = path.join('tools', 'bots', 'dart_aot_test.dart');
+      final String tmpAot = path.join(tmp, 'dart_aot_test.dart.aot');
 
-assert_equals(var expected, var actual) {
-  if (expected != actual) {
-    print('Test failed! Expected \'$expected\', got \'$actual\'');
-    exit(1);
-  }
-}
+      {
+        final ProcessResult result =
+            await Process.run(dart2aot, [testCode, tmpAot]);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+        expect(result.stdout, '');
+      }
 
-main(List<String> args) async {
-  ProcessResult result;
+      {
+        const String testStr = 'Dart AOT';
+        final ProcessResult result =
+            await Process.run(dartaotruntime, [tmpAot, testStr]);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+        expect(result.stdout, 'Hello, ${testStr}.${newline}');
+      }
+    });
+  });
 
-  result = Process.runSync(get_dart2aot(),
-      ['tools/bots/dart_aot_test.dart', 'tools/bots/dart_aot_test.dart.aot'],
-      stdoutEncoding: utf8, stderrEncoding: utf8);
-  stdout.write(result.stdout);
-  if (result.exitCode != 0 || result.stderr != '') {
-    stderr.write(result.stderr);
-    exit(1);
-  }
+  test("dart2native: Can compile and run AOT", () async {
+    await withTempDir((String tmp) async {
+      final String testCode = path.join('tools', 'bots', 'dart_aot_test.dart');
+      final String tmpAot = path.join(tmp, 'dart_aot_test.dart.aot');
 
-  result = Process.runSync(
-      get_dartaotruntime(), ['tools/bots/dart_aot_test.dart.aot'],
-      stdoutEncoding: utf8, stderrEncoding: utf8);
-  if (result.exitCode != 0 || result.stderr != '') {
-    stderr.write(result.stderr);
-    exit(1);
-  }
+      {
+        final ProcessResult result = await Process.run(dart2native,
+            [testCode, '--output', tmpAot, '--output-kind', 'aot']);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+      }
 
-  assert_equals('Hello, 世界.', result.stdout.trim());
+      {
+        const String testStr = 'Dart AOT';
+        final ProcessResult result =
+            await Process.run(dartaotruntime, [tmpAot, testStr]);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+        expect(result.stdout, 'Hello, ${testStr}.${newline}');
+      }
+    });
+  });
+
+  test("dart2native: Can compile and run exe", () async {
+    await withTempDir((String tmp) async {
+      final String testCode = path.join('tools', 'bots', 'dart_aot_test.dart');
+      final String tmpExe = path.join(tmp, 'dart_aot_test.exe');
+
+      {
+        final ProcessResult result =
+            await Process.run(dart2native, [testCode, '--output', tmpExe]);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+      }
+
+      {
+        const String testStr = 'Dart AOT';
+        final ProcessResult result = await Process.run(tmpExe, [testStr]);
+        expect(result.stderr, '');
+        expect(result.exitCode, 0);
+        expect(result.stdout, 'Hello, ${testStr}.${newline}');
+      }
+    });
+  });
+
+  test("dart2native: Returns non-zero on missing file.", () async {
+    await withTempDir((String tmp) async {
+      final String testCode = path.join(tmp, 'does_not_exist.dart');
+      final String tmpExe = path.join(tmp, 'dart_aot_test.exe');
+
+      {
+        final ProcessResult result =
+            await Process.run(dart2native, [testCode, '--output', tmpExe]);
+        expect(result.exitCode, isNonZero);
+      }
+    });
+  });
+
+  test("dart2native: Returns non-zero on non-file.", () async {
+    await withTempDir((String tmp) async {
+      final String testCode = tmp; // This is a directory, not a file.
+      final String tmpExe = path.join(tmp, 'dart_aot_test.exe');
+
+      {
+        final ProcessResult result =
+            await Process.run(dart2native, [testCode, '--output', tmpExe]);
+        expect(result.exitCode, isNonZero);
+      }
+    });
+  });
 }
diff --git a/tools/bots/dart_aot_test.dart b/tools/bots/dart_aot_test.dart
index 0a626f4..36abe33 100755
--- a/tools/bots/dart_aot_test.dart
+++ b/tools/bots/dart_aot_test.dart
@@ -5,6 +5,7 @@
 
 // Test program for Dart AOT (dart2aot, dartaotruntime).
 
-main(List<String> args) async {
-  print('Hello, 世界.');
+void main(List<String> args) async {
+  final String who = !args.isEmpty ? args[0] : '世界';
+  print('Hello, ${who}.');
 }
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index acd6fcf..aca2268 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -341,26 +341,26 @@
         "use-elf": true
     }},
     "dartk-android-(debug|product|release)-(arm|arm64)": {},
-    "dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
+    "dartkp-(linux|win|mac)-(debug|product|release)-(simarm|simarm64)": {
       "options": {
         "use-blobs": true
     }},
-    "dartkp-(win|mac)-(debug|product|release)-(simarm|simarm64)": {
+    "dartkp-linux-(debug|product|release)-(simarm|simarm64)-crossword": {
       "options": {
-        "use-blobs": true
+        "builder-tag": "crossword"
     }},
-    "dartkp-(linux|win|mac)-(debug|product|release)-(simarm|simarm64)-crossword": {
+    "dartkp-(win|mac)-(debug|product|release)-(simarm|simarm64)-crossword": {
       "options": {
         "builder-tag": "crossword",
         "use-blobs": true
     }},
     "dartkp-win-(product|release)-x64": {
       "options": {
-        "use-blobs": true
+        "use-elf": true
     }},
     "dartkp-win-debug-x64": {
       "options": {
-        "use-blobs": true,
+        "use-elf": true,
         "vm-options": ["--no-enable-malloc-hooks"]
     }},
     "dartkp-(linux|mac)-(product|release)-x64": { },
@@ -380,7 +380,7 @@
     "dartkp-no-bare-(linux|mac|win)-(debug|product|release)-(simarm|simarm64)": {
       "options": {
         "vm-options": ["--no-enable-malloc-hooks", "--no-use-bare-instructions"],
-        "use-blobs": true
+        "use-elf": true
     }},
     "dartk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
     "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
@@ -1611,8 +1611,8 @@
           "script": "tools/bots/dart_sdk.py"
         },
         {
-          "name": "run smoke tests",
-          "script": "out/ReleaseX64/dart",
+          "name": "run AOT and Exe smoke tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
             "tools/bots/aot_smoke_tests.dart"
           ]
@@ -1661,8 +1661,8 @@
           "script": "tools/bots/dart_sdk.py"
         },
         {
-          "name": "run smoke tests",
-          "script": "xcodebuild/ReleaseX64/dart",
+          "name": "run AOT and Exe smoke tests",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
             "tools/bots/aot_smoke_tests.dart"
           ]
@@ -1698,8 +1698,8 @@
           "script": "tools/bots/dart_sdk.py"
         },
         {
-          "name": "run smoke tests",
-          "script": "out/ReleaseX64/dart.exe",
+          "name": "run AOT and Exe smoke tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart.exe",
           "arguments": [
             "tools/bots/aot_smoke_tests.dart"
           ]
@@ -2278,7 +2278,7 @@
     },
     {
       "builders": [
-        "vm-kernel-precomp-mac-debug-simarm_x64",
+        "vm-kernel-precomp-linux-debug-simarm_x64",
         "vm-kernel-precomp-mac-release-simarm_x64"
       ],
       "meta": {
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index e3c30d5..882e1d3 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -216,6 +216,8 @@
     third_party/d8/linux/ia32/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
     out/ReleaseIA32/dart-sdk/bin/dart2js --use-kernel --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/ia32/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
+    out/ReleaseIA32/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/ia32/d8 hello.dart
+    out/ReleaseIA32/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/ia32/d8 --kernel hello.dart
     out/ReleaseIA32/dart pkg/front_end/tool/perf.dart parse hello.dart
     out/ReleaseIA32/dart pkg/front_end/tool/perf.dart scan hello.dart
     out/ReleaseIA32/dart pkg/front_end/tool/fasta_perf.dart kernel_gen_e2e hello.dart
@@ -395,6 +397,8 @@
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --enable-interpreter --compilation-counter-threshold=-1 hello.dart
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --use-bytecode-compiler hello.dart
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --use-bytecode-compiler --optimization-counter-threshold=-1 hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/ia32/d8 --mode=compile --compile-vm-options=--print-metrics --packages=.packages --out out.js hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/ia32/d8 --mode=compile --compile-vm-options=--print-metrics --packages=.packages --out out.js --kernel hello.dart
     out/ReleaseX64/dart pkg/front_end/tool/perf.dart parse hello.dart
     out/ReleaseX64/dart pkg/front_end/tool/perf.dart scan hello.dart
     out/ReleaseX64/dart pkg/front_end/tool/fasta_perf.dart kernel_gen_e2e hello.dart
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index b7967ec..ebe497a 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -238,7 +238,7 @@
     // always dealing with pixels in this method.
     var styles = _element.getComputedStyle();
 
-    var val = 0;
+    num val = 0;
 
     for (String measurement in dimensions) {
       // The border-box and default box model both exclude margin in the regular
diff --git a/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate b/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
index 06b5456..24cc438 100644
--- a/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
@@ -6,12 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS('', 'window[#]',
-        Device.isFirefox ? '${Device.propertyPrefix}RTCIceCandidate' :
-        'RTCIceCandidate');
+    var constructorName = JS('', 'window[#]', 'RTCIceCandidate');
     return JS('RtcIceCandidate', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
diff --git a/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate b/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
index 9ca8ceb..fd57f16 100644
--- a/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
@@ -6,12 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(Map dictionary) {
-    // TODO(efortuna): Remove this check if when you can actually construct with
-    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
-    // but one can't be used as a constructor).
-    var constructorName = JS('', 'window[#]',
-        Device.isFirefox ? '${Device.propertyPrefix}RTCSessionDescription' :
-       'RTCSessionDescription');
+    var constructorName = JS('', 'window[#]', 'RTCSessionDescription');
     return JS('RtcSessionDescription',
         'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
diff --git a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
index 868d215..4af23ea 100644
--- a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
+++ b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
@@ -6,8 +6,8 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(Map rtcIceServers, [Map mediaConstraints]) {
-    var constructorName = JS('RtcPeerConnection', 'window[#]',
-        '${Device.propertyPrefix}RTCPeerConnection');
+    var constructorName =
+        JS('RtcPeerConnection', 'window[#]', 'RTCPeerConnection');
     if (mediaConstraints != null) {
       return JS('RtcPeerConnection', 'new #(#,#)', constructorName,
           convertDartToNative_SerializedScriptValue(rtcIceServers),