Version 1.25.0-dev.2.0

Merge commit '8ba4f78dd30981372e5e14966f8576346b7f5a74' into dev
diff --git a/.packages b/.packages
index 549acea..3c4fe9b 100644
--- a/.packages
+++ b/.packages
@@ -76,6 +76,7 @@
 pub:third_party/pkg/pub/lib
 pub_semver:third_party/pkg/pub_semver/lib
 quiver:third_party/pkg/quiver/lib
+quiver_hashcode:third_party/pkg/quiver_hashcode/lib
 resource:third_party/pkg/resource/lib
 scheduled_test:third_party/pkg/scheduled_test/lib
 sdk_library_metadata:sdk/lib/_internal/sdk_library_metadata/lib
@@ -94,6 +95,7 @@
 test_dart:tools/testing/dart
 testing:pkg/testing/lib
 test_reflective_loader:third_party/pkg/test_reflective_loader/lib
+tuple:third_party/pkg/tuple/lib
 typed_data:third_party/pkg/typed_data/lib
 typed_mock:pkg/typed_mock/lib
 unittest:third_party/pkg/unittest/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea3d94b..510ca6d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
 ## 1.25.0
 
 ### Language
+* A string in a `part of` declaration may now be used to refer to the library
+  this file is part of.
+  A library part can now declare its library either as:
+  `part of name.of.library;` or as `part of "uriReferenceOfLibrary.dart";`.
+  This allows libraries with no library declarations (and therefore no name)
+  to have parts, and it allows tools to easily find the library of a part
+  file.
 
 #### Strong Mode
 
diff --git a/DEPS b/DEPS
index c033cff..c9e9f01 100644
--- a/DEPS
+++ b/DEPS
@@ -62,7 +62,7 @@
   "dart2js_info_tag" : "@0.5.4+2",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@1.0.6",
-  "dartdoc_tag" : "@v0.9.14-dev",
+  "dartdoc_tag" : "@v0.12.0",
   "fixnum_tag": "@0.10.5",
   "func_tag": "@1.0.0",
   "glob_tag": "@1.1.3",
@@ -83,7 +83,7 @@
   "matcher_tag": "@0.12.0+2",
   "metatest_tag": "@0.2.2+3",
   "mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
-  "mustache4dart_tag" : "@v1.0.10",
+  "mustache4dart_tag" : "@v1.1.0",
   "oauth2_tag": "@1.0.2",
   "observable_tag": "@0.17.0",
   "observatory_pub_packages_rev": "@26aad88f1c1915d39bbcbff3cad589e2402fdcf1",
@@ -116,6 +116,7 @@
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
   "test_reflective_loader_tag": "@0.1.0",
   "test_tag": "@0.12.18+1",
+  "tuple_tag": "@v1.0.1",
   "typed_data_tag": "@1.1.3",
   "usage_tag": "@v3.0.0+1",
   "utf_tag": "@0.9.0+3",
@@ -324,6 +325,8 @@
   Var("dart_root") + "/third_party/pkg/test_reflective_loader":
       (Var("github_mirror") % "test_reflective_loader") +
       Var("test_reflective_loader_tag"),
+  Var("dart_root") + "/third_party/pkg/tuple":
+      (Var("github_dartlang") % "tuple") + Var("tuple_tag"),
   Var("dart_root") + "/third_party/pkg/typed_data":
       (Var("github_mirror") % "typed_data") + Var("typed_data_tag"),
   Var("dart_root") + "/third_party/pkg/usage":
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index f3f98f1..a3c1a6e 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -35,13 +35,11 @@
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal2.dart';
 import 'package:analysis_server/src/single_context_manager.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
 import 'package:analyzer/context/context_root.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -50,7 +48,6 @@
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/dart/analysis/ast_provider_context.dart';
 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
@@ -62,9 +59,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/util/glob.dart';
-import 'package:analyzer/task/dart.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 import 'package:front_end/src/base/performace_logger.dart';
 import 'package:front_end/src/incremental/byte_store.dart';
@@ -281,11 +276,6 @@
   StreamController<ChangeNotice> _onFileAnalyzedController;
 
   /**
-   * The controller used to notify others when priority sources change.
-   */
-  StreamController<PriorityChangeEvent> _onPriorityChangeController;
-
-  /**
    * True if any exceptions thrown by analysis should be propagated up the call
    * stack.
    */
@@ -469,8 +459,7 @@
           packageMapProvider,
           analyzedFilesGlobs,
           instrumentationService,
-          defaultContextOptions,
-          options.enableNewAnalysisDriver);
+          defaultContextOptions);
     }
     this.fileResolverProvider = fileResolverProvider;
     this.packageResolverProvider = packageResolverProvider;
@@ -484,8 +473,6 @@
     _onFileAddedController = new StreamController.broadcast();
     // temporary plugin support:
     _onFileChangedController = new StreamController.broadcast();
-    _onPriorityChangeController =
-        new StreamController<PriorityChangeEvent>.broadcast();
     running = true;
     onAnalysisStarted.first.then((_) {
       onAnalysisComplete.then((_) {
@@ -494,11 +481,7 @@
       });
     });
     _setupIndexInvalidation();
-    if (options.enableNewAnalysisDriver) {
-      searchEngine = new SearchEngineImpl2(driverMap.values);
-    } else if (index != null) {
-      searchEngine = new SearchEngineImpl(index, getAstProvider);
-    }
+    searchEngine = new SearchEngineImpl2(driverMap.values);
     Notification notification = new ServerConnectedParams(VERSION, io.pid,
             sessionId: instrumentationService.sessionId)
         .toNotification();
@@ -592,12 +575,6 @@
   Stream get onFileChanged => _onFileChangedController.stream;
 
   /**
-   * The stream that is notified when priority sources change.
-   */
-  Stream<PriorityChangeEvent> get onPriorityChange =>
-      _onPriorityChangeController.stream;
-
-  /**
    * The [Future] that completes when the next operation is performed.
    */
   Future get test_onOperationPerformed {
@@ -665,31 +642,6 @@
   }
 
   /**
-   * Return the preferred [AnalysisContext] for analyzing the given [path].
-   * This will be the context that explicitly contains the path, if any such
-   * context exists, otherwise it will be the first analysis context that
-   * implicitly analyzes it.  Return `null` if no context is analyzing the
-   * path.
-   */
-  AnalysisContext getAnalysisContext(String path) {
-    return getContextSourcePair(path).context;
-  }
-
-  /**
-   * Return any [AnalysisContext] that is analyzing the given [source], either
-   * explicitly or implicitly.  Return `null` if there is no such context.
-   */
-  AnalysisContext getAnalysisContextForSource(Source source) {
-    for (AnalysisContext context in analysisContexts) {
-      SourceKind kind = context.getKindOf(source);
-      if (kind != SourceKind.UNKNOWN) {
-        return context;
-      }
-    }
-    return null;
-  }
-
-  /**
    * Return an analysis driver to which the file with the given [path] is
    * added if one exists, otherwise a driver in which the file was analyzed if
    * one exists, otherwise the first driver, otherwise `null`.
@@ -737,33 +689,8 @@
    * Return the [AstProvider] for the given [path].
    */
   AstProvider getAstProvider(String path) {
-    if (options.enableNewAnalysisDriver) {
-      var analysisDriver = getAnalysisDriver(path);
-      return new AstProviderForDriver(analysisDriver);
-    } else {
-      var analysisContext = getAnalysisContext(path);
-      return new AstProviderForContext(analysisContext);
-    }
-  }
-
-  CompilationUnitElement getCompilationUnitElement(String file) {
-    ContextSourcePair pair = getContextSourcePair(file);
-    if (pair == null) {
-      return null;
-    }
-    // prepare AnalysisContext and Source
-    AnalysisContext context = pair.context;
-    Source unitSource = pair.source;
-    if (context == null || unitSource == null) {
-      return null;
-    }
-    // get element in the first library
-    List<Source> librarySources = context.getLibrariesContaining(unitSource);
-    if (!librarySources.isNotEmpty) {
-      return null;
-    }
-    Source librarySource = librarySources.first;
-    return context.getCompilationUnitElement(unitSource, librarySource);
+    nd.AnalysisDriver analysisDriver = getAnalysisDriver(path);
+    return new AstProviderForDriver(analysisDriver);
   }
 
   /**
@@ -793,68 +720,6 @@
   }
 
   /**
-   * Return the primary [ContextSourcePair] representing the given [path].
-   *
-   * The [AnalysisContext] of this pair will be the context that explicitly
-   * contains the path, if any such context exists, otherwise it will be the
-   * first context that implicitly analyzes it.
-   *
-   * If the [path] is not analyzed by any context, a [ContextSourcePair] with
-   * a `null` context and a `file` [Source] is returned.
-   *
-   * If the [path] doesn't represent a file, a [ContextSourcePair] with a `null`
-   * context and `null` [Source] is returned.
-   *
-   * Does not return `null`.
-   */
-  ContextSourcePair getContextSourcePair(String path) {
-    // try SDK
-    {
-      DartSdk sdk = findSdk();
-      if (sdk != null) {
-        Uri uri = resourceProvider.pathContext.toUri(path);
-        Source sdkSource = sdk.fromFileUri(uri);
-        if (sdkSource != null) {
-          return new ContextSourcePair(sdk.context, sdkSource);
-        }
-      }
-    }
-    // try to find the deep-most containing context
-    Resource resource = resourceProvider.getResource(path);
-    if (resource is! File) {
-      return new ContextSourcePair(null, null);
-    }
-    File file = resource;
-    {
-      AnalysisContext containingContext = getContainingContext(path);
-      if (containingContext != null) {
-        Source source =
-            ContextManagerImpl.createSourceInContext(containingContext, file);
-        return new ContextSourcePair(containingContext, source);
-      }
-    }
-    // try to find a context that analysed the file
-    for (AnalysisContext context in analysisContexts) {
-      Source source = ContextManagerImpl.createSourceInContext(context, file);
-      SourceKind kind = context.getKindOf(source);
-      if (kind != SourceKind.UNKNOWN) {
-        return new ContextSourcePair(context, source);
-      }
-    }
-    // try to find a context for which the file is a priority source
-    for (InternalAnalysisContext context in analysisContexts) {
-      List<Source> sources = context.getSourcesWithFullName(path);
-      if (sources.isNotEmpty) {
-        Source source = sources.first;
-        return new ContextSourcePair(context, source);
-      }
-    }
-    // file-based source
-    Source fileSource = file.createSource();
-    return new ContextSourcePair(null, fileSource);
-  }
-
-  /**
    * Return a [Future] that completes with the [Element] at the given
    * [offset] of the given [file], or with `null` if there is no node at the
    * [offset] or the node does not have an element.
@@ -889,44 +754,13 @@
   }
 
   /**
-   * Return an analysis error info containing the array of all of the errors and
-   * the line info associated with [file].
-   *
-   * Returns `null` if [file] does not belong to any [AnalysisContext], or the
-   * file does not exist.
-   *
-   * The array of errors will be empty if there are no errors in [file]. The
-   * errors contained in the array can be incomplete.
-   *
-   * This method does not wait for all errors to be computed, and returns just
-   * the current state.
-   */
-  AnalysisErrorInfo getErrors(String file) {
-    ContextSourcePair contextSource = getContextSourcePair(file);
-    AnalysisContext context = contextSource.context;
-    Source source = contextSource.source;
-    if (context == null) {
-      return null;
-    }
-    if (!context.exists(source)) {
-      return null;
-    }
-    return context.getErrors(source);
-  }
-
-  /**
    * Return a [Future] that completes with the resolved [AstNode] at the
    * given [offset] of the given [file], or with `null` if there is no node as
    * the [offset].
    */
   Future<AstNode> getNodeAtOffset(String file, int offset) async {
-    CompilationUnit unit;
-    if (options.enableNewAnalysisDriver) {
-      nd.AnalysisResult result = await getAnalysisResult(file);
-      unit = result?.unit;
-    } else {
-      unit = await getResolvedCompilationUnit(file);
-    }
+    nd.AnalysisResult result = await getAnalysisResult(file);
+    CompilationUnit unit = result?.unit;
     if (unit != null) {
       return new NodeLocator(offset).searchWithin(unit);
     }
@@ -939,23 +773,8 @@
    * Dart file or cannot be resolved.
    */
   Future<CompilationUnit> getResolvedCompilationUnit(String path) async {
-    if (options.enableNewAnalysisDriver) {
-      nd.AnalysisResult result = await getAnalysisResult(path);
-      return result?.unit;
-    }
-    ContextSourcePair contextSource = getContextSourcePair(path);
-    AnalysisContext context = contextSource.context;
-    if (context == null) {
-      return null;
-    }
-    return runWithActiveContext(context, () {
-      Source unitSource = contextSource.source;
-      List<Source> librarySources = context.getLibrariesContaining(unitSource);
-      for (Source librarySource in librarySources) {
-        return context.resolveCompilationUnit2(unitSource, librarySource);
-      }
-      return null;
-    });
+    nd.AnalysisResult result = await getAnalysisResult(path);
+    return result?.unit;
   }
 
 // TODO(brianwilkerson) Add the following method after 'prioritySources' has
@@ -1044,43 +863,6 @@
   }
 
   /**
-   * Returns a [Future] completing when [file] has been completely analyzed, in
-   * particular, all its errors have been computed.  The future is completed
-   * with an [AnalysisDoneReason] indicating what caused the file's analysis to
-   * be considered complete.
-   *
-   * If the given file doesn't belong to any context, null is returned.
-   *
-   * TODO(scheglov) this method should be improved.
-   *
-   * 1. The analysis context should be told to analyze this particular file ASAP.
-   *
-   * 2. We should complete the future as soon as the file is analyzed (not wait
-   *    until the context is completely finished)
-   */
-  Future<AnalysisDoneReason> onFileAnalysisComplete(String file) {
-    // prepare AnalysisContext
-    AnalysisContext context = getAnalysisContext(file);
-    if (context == null) {
-      return null;
-    }
-    // done if everything is already analyzed
-    if (isAnalysisComplete()) {
-      return new Future.value(AnalysisDoneReason.COMPLETE);
-    }
-    // schedule context analysis
-    schedulePerformAnalysisOperation(context);
-    // associate with the context completer
-    Completer<AnalysisDoneReason> completer =
-        contextAnalysisDoneCompleters[context];
-    if (completer == null) {
-      completer = new Completer<AnalysisDoneReason>();
-      contextAnalysisDoneCompleters[context] = completer;
-    }
-    return completer.future;
-  }
-
-  /**
    * Perform the next available [ServerOperation].
    */
   void performOperation() {
@@ -1293,6 +1075,7 @@
           .contains(GeneralAnalysisService.ANALYZED_FILES)) {
         sendAnalysisNotificationAnalyzedFiles(this);
       }
+      _scheduleAnalysisImplementedNotification();
     }
     // Only send status when subscribed.
     if (!serverServices.contains(ServerService.STATUS)) {
@@ -1341,85 +1124,16 @@
     if (notificationManager != null) {
       notificationManager.setSubscriptions(subscriptions);
     }
-    if (options.enableNewAnalysisDriver) {
-      this.analysisServices = subscriptions;
-      Set<String> allNewFiles =
-          subscriptions.values.expand((files) => files).toSet();
-      for (String file in allNewFiles) {
-        // The result will be produced by the "results" stream with
-        // the fully resolved unit, and processed with sending analysis
-        // notifications as it happens after content changes.
-        if (AnalysisEngine.isDartFileName(file)) {
-          getAnalysisResult(file);
-        }
-      }
-      return;
-    }
-    // send notifications for already analyzed sources
-    subscriptions.forEach((service, Set<String> newFiles) {
-      Set<String> oldFiles = analysisServices[service];
-      Set<String> todoFiles =
-          oldFiles != null ? newFiles.difference(oldFiles) : newFiles;
-      for (String file in todoFiles) {
-        if (contextManager.isIgnored(file)) {
-          continue;
-        }
-        // prepare context
-        ContextSourcePair contextSource = getContextSourcePair(file);
-        AnalysisContext context = contextSource.context;
-        if (context == null) {
-          continue;
-        }
-        Source source = contextSource.source;
-        // Ensure that if the AST is flushed / not ready, it will be
-        // computed eventually.
-        if (AnalysisEngine.isDartFileName(file)) {
-          (context as InternalAnalysisContext).ensureResolvedDartUnits(source);
-        }
-        // Send notifications that don't directly take an AST.
-        switch (service) {
-          case AnalysisService.NAVIGATION:
-            sendAnalysisNotificationNavigation(this, context, source);
-            continue;
-          case AnalysisService.OCCURRENCES:
-            sendAnalysisNotificationOccurrences(this, context, source);
-            continue;
-        }
-        // Dart unit notifications.
-        if (AnalysisEngine.isDartFileName(file)) {
-          // TODO(scheglov) This way to get resolved information is very Dart
-          // specific. OTOH as it is planned now Angular results are not
-          // flushable.
-          CompilationUnit dartUnit =
-              _getResolvedCompilationUnitToResendNotification(context, source);
-          if (dartUnit != null) {
-            switch (service) {
-              case AnalysisService.HIGHLIGHTS:
-                sendAnalysisNotificationHighlights(this, file, dartUnit);
-                break;
-              case AnalysisService.OUTLINE:
-                AnalysisContext context = resolutionMap
-                    .elementDeclaredByCompilationUnit(dartUnit)
-                    .context;
-                LineInfo lineInfo = context.getLineInfo(source);
-                SourceKind kind = context.getKindOf(source);
-                sendAnalysisNotificationOutline(
-                    this, file, lineInfo, kind, dartUnit);
-                break;
-              case AnalysisService.OVERRIDES:
-                sendAnalysisNotificationOverrides(this, file, dartUnit);
-                break;
-            }
-          }
-        }
-      }
-    });
-    // remember new subscriptions
     this.analysisServices = subscriptions;
-    // special case for implemented elements
-    if (analysisServices.containsKey(AnalysisService.IMPLEMENTED) &&
-        isAnalysisComplete()) {
-      _scheduleAnalysisImplementedNotification();
+    Set<String> allNewFiles =
+        subscriptions.values.expand((files) => files).toSet();
+    for (String file in allNewFiles) {
+      // The result will be produced by the "results" stream with
+      // the fully resolved unit, and processed with sending analysis
+      // notifications as it happens after content changes.
+      if (AnalysisEngine.isDartFileName(file)) {
+        getAnalysisResult(file);
+      }
     }
   }
 
@@ -1446,83 +1160,12 @@
    * Set the priority files to the given [files].
    */
   void setPriorityFiles(String requestId, List<String> files) {
-    if (options.enableNewAnalysisDriver) {
-      priorityFiles.clear();
-      priorityFiles.addAll(files);
-      // Set priority files in drivers.
-      driverMap.values.forEach((driver) {
-        driver.priorityFiles = files;
-      });
-      return;
-    }
-    // Note: when a file is a priority file, that information needs to be
-    // propagated to all contexts that analyze the file, so that all contexts
-    // will be able to do incremental resolution of the file.  See
-    // dartbug.com/22209.
-    Map<AnalysisContext, List<Source>> sourceMap =
-        new HashMap<AnalysisContext, List<Source>>();
-    List<String> unanalyzed = new List<String>();
-    Source firstSource = null;
-    files.forEach((String file) {
-      if (contextManager.isIgnored(file)) {
-        unanalyzed.add(file);
-        return;
-      }
-      // Prepare the context/source pair.
-      ContextSourcePair contextSource = getContextSourcePair(file);
-      AnalysisContext preferredContext = contextSource.context;
-      Source source = contextSource.source;
-      // Try to make the file analyzable.
-      // If it is not in any context yet, add it to the first one which
-      // could use it, e.g. imports its package, even if not the library.
-      if (preferredContext == null) {
-        Resource resource = resourceProvider.getResource(file);
-        if (resource is File && resource.exists) {
-          for (AnalysisContext context in analysisContexts) {
-            Uri uri = context.sourceFactory.restoreUri(source);
-            if (uri.scheme != 'file') {
-              preferredContext = context;
-              source =
-                  ContextManagerImpl.createSourceInContext(context, resource);
-              break;
-            }
-          }
-        }
-      }
-      // Fill the source map.
-      bool contextFound = false;
-      if (preferredContext != null) {
-        sourceMap.putIfAbsent(preferredContext, () => <Source>[]).add(source);
-        contextFound = true;
-      }
-      for (AnalysisContext context in analysisContexts) {
-        if (context != preferredContext &&
-            context.getKindOf(source) != SourceKind.UNKNOWN) {
-          sourceMap.putIfAbsent(context, () => <Source>[]).add(source);
-          contextFound = true;
-        }
-      }
-      if (firstSource == null) {
-        firstSource = source;
-      }
-      if (!contextFound) {
-        unanalyzed.add(file);
-      }
+    priorityFiles.clear();
+    priorityFiles.addAll(files);
+    // Set priority files in drivers.
+    driverMap.values.forEach((driver) {
+      driver.priorityFiles = files;
     });
-    if (unanalyzed.isNotEmpty) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.writeAll(unanalyzed, ', ');
-      throw new RequestFailure(
-          new Response.unanalyzedPriorityFiles(requestId, buffer.toString()));
-    }
-    sourceMap.forEach((context, List<Source> sourceList) {
-      context.analysisPriorityOrder = sourceList;
-      // Schedule the context for analysis so that it has the opportunity to
-      // cache the AST's for the priority sources as soon as possible.
-      schedulePerformAnalysisOperation(context);
-    });
-    operationQueue.reschedule();
-    _onPriorityChangeController.add(new PriorityChangeEvent(firstSource));
   }
 
   /**
@@ -1546,15 +1189,6 @@
     });
   }
 
-  void test_flushAstStructures(String file) {
-    if (AnalysisEngine.isDartFileName(file)) {
-      ContextSourcePair contextSource = getContextSourcePair(file);
-      InternalAnalysisContext context = contextSource.context;
-      Source source = contextSource.source;
-      context.test_flushAstStructures(source);
-    }
-  }
-
   /**
    * Performs all scheduled analysis operations.
    */
@@ -1574,58 +1208,9 @@
    * Implementation for `analysis.updateContent`.
    */
   void updateContent(String id, Map<String, dynamic> changes) {
-    if (options.enableNewAnalysisDriver) {
-      changes.forEach((file, change) {
-        // Prepare the new contents.
-        String oldContents = fileContentOverlay[file];
-        String newContents;
-        if (change is AddContentOverlay) {
-          newContents = change.content;
-        } else if (change is ChangeContentOverlay) {
-          if (oldContents == null) {
-            // The client may only send a ChangeContentOverlay if there is
-            // already an existing overlay for the source.
-            throw new RequestFailure(new Response(id,
-                error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
-                    'Invalid overlay change')));
-          }
-          try {
-            newContents = SourceEdit.applySequence(oldContents, change.edits);
-          } on RangeError {
-            throw new RequestFailure(new Response(id,
-                error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
-                    'Invalid overlay change')));
-          }
-        } else if (change is RemoveContentOverlay) {
-          newContents = null;
-        } else {
-          // Protocol parsing should have ensured that we never get here.
-          throw new AnalysisException('Illegal change type');
-        }
-
-        fileContentOverlay[file] = newContents;
-
-        driverMap.values.forEach((driver) {
-          driver.changeFile(file);
-        });
-
-        // temporary plugin support:
-        _onFileChangedController.add(file);
-
-        // If the file did not exist, and is "overlay only", it still should be
-        // analyzed. Add it to driver to which it should have been added.
-        contextManager.getDriverFor(file)?.addFile(file);
-
-        // TODO(scheglov) implement other cases
-      });
-      return;
-    }
     changes.forEach((file, change) {
-      ContextSourcePair contextSource = getContextSourcePair(file);
-      Source source = contextSource.source;
-      operationQueue.sourceAboutToChange(source);
       // Prepare the new contents.
-      String oldContents = overlayState.getContents(source);
+      String oldContents = fileContentOverlay[file];
       String newContents;
       if (change is AddContentOverlay) {
         newContents = change.content;
@@ -1651,79 +1236,20 @@
         throw new AnalysisException('Illegal change type');
       }
 
-      AnalysisContext containingContext = getContainingContext(file);
+      fileContentOverlay[file] = newContents;
 
-      // Check for an implicitly added but missing source.
-      // (For example, the target of an import might not exist yet.)
-      // We need to do this before setContents, which changes the stamp.
-      bool wasMissing = containingContext?.getModificationStamp(source) == -1;
+      driverMap.values.forEach((driver) {
+        driver.changeFile(file);
+      });
 
-      overlayState.setContents(source, newContents);
-      // If the source does not exist, then it was an overlay-only one.
-      // Remove it from contexts.
-      if (newContents == null && !source.exists()) {
-        for (InternalAnalysisContext context in analysisContexts) {
-          List<Source> sources = context.getSourcesWithFullName(file);
-          ChangeSet changeSet = new ChangeSet();
-          sources.forEach(changeSet.removedSource);
-          context.applyChanges(changeSet);
-          schedulePerformAnalysisOperation(context);
-        }
-        return;
-      }
-      // Update all contexts.
-      bool anyContextUpdated = false;
-      for (InternalAnalysisContext context in analysisContexts) {
-        List<Source> sources = context.getSourcesWithFullName(file);
-        sources.forEach((Source source) {
-          anyContextUpdated = true;
-          if (context == containingContext && wasMissing) {
-            // Promote missing source to an explicitly added Source.
-            context.applyChanges(new ChangeSet()..addedSource(source));
-            schedulePerformAnalysisOperation(context);
-          }
-          if (context.handleContentsChanged(
-              source, oldContents, newContents, true)) {
-            schedulePerformAnalysisOperation(context);
-          } else {
-            // When the client sends any change for a source, we should resend
-            // subscribed notifications, even if there were no changes in the
-            // source contents.
-            // TODO(scheglov) consider checking if there are subscriptions.
-            if (AnalysisEngine.isDartFileName(file)) {
-              List<CompilationUnit> dartUnits =
-                  context.ensureResolvedDartUnits(source);
-              if (dartUnits != null) {
-                AnalysisErrorInfo errorInfo = context.getErrors(source);
-                for (var dartUnit in dartUnits) {
-                  scheduleNotificationOperations(
-                      this,
-                      source,
-                      file,
-                      errorInfo.lineInfo,
-                      context,
-                      null,
-                      dartUnit,
-                      errorInfo.errors);
-                  scheduleIndexOperation(this, file, dartUnit);
-                }
-              } else {
-                schedulePerformAnalysisOperation(context);
-              }
-            }
-          }
-        });
-      }
-      // The source is not analyzed by any context, add to the containing one.
-      if (!anyContextUpdated) {
-        AnalysisContext context = contextSource.context;
-        if (context != null && source != null) {
-          ChangeSet changeSet = new ChangeSet();
-          changeSet.addedSource(source);
-          context.applyChanges(changeSet);
-          schedulePerformAnalysisOperation(context);
-        }
-      }
+      // temporary plugin support:
+      _onFileChangedController.add(file);
+
+      // If the file did not exist, and is "overlay only", it still should be
+      // analyzed. Add it to driver to which it should have been added.
+      contextManager.getDriverFor(file)?.addFile(file);
+
+      // TODO(scheglov) implement other cases
     });
   }
 
@@ -1732,29 +1258,26 @@
    * existing analysis context.
    */
   void updateOptions(List<OptionUpdater> optionUpdaters) {
-    if (options.enableNewAnalysisDriver) {
-      // TODO(scheglov) implement for the new analysis driver
-      return;
-    }
-    //
-    // Update existing contexts.
-    //
-    for (AnalysisContext context in analysisContexts) {
-      AnalysisOptionsImpl options =
-          new AnalysisOptionsImpl.from(context.analysisOptions);
-      optionUpdaters.forEach((OptionUpdater optionUpdater) {
-        optionUpdater(options);
-      });
-      context.analysisOptions = options;
-      // TODO(brianwilkerson) As far as I can tell, this doesn't cause analysis
-      // to be scheduled for this context.
-    }
-    //
-    // Update the defaults used to create new contexts.
-    //
-    optionUpdaters.forEach((OptionUpdater optionUpdater) {
-      optionUpdater(defaultContextOptions);
-    });
+    // TODO(scheglov) implement for the new analysis driver
+//    //
+//    // Update existing contexts.
+//    //
+//    for (AnalysisContext context in analysisContexts) {
+//      AnalysisOptionsImpl options =
+//          new AnalysisOptionsImpl.from(context.analysisOptions);
+//      optionUpdaters.forEach((OptionUpdater optionUpdater) {
+//        optionUpdater(options);
+//      });
+//      context.analysisOptions = options;
+//      // TODO(brianwilkerson) As far as I can tell, this doesn't cause analysis
+//      // to be scheduled for this context.
+//    }
+//    //
+//    // Update the defaults used to create new contexts.
+//    //
+//    optionUpdaters.forEach((OptionUpdater optionUpdater) {
+//      optionUpdater(defaultContextOptions);
+//    });
   }
 
   void _computingPackageMap(bool computing) {
@@ -1812,29 +1335,6 @@
     return contexts;
   }
 
-  /**
-   * Returns the [CompilationUnit] of the Dart file with the given [source] that
-   * should be used to resend notifications for already resolved unit.
-   * Returns `null` if the file is not a part of any context, library has not
-   * been yet resolved, or any problem happened.
-   */
-  CompilationUnit _getResolvedCompilationUnitToResendNotification(
-      AnalysisContext context, Source source) {
-    List<Source> librarySources = context.getLibrariesContaining(source);
-    if (librarySources.isEmpty) {
-      return null;
-    }
-    // if library has not been resolved yet, the unit will be resolved later
-    Source librarySource = librarySources[0];
-    if (context.getResult(librarySource, LIBRARY_ELEMENT6) == null) {
-      return null;
-    }
-    // if library has been already resolved, resolve unit
-    return runWithActiveContext(context, () {
-      return context.resolveCompilationUnit2(source, librarySource);
-    });
-  }
-
   bool _hasAnalysisServiceSubscription(AnalysisService service, String file) {
     return analysisServices[service]?.contains(file) ?? false;
   }
@@ -1886,29 +1386,32 @@
       return;
     }
     onContextsChanged.listen((ContextsChangedEvent event) {
-      for (AnalysisContext context in event.added) {
-        context
-            .onResultChanged(RESOLVED_UNIT3)
-            .listen((ResultChangedEvent event) {
-          if (event.wasComputed) {
-            Object value = event.value;
-            if (value is CompilationUnit) {
-              index.indexDeclarations(value);
-            }
-          }
-        });
-        context
-            .onResultChanged(RESOLVED_UNIT)
-            .listen((ResultChangedEvent event) {
-          if (event.wasInvalidated) {
-            LibrarySpecificUnit target = event.target;
-            index.removeUnit(event.context, target.library, target.unit);
-          }
-        });
-      }
-      for (AnalysisContext context in event.removed) {
-        index.removeContext(context);
-      }
+      // TODO(brianwilkerson) `onContextsChanged` should never have anything
+      // written to it. Figure out whether we need something like this under the
+      // new analysis driver, and remove this method if not.
+//      for (AnalysisContext context in event.added) {
+//        context
+//            .onResultChanged(RESOLVED_UNIT3)
+//            .listen((ResultChangedEvent event) {
+//          if (event.wasComputed) {
+//            Object value = event.value;
+//            if (value is CompilationUnit) {
+//              index.indexDeclarations(value);
+//            }
+//          }
+//        });
+//        context
+//            .onResultChanged(RESOLVED_UNIT)
+//            .listen((ResultChangedEvent event) {
+//          if (event.wasInvalidated) {
+//            LibrarySpecificUnit target = event.target;
+//            index.removeUnit(event.context, target.library, target.unit);
+//          }
+//        });
+//      }
+//      for (AnalysisContext context in event.removed) {
+//        index.removeContext(context);
+//      }
     });
   }
 }
@@ -1916,7 +1419,6 @@
 class AnalysisServerOptions {
   bool enableIncrementalResolutionApi = false;
   bool enableIncrementalResolutionValidation = false;
-  bool enableNewAnalysisDriver = false;
   bool useAnalysisHighlight2 = false;
   String fileReadMode = 'as-is';
   String newAnalysisDriverLog;
@@ -2095,35 +1597,21 @@
 
   @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
-    if (analysisServer.options.enableNewAnalysisDriver) {
-      nd.AnalysisDriver analysisDriver =
-          analysisServer.driverMap[contextFolder];
-      if (analysisDriver != null) {
-        changeSet.addedSources.forEach((source) {
-          analysisDriver.addFile(source.fullName);
-          // temporary plugin support:
-          analysisServer._onFileAddedController.add(source.fullName);
-        });
-        changeSet.changedSources.forEach((source) {
-          analysisDriver.changeFile(source.fullName);
-          // temporary plugin support:
-          analysisServer._onFileChangedController.add(source.fullName);
-        });
-        changeSet.removedSources.forEach((source) {
-          analysisDriver.removeFile(source.fullName);
-        });
-      }
-    } else {
-      AnalysisContext context = analysisServer.folderMap[contextFolder];
-      if (context != null) {
-        context.applyChanges(changeSet);
-        analysisServer.schedulePerformAnalysisOperation(context);
-        List<String> flushedFiles = new List<String>();
-        for (Source source in changeSet.removedSources) {
-          flushedFiles.add(source.fullName);
-        }
-        sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
-      }
+    nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
+    if (analysisDriver != null) {
+      changeSet.addedSources.forEach((source) {
+        analysisDriver.addFile(source.fullName);
+        // temporary plugin support:
+        analysisServer._onFileAddedController.add(source.fullName);
+      });
+      changeSet.changedSources.forEach((source) {
+        analysisDriver.changeFile(source.fullName);
+        // temporary plugin support:
+        analysisServer._onFileChangedController.add(source.fullName);
+      });
+      changeSet.removedSources.forEach((source) {
+        analysisDriver.removeFile(source.fullName);
+      });
     }
   }
 
@@ -2184,21 +1672,9 @@
 
   @override
   void removeContext(Folder folder, List<String> flushedFiles) {
-    if (analysisServer.options.enableNewAnalysisDriver) {
-      sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
-      nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder);
-      driver.dispose();
-    } else {
-      AnalysisContext context = analysisServer.folderMap.remove(folder);
-      sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
-
-      analysisServer.operationQueue.contextRemoved(context);
-      analysisServer._onContextsChangedController
-          .add(new ContextsChangedEvent(removed: [context]));
-      analysisServer.sendContextAnalysisDoneNotifications(
-          context, AnalysisDoneReason.CONTEXT_REMOVED);
-      context.dispose();
-    }
+    sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
+    nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder);
+    driver.dispose();
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index db0b06e..2f115f6 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -18,7 +18,6 @@
 import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/source/sdk_ext.dart';
 import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/context/context.dart' as context;
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -529,8 +528,6 @@
    */
   final InstrumentationService _instrumentationService;
 
-  final bool enableNewAnalysisDriver;
-
   @override
   ContextManagerCallbacks callbacks;
 
@@ -545,12 +542,6 @@
       new HashMap<Folder, AnalysisDriver>();
 
   /**
-   * A table mapping [Folder]s to the [AnalysisContext]s associated with them.
-   */
-  final Map<Folder, AnalysisContext> _folderMap =
-      new HashMap<Folder, AnalysisContext>();
-
-  /**
    * Stream subscription we are using to watch each analysis root directory for
    * changes.
    */
@@ -564,8 +555,7 @@
       this._packageMapProvider,
       this.analyzedFilesGlobs,
       this._instrumentationService,
-      this.defaultContextOptions,
-      this.enableNewAnalysisDriver) {
+      this.defaultContextOptions) {
     absolutePathContext = resourceProvider.absolutePathContext;
     pathContext = resourceProvider.pathContext;
   }
@@ -574,11 +564,7 @@
   Iterable<AnalysisContext> get analysisContexts => folderMap.values;
 
   Map<Folder, AnalysisContext> get folderMap {
-    if (enableNewAnalysisDriver) {
-      throw new StateError('Should not be used with the new analysis driver');
-    } else {
-      return _folderMap;
-    }
+    throw new StateError('Should not be used with the new analysis driver');
   }
 
   @override
@@ -1008,29 +994,15 @@
   void _checkForAnalysisOptionsUpdate(
       String path, ContextInfo info, ChangeType changeType) {
     if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
-      if (enableNewAnalysisDriver) {
-        AnalysisDriver driver = info.analysisDriver;
-        String contextRoot = info.folder.path;
-        ContextBuilder builder =
-            callbacks.createContextBuilder(info.folder, defaultContextOptions);
-        AnalysisOptions options = builder.getAnalysisOptions(contextRoot,
-            contextRoot: driver.contextRoot);
-        SourceFactory factory =
-            builder.createSourceFactory(contextRoot, options);
-        driver.configure(analysisOptions: options, sourceFactory: factory);
-        // TODO(brianwilkerson) Set exclusion patterns.
-      } else {
-        var analysisContext = info.context;
-        if (analysisContext is context.AnalysisContextImpl) {
-          Map<String, Object> options =
-              readOptions(info.folder, info.disposition.packages);
-          processOptionsForContext(info, options,
-              optionsRemoved: changeType == ChangeType.REMOVE);
-          analysisContext.sourceFactory = _createSourceFactory(
-              analysisContext, analysisContext.analysisOptions, info.folder);
-          callbacks.applyChangesToContext(info.folder, new ChangeSet());
-        }
-      }
+      AnalysisDriver driver = info.analysisDriver;
+      String contextRoot = info.folder.path;
+      ContextBuilder builder =
+          callbacks.createContextBuilder(info.folder, defaultContextOptions);
+      AnalysisOptions options = builder.getAnalysisOptions(contextRoot,
+          contextRoot: driver.contextRoot);
+      SourceFactory factory = builder.createSourceFactory(contextRoot, options);
+      driver.configure(analysisOptions: options, sourceFactory: factory);
+      // TODO(brianwilkerson) Set exclusion patterns.
     }
   }
 
@@ -1045,13 +1017,8 @@
       AnalysisOptions options = builder.getAnalysisOptions(contextRoot,
           contextRoot: info.analysisDriver?.contextRoot);
       SourceFactory factory = builder.createSourceFactory(contextRoot, options);
-      if (enableNewAnalysisDriver) {
-        AnalysisDriver driver = info.analysisDriver;
-        driver.configure(analysisOptions: options, sourceFactory: factory);
-      } else {
-        info.context.analysisOptions = options;
-        info.context.sourceFactory = factory;
-      }
+      AnalysisDriver driver = info.analysisDriver;
+      driver.configure(analysisOptions: options, sourceFactory: factory);
     }
   }
 
@@ -1062,31 +1029,14 @@
    * file.)
    */
   List<String> _computeFlushedFiles(ContextInfo info) {
-    if (enableNewAnalysisDriver) {
-      Set<String> flushedFiles = info.analysisDriver.addedFiles.toSet();
-      for (ContextInfo contextInfo in rootInfo.descendants) {
-        AnalysisDriver other = contextInfo.analysisDriver;
-        if (other != info.analysisDriver) {
-          flushedFiles.removeAll(other.addedFiles);
-        }
+    Set<String> flushedFiles = info.analysisDriver.addedFiles.toSet();
+    for (ContextInfo contextInfo in rootInfo.descendants) {
+      AnalysisDriver other = contextInfo.analysisDriver;
+      if (other != info.analysisDriver) {
+        flushedFiles.removeAll(other.addedFiles);
       }
-      return flushedFiles.toList(growable: false);
-    } else {
-      AnalysisContext context = info.context;
-      HashSet<String> flushedFiles = new HashSet<String>();
-      for (Source source in context.sources) {
-        flushedFiles.add(source.fullName);
-      }
-      for (ContextInfo contextInfo in rootInfo.descendants) {
-        AnalysisContext contextN = contextInfo.context;
-        if (context != contextN) {
-          for (Source source in contextN.sources) {
-            flushedFiles.remove(source.fullName);
-          }
-        }
-      }
-      return flushedFiles.toList(growable: false);
     }
+    return flushedFiles.toList(growable: false);
   }
 
   /**
@@ -1187,22 +1137,14 @@
     applyToAnalysisOptions(options, optionMap);
 
     info.setDependencies(dependencies);
-    if (enableNewAnalysisDriver) {
-      String includedPath = folder.path;
-      List<String> containedExcludedPaths = excludedPaths
-          .where((String excludedPath) =>
-              pathContext.isWithin(includedPath, excludedPath))
-          .toList();
-      processOptionsForDriver(info, options, optionMap);
-      info.analysisDriver = callbacks.addAnalysisDriver(folder,
-          new ContextRoot(folder.path, containedExcludedPaths), options);
-    } else {
-      info.context = callbacks.addContext(folder, options);
-      _folderMap[folder] = info.context;
-      info.context.name = folder.path;
-      processOptionsForContext(info, optionMap);
-    }
-
+    String includedPath = folder.path;
+    List<String> containedExcludedPaths = excludedPaths
+        .where((String excludedPath) =>
+            pathContext.isWithin(includedPath, excludedPath))
+        .toList();
+    processOptionsForDriver(info, options, optionMap);
+    info.analysisDriver = callbacks.addAnalysisDriver(
+        folder, new ContextRoot(folder.path, containedExcludedPaths), options);
     return info;
   }
 
@@ -1470,15 +1412,7 @@
         if (resource is File) {
           File file = resource;
           if (_shouldFileBeAnalyzed(file)) {
-            if (enableNewAnalysisDriver) {
-              info.analysisDriver.addFile(path);
-            } else {
-              ChangeSet changeSet = new ChangeSet();
-              Source source = createSourceInContext(info.context, file);
-              changeSet.addedSource(source);
-              callbacks.applyChangesToContext(info.folder, changeSet);
-              info.sources[path] = source;
-            }
+            info.analysisDriver.addFile(path);
           }
         }
         break;
@@ -1515,34 +1449,11 @@
           }
         }
 
-        if (enableNewAnalysisDriver) {
-          callbacks.applyFileRemoved(info.analysisDriver, path);
-        } else {
-          List<Source> sources = info.context.getSourcesWithFullName(path);
-          if (!sources.isEmpty) {
-            ChangeSet changeSet = new ChangeSet();
-            sources.forEach((Source source) {
-              changeSet.removedSource(source);
-            });
-            callbacks.applyChangesToContext(info.folder, changeSet);
-            info.sources.remove(path);
-          }
-        }
+        callbacks.applyFileRemoved(info.analysisDriver, path);
         break;
       case ChangeType.MODIFY:
-        if (enableNewAnalysisDriver) {
-          for (AnalysisDriver driver in driverMap.values) {
-            driver.changeFile(path);
-          }
-        } else {
-          List<Source> sources = info.context.getSourcesWithFullName(path);
-          if (!sources.isEmpty) {
-            ChangeSet changeSet = new ChangeSet();
-            sources.forEach((Source source) {
-              changeSet.changedSource(source);
-            });
-            callbacks.applyChangesToContext(info.folder, changeSet);
-          }
+        for (AnalysisDriver driver in driverMap.values) {
+          driver.changeFile(path);
         }
         break;
     }
@@ -1702,18 +1613,11 @@
   }
 
   void _updateContextPackageUriResolver(Folder contextFolder) {
-    if (enableNewAnalysisDriver) {
-      ContextInfo info = getContextInfoFor(contextFolder);
-      AnalysisDriver driver = info.analysisDriver;
-      SourceFactory sourceFactory =
-          _createSourceFactory(null, driver.analysisOptions, contextFolder);
-      driver.configure(sourceFactory: sourceFactory);
-    } else {
-      AnalysisContext context = folderMap[contextFolder];
-      context.sourceFactory =
-          _createSourceFactory(context, context.analysisOptions, contextFolder);
-      callbacks.updateContextPackageUriResolver(context);
-    }
+    ContextInfo info = getContextInfoFor(contextFolder);
+    AnalysisDriver driver = info.analysisDriver;
+    SourceFactory sourceFactory =
+        _createSourceFactory(null, driver.analysisOptions, contextFolder);
+    driver.configure(sourceFactory: sourceFactory);
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 512a2a9..2351ef6 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -21,9 +21,7 @@
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
-import 'package:analysis_server/src/services/dependencies/reachable_source_collector.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -66,44 +64,18 @@
       }
     }
 
-    if (server.options.enableNewAnalysisDriver) {
-      var result = await server.getAnalysisResult(file);
+    AnalysisResult result = await server.getAnalysisResult(file);
 
-      if (server.onResultErrorSupplementor != null) {
-        if (result != null) {
-          await server.onResultErrorSupplementor(file, result.errors);
-        } else {
-          server.onNoAnalysisResult(file, send);
-          return;
-        }
+    if (server.onResultErrorSupplementor != null) {
+      if (result != null) {
+        await server.onResultErrorSupplementor(file, result.errors);
+      } else {
+        server.onNoAnalysisResult(file, send);
+        return;
       }
-
-      send(result?.driver?.analysisOptions, result?.lineInfo, result?.errors);
-      return;
     }
 
-    Future<AnalysisDoneReason> completionFuture =
-        server.onFileAnalysisComplete(file);
-    if (completionFuture == null) {
-      server.sendResponse(new Response.getErrorsInvalidFile(request));
-    }
-    completionFuture.then((AnalysisDoneReason reason) async {
-      switch (reason) {
-        case AnalysisDoneReason.COMPLETE:
-          engine.AnalysisErrorInfo errorInfo = server.getErrors(file);
-          if (errorInfo == null) {
-            server.sendResponse(new Response.getErrorsInvalidFile(request));
-          } else {
-            engine.AnalysisContext context = server.getAnalysisContext(file);
-            send(context.analysisOptions, errorInfo.lineInfo, errorInfo.errors);
-          }
-          break;
-        case AnalysisDoneReason.CONTEXT_REMOVED:
-          // The active contexts have changed, so try again.
-          await getErrors(request);
-          break;
-      }
-    });
+    send(result?.driver?.analysisOptions, result?.lineInfo, result?.errors);
   }
 
   /**
@@ -113,13 +85,8 @@
     var params = new AnalysisGetHoverParams.fromRequest(request);
 
     // Prepare the resolved units.
-    CompilationUnit unit;
-    if (server.options.enableNewAnalysisDriver) {
-      AnalysisResult result = await server.getAnalysisResult(params.file);
-      unit = result?.unit;
-    } else {
-      unit = await server.getResolvedCompilationUnit(params.file);
-    }
+    AnalysisResult result = await server.getAnalysisResult(params.file);
+    CompilationUnit unit = result?.unit;
 
     // Prepare the hovers.
     List<HoverInformation> hovers = <HoverInformation>[];
@@ -163,117 +130,80 @@
     int offset = params.offset;
     int length = params.length;
 
-    if (server.options.enableNewAnalysisDriver) {
-      AnalysisDriver driver = server.getAnalysisDriver(file);
-      if (driver == null) {
-        server.sendResponse(new Response.getNavigationInvalidFile(request));
-      } else {
-        //
-        // Allow plugins to start computing navigation data.
-        //
-        plugin.AnalysisGetNavigationParams requestParams =
-            new plugin.AnalysisGetNavigationParams(file, offset, length);
-        Map<PluginInfo, Future<plugin.Response>> pluginFutures = server
-            .pluginManager
-            .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
-        //
-        // Compute navigation data generated by server.
-        //
-        List<AnalysisNavigationParams> allResults =
-            <AnalysisNavigationParams>[];
-        AnalysisResult result = await server.getAnalysisResult(file);
-        CompilationUnit unit = result?.unit;
-        if (unit != null && result.exists) {
-          NavigationCollectorImpl collector = new NavigationCollectorImpl();
-          computeDartNavigation(collector, unit, offset, length);
-          collector.createRegions();
-          allResults.add(new AnalysisNavigationParams(
-              file, collector.regions, collector.targets, collector.files));
-        }
-        //
-        // Add the navigation data produced by plugins to the server-generated
-        // navigation data.
-        //
-        if (pluginFutures != null) {
-          List<plugin.Response> responses = await waitForResponses(
-              pluginFutures,
-              requestParameters: requestParams);
-          for (plugin.Response response in responses) {
-            plugin.AnalysisGetNavigationResult result =
-                new plugin.AnalysisGetNavigationResult.fromResponse(response);
-            allResults.add(new AnalysisNavigationParams(
-                file, result.regions, result.targets, result.files));
-          }
-        }
-        //
-        // Return the result.
-        //
-        ResultMerger merger = new ResultMerger();
-        AnalysisNavigationParams mergedResults =
-            merger.mergeNavigation(allResults);
-        if (mergedResults == null) {
-          server.sendResponse(new AnalysisGetNavigationResult(
-                  <String>[], <NavigationTarget>[], <NavigationRegion>[])
-              .toResponse(request.id));
-        } else {
-          server.sendResponse(new AnalysisGetNavigationResult(
-                  mergedResults.files,
-                  mergedResults.targets,
-                  mergedResults.regions)
-              .toResponse(request.id));
-        }
-      }
-      return;
-    }
-
-    Future<AnalysisDoneReason> analysisFuture =
-        server.onFileAnalysisComplete(file);
-    if (analysisFuture == null) {
+    AnalysisDriver driver = server.getAnalysisDriver(file);
+    if (driver == null) {
       server.sendResponse(new Response.getNavigationInvalidFile(request));
-      return;
-    }
-    analysisFuture.then((AnalysisDoneReason reason) async {
-      switch (reason) {
-        case AnalysisDoneReason.COMPLETE:
-          CompilationUnit unit = await server.getResolvedCompilationUnit(file);
-          if (unit == null) {
-            server.sendResponse(new Response.getNavigationInvalidFile(request));
-          } else {
-            CompilationUnitElement unitElement = unit.element;
-            NavigationCollectorImpl collector = computeNavigation(
-                server,
-                unitElement.context,
-                unitElement.source,
-                params.offset,
-                params.length);
-            server.sendResponse(new AnalysisGetNavigationResult(
-                    collector.files, collector.targets, collector.regions)
-                .toResponse(request.id));
-          }
-          break;
-        case AnalysisDoneReason.CONTEXT_REMOVED:
-          // The active contexts have changed, so try again.
-          await getNavigation(request);
-          break;
+    } else {
+      //
+      // Allow plugins to start computing navigation data.
+      //
+      plugin.AnalysisGetNavigationParams requestParams =
+          new plugin.AnalysisGetNavigationParams(file, offset, length);
+      Map<PluginInfo, Future<plugin.Response>> pluginFutures = server
+          .pluginManager
+          .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
+      //
+      // Compute navigation data generated by server.
+      //
+      List<AnalysisNavigationParams> allResults = <AnalysisNavigationParams>[];
+      AnalysisResult result = await server.getAnalysisResult(file);
+      CompilationUnit unit = result?.unit;
+      if (unit != null && result.exists) {
+        NavigationCollectorImpl collector = new NavigationCollectorImpl();
+        computeDartNavigation(collector, unit, offset, length);
+        collector.createRegions();
+        allResults.add(new AnalysisNavigationParams(
+            file, collector.regions, collector.targets, collector.files));
       }
-    });
+      //
+      // Add the navigation data produced by plugins to the server-generated
+      // navigation data.
+      //
+      if (pluginFutures != null) {
+        List<plugin.Response> responses = await waitForResponses(pluginFutures,
+            requestParameters: requestParams);
+        for (plugin.Response response in responses) {
+          plugin.AnalysisGetNavigationResult result =
+              new plugin.AnalysisGetNavigationResult.fromResponse(response);
+          allResults.add(new AnalysisNavigationParams(
+              file, result.regions, result.targets, result.files));
+        }
+      }
+      //
+      // Return the result.
+      //
+      ResultMerger merger = new ResultMerger();
+      AnalysisNavigationParams mergedResults =
+          merger.mergeNavigation(allResults);
+      if (mergedResults == null) {
+        server.sendResponse(new AnalysisGetNavigationResult(
+                <String>[], <NavigationTarget>[], <NavigationRegion>[])
+            .toResponse(request.id));
+      } else {
+        server.sendResponse(new AnalysisGetNavigationResult(mergedResults.files,
+                mergedResults.targets, mergedResults.regions)
+            .toResponse(request.id));
+      }
+    }
   }
 
   /**
    * Implement the `analysis.getReachableSources` request.
    */
   Response getReachableSources(Request request) {
-    AnalysisGetReachableSourcesParams params =
-        new AnalysisGetReachableSourcesParams.fromRequest(request);
-    ContextSourcePair pair = server.getContextSourcePair(params.file);
-    if (pair.context == null || pair.source == null) {
-      return new Response.getReachableSourcesInvalidFile(request);
-    }
-    Map<String, List<String>> sources =
-        new ReachableSourceCollector(pair.source, pair.context)
-            .collectSources();
-    return new AnalysisGetReachableSourcesResult(sources)
-        .toResponse(request.id);
+    return new Response.unsupportedFeature(request.id,
+        'Please contact the Dart analyzer team if you need this request.');
+//    AnalysisGetReachableSourcesParams params =
+//        new AnalysisGetReachableSourcesParams.fromRequest(request);
+//    ContextSourcePair pair = server.getContextSourcePair(params.file);
+//    if (pair.context == null || pair.source == null) {
+//      return new Response.getReachableSourcesInvalidFile(request);
+//    }
+//    Map<String, List<String>> sources =
+//        new ReachableSourceCollector(pair.source, pair.context)
+//            .collectSources();
+//    return new AnalysisGetReachableSourcesResult(sources)
+//        .toResponse(request.id);
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
index 8e6027a..16aa7a9 100644
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/domain_diagnostic.dart
@@ -37,14 +37,8 @@
 
   /// Answer the `diagnostic.getDiagnostics` request.
   Response computeDiagnostics(Request request) {
-    List<ContextData> contexts = <ContextData>[];
-    if (server.options.enableNewAnalysisDriver) {
-      contexts = server.driverMap.values.map(extractDataFromDriver).toList();
-    } else {
-      for (AnalysisContext context in server.analysisContexts) {
-        contexts.add(extractDataFromContext(context));
-      }
-    }
+    List<ContextData> contexts =
+        server.driverMap.values.map(extractDataFromDriver).toList();
     return new DiagnosticGetDiagnosticsResult(contexts).toResponse(request.id);
   }
 
diff --git a/pkg/analysis_server/lib/src/domain_execution.dart b/pkg/analysis_server/lib/src/domain_execution.dart
index 3a9161c..801979e 100644
--- a/pkg/analysis_server/lib/src/domain_execution.dart
+++ b/pkg/analysis_server/lib/src/domain_execution.dart
@@ -12,7 +12,6 @@
 import 'package:analysis_server/src/constants.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
@@ -98,21 +97,11 @@
           'There is no execution context with an id of $contextId');
     }
 
-    SourceFactory sourceFactory;
-    AnalysisDriver driver;
-    if (server.options.enableNewAnalysisDriver) {
-      driver = server.getAnalysisDriver(path);
-      if (driver == null) {
-        return new Response.invalidExecutionContext(request, contextId);
-      }
-      sourceFactory = driver.sourceFactory;
-    } else {
-      AnalysisContext context = server.getContainingContext(path);
-      if (context == null) {
-        return new Response.invalidExecutionContext(request, contextId);
-      }
-      sourceFactory = context.sourceFactory;
+    AnalysisDriver driver = server.getAnalysisDriver(path);
+    if (driver == null) {
+      return new Response.invalidExecutionContext(request, contextId);
     }
+    SourceFactory sourceFactory = driver.sourceFactory;
 
     String file = params.file;
     String uri = params.uri;
@@ -129,13 +118,7 @@
             request, 'file', 'Must not refer to a directory');
       }
 
-      Source source;
-      if (server.options.enableNewAnalysisDriver) {
-        source = driver.fsState.getFileForPath(file).source;
-      } else {
-        ContextSourcePair contextSource = server.getContextSourcePair(file);
-        source = contextSource.source;
-      }
+      Source source = driver.fsState.getFileForPath(file).source;
       if (source.uriKind != UriKind.FILE_URI) {
         uri = source.uri.toString();
       } else {
@@ -158,112 +141,7 @@
    * Implement the 'execution.setSubscriptions' request.
    */
   Response setSubscriptions(Request request) {
-    if (server.options.enableNewAnalysisDriver) {
-      // Under the analysis driver, setSubscriptions() becomes a no-op.
-      return new ExecutionSetSubscriptionsResult().toResponse(request.id);
-    } else {
-      List<ExecutionService> subscriptions =
-          new ExecutionSetSubscriptionsParams.fromRequest(request)
-              .subscriptions;
-      if (subscriptions.contains(ExecutionService.LAUNCH_DATA)) {
-        if (onFileAnalyzed == null) {
-          onFileAnalyzed = server.onFileAnalyzed.listen(_fileAnalyzed);
-          _reportCurrentFileStatus();
-        }
-      } else {
-        if (onFileAnalyzed != null) {
-          onFileAnalyzed.cancel();
-          onFileAnalyzed = null;
-        }
-      }
-      return new ExecutionSetSubscriptionsResult().toResponse(request.id);
-    }
-  }
-
-  void _fileAnalyzed(ChangeNotice notice) {
-    ServerPerformanceStatistics.executionNotifications.makeCurrentWhile(() {
-      Source source = notice.source;
-      String filePath = source.fullName;
-      // check files
-      bool isDartFile = notice.resolvedDartUnit != null;
-      if (!isDartFile) {
-        return;
-      }
-      // prepare context
-      AnalysisContext context = server.getContainingContext(filePath);
-      if (context == null) {
-        return;
-      }
-      // analyze the file
-      if (isDartFile) {
-        ExecutableKind kind = ExecutableKind.NOT_EXECUTABLE;
-        if (context.isClientLibrary(source)) {
-          kind = ExecutableKind.CLIENT;
-          if (context.isServerLibrary(source)) {
-            kind = ExecutableKind.EITHER;
-          }
-        } else if (context.isServerLibrary(source)) {
-          kind = ExecutableKind.SERVER;
-        }
-        server.sendNotification(
-            new ExecutionLaunchDataParams(filePath, kind: kind)
-                .toNotification());
-      }
-    });
-  }
-
-  /**
-   * Return `true` if the given [filePath] represents a file that is in an
-   * analysis root.
-   */
-  bool _isInAnalysisRoot(String filePath) =>
-      server.contextManager.isInAnalysisRoot(filePath);
-
-  void _reportCurrentFileStatus() {
-    for (AnalysisContext context in server.analysisContexts) {
-      List<Source> librarySources = context.librarySources;
-      List<Source> clientSources = context.launchableClientLibrarySources;
-      List<Source> serverSources = context.launchableServerLibrarySources;
-      for (Source source in clientSources) {
-        if (serverSources.remove(source)) {
-          _sendKindNotification(source.fullName, ExecutableKind.EITHER);
-        } else {
-          _sendKindNotification(source.fullName, ExecutableKind.CLIENT);
-        }
-        librarySources.remove(source);
-      }
-      for (Source source in serverSources) {
-        _sendKindNotification(source.fullName, ExecutableKind.SERVER);
-        librarySources.remove(source);
-      }
-      for (Source source in librarySources) {
-        _sendKindNotification(source.fullName, ExecutableKind.NOT_EXECUTABLE);
-      }
-      for (Source source in context.htmlSources) {
-        String filePath = source.fullName;
-        if (_isInAnalysisRoot(filePath)) {
-          List<Source> libraries =
-              context.getLibrariesReferencedFromHtml(source);
-          server.sendNotification(new ExecutionLaunchDataParams(filePath,
-                  referencedFiles: _getFullNames(libraries))
-              .toNotification());
-        }
-      }
-    }
-  }
-
-  /**
-   * Send a notification indicating the [kind] of the file with the given
-   * [filePath], but only if the file is in an analysis root.
-   */
-  void _sendKindNotification(String filePath, ExecutableKind kind) {
-    if (_isInAnalysisRoot(filePath)) {
-      server.sendNotification(
-          new ExecutionLaunchDataParams(filePath, kind: kind).toNotification());
-    }
-  }
-
-  static List<String> _getFullNames(List<Source> sources) {
-    return sources.map((Source source) => source.fullName).toList();
+    // Under the analysis driver, setSubscriptions() becomes a no-op.
+    return new ExecutionSetSubscriptionsResult().toResponse(request.id);
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 5395f19..db4f40d 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -36,7 +36,6 @@
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer/src/generated/parser.dart' as engine;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/task/dart.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
@@ -82,12 +81,8 @@
     String unformattedSource;
     try {
       Source source = server.resourceProvider.getFile(file).createSource();
-      if (server.options.enableNewAnalysisDriver) {
-        unformattedSource = server.fileContentOverlay[file];
-      } else {
-        unformattedSource = server.overlayState.getContents(source);
-      }
-      unformattedSource ??= source.contents.data;
+      unformattedSource =
+          server.fileContentOverlay[file] ?? source.contents.data;
     } catch (e) {
       return new Response.formatInvalidFile(request);
     }
@@ -345,37 +340,15 @@
       return;
     }
     // Prepare the file information.
-    int fileStamp;
-    String code;
-    CompilationUnit unit;
-    List<engine.AnalysisError> errors;
-    if (server.options.enableNewAnalysisDriver) {
-      AnalysisResult result = await server.getAnalysisResult(file);
-      if (result == null) {
-        server.sendResponse(new Response.fileNotAnalyzed(request, file));
-        return;
-      }
-      fileStamp = -1;
-      code = result.content;
-      unit = result.unit;
-      errors = result.errors;
-    } else {
-      // prepare resolved unit
-      unit = await server.getResolvedCompilationUnit(file);
-      if (unit == null) {
-        server.sendResponse(new Response.fileNotAnalyzed(request, file));
-        return;
-      }
-      // prepare context
-      CompilationUnitElement compilationUnitElement =
-          resolutionMap.elementDeclaredByCompilationUnit(unit);
-      engine.AnalysisContext context = compilationUnitElement.context;
-      Source source = compilationUnitElement.source;
-      errors = context.computeErrors(source);
-      // prepare code
-      fileStamp = context.getModificationStamp(source);
-      code = context.getContents(source).data;
+    AnalysisResult result = await server.getAnalysisResult(file);
+    if (result == null) {
+      server.sendResponse(new Response.fileNotAnalyzed(request, file));
+      return;
     }
+    int fileStamp = -1;
+    String code = result.content;
+    CompilationUnit unit = result.unit;
+    List<engine.AnalysisError> errors = result.errors;
     // check if there are scan/parse errors in the file
     int numScanParseErrors = _getNumberOfScanParseErrors(errors);
     if (numScanParseErrors != 0) {
@@ -400,43 +373,16 @@
       return;
     }
     // Prepare the file information.
-    int fileStamp;
-    String code;
-    CompilationUnit unit;
-    List<engine.AnalysisError> errors;
-    if (server.options.enableNewAnalysisDriver) {
-      AnalysisDriver driver = server.getAnalysisDriver(file);
-      ParseResult result = await driver?.parseFile(file);
-      if (result == null) {
-        server.sendResponse(new Response.fileNotAnalyzed(request, file));
-        return;
-      }
-      fileStamp = -1;
-      code = result.content;
-      unit = result.unit;
-      errors = result.errors;
-    } else {
-      // prepare location
-      ContextSourcePair contextSource = server.getContextSourcePair(file);
-      engine.AnalysisContext context = contextSource.context;
-      Source source = contextSource.source;
-      if (context == null || source == null) {
-        server.sendResponse(new Response.sortMembersInvalidFile(request));
-        return;
-      }
-      // prepare code
-      fileStamp = context.getModificationStamp(source);
-      code = context.getContents(source).data;
-      // prepare parsed unit
-      try {
-        unit = context.parseCompilationUnit(source);
-      } catch (e) {
-        server.sendResponse(new Response.sortMembersInvalidFile(request));
-        return;
-      }
-      // Get the errors.
-      errors = context.getErrors(source).errors;
+    AnalysisDriver driver = server.getAnalysisDriver(file);
+    ParseResult result = await driver?.parseFile(file);
+    if (result == null) {
+      server.sendResponse(new Response.fileNotAnalyzed(request, file));
+      return;
     }
+    int fileStamp = -1;
+    String code = result.content;
+    CompilationUnit unit = result.unit;
+    List<engine.AnalysisError> errors = result.errors;
     // Check if there are scan/parse errors in the file.
     int numScanParseErrors = _getNumberOfScanParseErrors(errors);
     if (numScanParseErrors != 0) {
@@ -713,32 +659,6 @@
     });
   }
 
-  /**
-   * Perform enough analysis to be able to perform refactoring of the given
-   * [kind] in the given [file].
-   */
-  Future<Null> _analyzeForRefactoring(String file, RefactoringKind kind) async {
-    if (server.options.enableNewAnalysisDriver) {
-      return;
-    }
-    // "Extract Local" and "Inline Local" refactorings need only local analysis.
-    if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE ||
-        kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
-      ContextSourcePair pair = server.getContextSourcePair(file);
-      engine.AnalysisContext context = pair.context;
-      Source source = pair.source;
-      if (context != null && source != null) {
-        if (context.computeResult(source, SOURCE_KIND) == SourceKind.LIBRARY) {
-          await context.computeResolvedCompilationUnitAsync(source, source);
-          return;
-        }
-      }
-    }
-    // A refactoring for which we cannot optimize analysis.
-    // So, wait for full analysis.
-    await server.onAnalysisComplete;
-  }
-
   void _checkForReset_afterCreateChange() {
     if (test_simulateRefactoringReset_afterCreateChange) {
       _reset();
@@ -772,7 +692,6 @@
    */
   Future _init(
       RefactoringKind kind, String file, int offset, int length) async {
-    await _analyzeForRefactoring(file, kind);
     // check if we can continue with the existing Refactoring instance
     if (this.kind == kind &&
         this.file == file &&
@@ -848,12 +767,13 @@
       }
     }
     if (kind == RefactoringKind.MOVE_FILE) {
-      _resetOnAnalysisStarted();
-      ContextSourcePair contextSource = server.getContextSourcePair(file);
-      engine.AnalysisContext context = contextSource.context;
-      Source source = contextSource.source;
-      refactoring = new MoveFileRefactoring(
-          server.resourceProvider, searchEngine, context, source, file);
+      // TODO(brianwilkerson) Re-implement this refactoring under the new analysis driver
+//      _resetOnAnalysisStarted();
+//      ContextSourcePair contextSource = server.getContextSourcePair(file);
+//      engine.AnalysisContext context = contextSource.context;
+//      Source source = contextSource.source;
+//      refactoring = new MoveFileRefactoring(
+//          server.resourceProvider, searchEngine, context, source, file);
     }
     if (kind == RefactoringKind.RENAME) {
       AstNode node = await server.getNodeAtOffset(file, offset);
@@ -953,19 +873,9 @@
    * But when any other file is changed or analyzed, we can continue.
    */
   void _resetOnFileResolutionChanged(String file) {
-    if (server.options.enableNewAnalysisDriver) {
-      return;
-    }
-    subscriptionToReset?.cancel();
-    subscriptionToReset = server
-        .getAnalysisContext(file)
-        ?.onResultChanged(RESOLVED_UNIT)
-        ?.listen((event) {
-      Source targetSource = event.target.source;
-      if (targetSource?.fullName == file) {
-        _reset();
-      }
-    });
+    // TODO(brianwilkerson) Decide whether we want to implement this
+    // functionality for the new analysis driver or whether we should remove
+    // this method.
   }
 
   void _sendResultResponse() {
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 4021eb0..2584dbd 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
+
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/computer/computer_highlights.dart';
 import 'package:analysis_server/src/computer/computer_highlights2.dart';
@@ -12,7 +14,6 @@
 import 'package:analysis_server/src/domains/analysis/occurrences.dart';
 import 'package:analysis_server/src/operation/operation.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
-import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -38,14 +39,15 @@
   }
 }
 
-scheduleImplementedNotification(
+Future<Null> scheduleImplementedNotification(
     AnalysisServer server, Iterable<String> files) async {
   SearchEngine searchEngine = server.searchEngine;
   if (searchEngine == null) {
     return;
   }
   for (String file in files) {
-    CompilationUnitElement unitElement = server.getCompilationUnitElement(file);
+    CompilationUnit unit = await server.getResolvedCompilationUnit(file);
+    CompilationUnitElement unitElement = unit?.element;
     if (unitElement != null) {
       try {
         ImplementedComputer computer =
@@ -133,17 +135,10 @@
 
 void sendAnalysisNotificationAnalyzedFiles(AnalysisServer server) {
   _sendNotification(server, () {
-    Set<String> analyzedFiles;
-    if (server.options.enableNewAnalysisDriver) {
-      analyzedFiles = server.driverMap.values
-          .map((driver) => driver.knownFiles)
-          .expand((files) => files)
-          .toSet();
-    } else {
-      LibraryDependencyCollector collector =
-          new LibraryDependencyCollector(server.analysisContexts.toList());
-      analyzedFiles = collector.collectLibraryDependencies();
-    }
+    Set<String> analyzedFiles = server.driverMap.values
+        .map((driver) => driver.knownFiles)
+        .expand((files) => files)
+        .toSet();
     Set<String> prevAnalyzedFiles = server.prevAnalyzedFiles;
     if (prevAnalyzedFiles != null &&
         prevAnalyzedFiles.length == analyzedFiles.length &&
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index ade2e9f..093c2da 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -46,11 +46,6 @@
  */
 abstract class DartCompletionRequest extends CompletionRequest {
   /**
-   * Return the dart:core library element
-   */
-  LibraryElement get coreLib;
-
-  /**
    * Return the expression to the right of the "dot" or "dot dot",
    * or `null` if this is not a "dot" completion (e.g. `foo.b`).
    */
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index 91fcb4d..ebb3245 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -51,9 +51,6 @@
         new protocol.SearchFindElementReferencesParams.fromRequest(request);
     String file = params.file;
     // prepare element
-    if (!server.options.enableNewAnalysisDriver) {
-      await server.onAnalysisComplete;
-    }
     Element element = await server.getElementAtOffset(file, params.offset);
     if (element is ImportElement) {
       element = (element as ImportElement).prefix;
@@ -141,14 +138,6 @@
   Future getTypeHierarchy(protocol.Request request) async {
     var params = new protocol.SearchGetTypeHierarchyParams.fromRequest(request);
     String file = params.file;
-    // wait for analysis
-    if (!server.options.enableNewAnalysisDriver) {
-      if (params.superOnly == true) {
-        await server.onFileAnalysisComplete(file);
-      } else {
-        await server.onAnalysisComplete;
-      }
-    }
     // prepare element
     Element element = await server.getElementAtOffset(file, params.offset);
     if (element == null) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 45a543c..30215da 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -241,12 +241,6 @@
       "incremental-resolution-validation";
 
   /**
-   * The name of the option used to disable using the new analysis driver.
-   */
-  static const String DISABLE_NEW_ANALYSIS_DRIVER =
-      'disable-new-analysis-driver';
-
-  /**
    * The name of the option used to cause instrumentation to also be written to
    * a local file.
    */
@@ -382,8 +376,6 @@
         results[ENABLE_INCREMENTAL_RESOLUTION_API];
     analysisServerOptions.enableIncrementalResolutionValidation =
         results[INCREMENTAL_RESOLUTION_VALIDATION];
-    analysisServerOptions.enableNewAnalysisDriver =
-        !results[DISABLE_NEW_ANALYSIS_DRIVER];
     analysisServerOptions.useAnalysisHighlight2 =
         results[USE_ANALYSIS_HIGHLIGHT2];
     analysisServerOptions.fileReadMode = results[FILE_READ_MODE];
@@ -421,12 +413,10 @@
           .defaultSdkDirectory(PhysicalResourceProvider.INSTANCE)
           .path;
     }
-    bool useSummaries = analysisServerOptions.fileReadMode == 'as-is' ||
-        analysisServerOptions.enableNewAnalysisDriver;
     // TODO(brianwilkerson) It would be nice to avoid creating an SDK that
     // cannot be re-used, but the SDK is needed to create a package map provider
     // in the case where we need to run `pub` in order to get the package map.
-    DartSdk defaultSdk = _createDefaultSdk(defaultSdkPath, useSummaries);
+    DartSdk defaultSdk = _createDefaultSdk(defaultSdkPath, true);
     //
     // Initialize the instrumentation service.
     //
@@ -457,7 +447,7 @@
     //
     socketServer = new SocketServer(
         analysisServerOptions,
-        new DartSdkManager(defaultSdkPath, useSummaries),
+        new DartSdkManager(defaultSdkPath, true),
         defaultSdk,
         instrumentationService,
         diagnosticServer,
@@ -545,10 +535,6 @@
         help: "enable validation of incremental resolution results (slow)",
         defaultsTo: false,
         negatable: false);
-    parser.addFlag(DISABLE_NEW_ANALYSIS_DRIVER,
-        help: "disable using new analysis driver",
-        defaultsTo: false,
-        negatable: false);
     parser.addOption(INSTRUMENTATION_LOG_FILE,
         help:
             "the path of the file to which instrumentation data will be written");
diff --git a/pkg/analysis_server/lib/src/server/http_server.dart b/pkg/analysis_server/lib/src/server/http_server.dart
index 94eb15d..6541df5 100644
--- a/pkg/analysis_server/lib/src/server/http_server.dart
+++ b/pkg/analysis_server/lib/src/server/http_server.dart
@@ -126,12 +126,7 @@
    */
   Future<Null> _handleGetRequest(HttpRequest request) async {
     if (getHandler == null) {
-      if (socketServer.analysisServer.options.enableNewAnalysisDriver) {
-        getHandler = new DiagnosticsSite(socketServer, _printBuffer);
-      } else {
-        getHandler = new ErrorGetHandler(
-            'Diagnostics only supported for the new analysis driver.');
-      }
+      getHandler = new DiagnosticsSite(socketServer, _printBuffer);
     }
     await getHandler.handleGetRequest(request);
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 7304c26..f4331aa 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -14,7 +14,6 @@
 import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -105,7 +104,10 @@
   final AnalysisResult result;
 
   @override
-  final LibraryElement coreLib;
+  final ResourceProvider resourceProvider;
+
+  @override
+  final InterfaceType objectType;
 
   @override
   final Source source;
@@ -120,16 +122,8 @@
   Source librarySource;
 
   @override
-  final ResourceProvider resourceProvider;
-
-  @override
   CompletionTarget target;
 
-  /**
-   * The [DartType] for Object in dart:core
-   */
-  InterfaceType _objectType;
-
   OpType _opType;
 
   final CompletionRequest _originalRequest;
@@ -139,7 +133,7 @@
   DartCompletionRequestImpl._(
       this.result,
       this.resourceProvider,
-      this.coreLib,
+      this.objectType,
       this.librarySource,
       this.source,
       this.offset,
@@ -167,14 +161,6 @@
     return null;
   }
 
-  @override
-  InterfaceType get objectType {
-    if (_objectType == null) {
-      _objectType = coreLib.getType('Object').type;
-    }
-    return _objectType;
-  }
-
   OpType get opType {
     if (_opType == null) {
       _opType = new OpType.forCompletion(target, offset);
@@ -237,19 +223,14 @@
     const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
     performance.logStartTime(BUILD_REQUEST_TAG);
 
-    Source libSource;
-    CompilationUnit unit;
-    unit = request.result.unit;
-    // TODO(scheglov) support for parts
-    libSource = resolutionMap.elementDeclaredByCompilationUnit(unit).source;
-
-    LibraryElement coreLib =
-        await request.result.driver.getLibraryByUri('dart:core');
+    CompilationUnit unit = request.result.unit;
+    Source libSource = unit.element.library.source;
+    InterfaceType objectType = request.result.typeProvider.objectType;
 
     DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
         request.result,
         request.resourceProvider,
-        coreLib,
+        objectType,
         libSource,
         request.source,
         request.offset,
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 1a6945a..133bd70 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
@@ -328,7 +328,8 @@
       _removeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
       _addInsertEdit(loc, delimiter);
     }
-    expr = errorMatching(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
+    expr = errorMatching(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'") ??
+        errorMatching(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
     if (expr != null) {
       expr = expr.getAncestor((n) => n is ListLiteral);
       if (expr != null) {
@@ -343,6 +344,7 @@
             _addInsertEdit(loc, ']');
           }
           _removeError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
+          _removeError(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
           var ms =
               _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
           if (ms != null) {
@@ -425,7 +427,10 @@
           _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
       if (error != null) {
         int insertOffset;
-        if (expr == null || expr.isSynthetic) {
+        // Fasta scanner reports unterminated string literal errors
+        // and generates a synthetic string token with non-zero length.
+        // Because of this, check for length == 0 rather than isSynthetic.
+        if (expr == null || expr.length == 0) {
           if (node is ReturnStatement) {
             insertOffset = (node as ReturnStatement).returnKeyword.end;
           } else if (node is ExpressionStatement) {
@@ -828,7 +833,8 @@
 
   bool _complete_methodCall() {
     var parenError =
-        _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "')'");
+        _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "')'") ??
+            _findError(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "')'");
     if (parenError == null) {
       return false;
     }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 94de692..ad395d5 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -1075,8 +1075,6 @@
 
     buf.writeln('<div class="column one-half">');
     h3('Status');
-    buf.writeln(writeOption(
-        'New analysis driver enabled', server.options.enableNewAnalysisDriver));
     buf.writeln(writeOption('Instrumentation enabled',
         AnalysisEngine.instance.instrumentationService.isActive));
     buf.writeln(writeOption('Server process ID', pid));
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index 36a62d9..bbe0a10 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -125,10 +125,7 @@
     addAnalysisSubscription(AnalysisService.IMPLEMENTED, testFile);
   }
 
-  @failingTest
   test_afterAnalysis() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {}
 class B extends A {}
@@ -138,10 +135,7 @@
     assertHasImplementedClass('A {');
   }
 
-  @failingTest
   test_afterIncrementalResolution() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     subscribeForImplemented();
     addTestFile('''
 class A {}
@@ -160,10 +154,7 @@
     assertHasImplementedClass('A  {');
   }
 
-  @failingTest
   test_class_extended() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {}
 class B extends A {}
@@ -172,10 +163,7 @@
     assertHasImplementedClass('A {');
   }
 
-  @failingTest
   test_class_implemented() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {}
 class B implements A {}
@@ -184,10 +172,7 @@
     assertHasImplementedClass('A {');
   }
 
-  @failingTest
   test_class_mixed() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {}
 class B = Object with A;
@@ -196,10 +181,7 @@
     assertHasImplementedClass('A {');
   }
 
-  @failingTest
   test_field_withField() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   int f; // A
@@ -212,10 +194,7 @@
     assertHasImplementedMember('f; // A');
   }
 
-  @failingTest
   test_field_withGetter() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   int f; // A
@@ -228,10 +207,7 @@
     assertHasImplementedMember('f; // A');
   }
 
-  @failingTest
   test_field_withSetter() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   int f; // A
@@ -244,10 +220,7 @@
     assertHasImplementedMember('f; // A');
   }
 
-  @failingTest
   test_getter_withField() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   get f => null; // A
@@ -260,10 +233,7 @@
     assertHasImplementedMember('f => null; // A');
   }
 
-  @failingTest
   test_getter_withGetter() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   get f => null; // A
@@ -276,10 +246,7 @@
     assertHasImplementedMember('f => null; // A');
   }
 
-  @failingTest
   test_method_withMethod() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   m() {} // A
@@ -293,10 +260,7 @@
     assertNoImplementedMember('m() {} // B');
   }
 
-  @failingTest
   test_method_withMethod_indirectSubclass() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   m() {} // A
@@ -311,10 +275,7 @@
     assertHasImplementedMember('m() {} // A');
   }
 
-  @failingTest
   test_method_withMethod_private_differentLib() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addFile(
         '$testFolder/lib.dart',
         r'''
@@ -332,10 +293,7 @@
     assertNoImplementedMember('_m() {} // A');
   }
 
-  @failingTest
   test_method_withMethod_private_sameLibrary() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   _m() {} // A
@@ -349,10 +307,7 @@
     assertNoImplementedMember('_m() {} // B');
   }
 
-  @failingTest
   test_method_withMethod_wasAbstract() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 abstract class A {
   m(); // A
@@ -365,10 +320,7 @@
     assertHasImplementedMember('m(); // A');
   }
 
-  @failingTest
   test_setter_withField() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   set f(_) {} // A
@@ -381,10 +333,7 @@
     assertHasImplementedMember('f(_) {} // A');
   }
 
-  @failingTest
   test_setter_withSetter() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   set f(_) {} // A
@@ -397,10 +346,7 @@
     assertHasImplementedMember('f(_) {} // A');
   }
 
-  @failingTest
   test_static_field_instanceStatic() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   int F = 0;
@@ -413,10 +359,7 @@
     assertNoImplementedMember('F = 0');
   }
 
-  @failingTest
   test_static_field_staticInstance() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   static int F = 0;
@@ -429,10 +372,7 @@
     assertNoImplementedMember('F = 0');
   }
 
-  @failingTest
   test_static_field_staticStatic() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   static int F = 0;
@@ -445,10 +385,7 @@
     assertNoImplementedMember('F = 0');
   }
 
-  @failingTest
   test_static_method_instanceStatic() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   int m() => 0;
@@ -461,10 +398,7 @@
     assertNoImplementedMember('m() => 0');
   }
 
-  @failingTest
   test_static_method_staticInstance() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   static int m() => 0;
@@ -477,10 +411,7 @@
     assertNoImplementedMember('m() => 0');
   }
 
-  @failingTest
   test_static_method_staticStatic() async {
-    // See https://github.com/dart-lang/sdk/issues/29113
-    fail('The analysis.implemented notification is not implemented.');
     addTestFile('''
 class A {
   static int m() => 0;
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index ff2c771..8d0348e 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -139,7 +139,6 @@
     // Create server
     //
     AnalysisServerOptions options = new AnalysisServerOptions();
-    options.enableNewAnalysisDriver = true;
     return new AnalysisServer(
         serverChannel,
         resourceProvider,
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 5ba35a6..8bac130 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domain_server.dart';
 import 'package:analysis_server/src/operation/operation.dart';
 import 'package:analysis_server/src/plugin/server_plugin.dart';
@@ -16,7 +15,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -44,81 +42,52 @@
   MockPackageMapProvider packageMapProvider;
 
   /**
-   * Verify that getAnalysisContextForSource returns the correct contexts even
-   * for sources that are included by multiple contexts.
-   *
-   * See dartbug.com/21898
+   * Test that having multiple analysis contexts analyze the same file doesn't
+   * cause that file to receive duplicate notifications when it's modified.
    */
-  Future fail_getAnalysisContextForSource_crossImports() {
+  Future do_not_test_no_duplicate_notifications() async {
     // Subscribe to STATUS so we'll know when analysis is done.
     server.serverServices = [ServerService.STATUS].toSet();
-    // Analyze project foo containing foo.dart and project bar containing
-    // bar.dart.
     resourceProvider.newFolder('/foo');
     resourceProvider.newFolder('/bar');
-    File foo = resourceProvider.newFile(
-        '/foo/foo.dart',
-        '''
-libary foo;
-import "../bar/bar.dart";
-''');
-    Source fooSource = foo.createSource();
-    File bar = resourceProvider.newFile(
-        '/bar/bar.dart',
-        '''
-library bar;
-import "../foo/foo.dart";
-''');
-    Source barSource = bar.createSource();
+    resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";');
+    File bar = resourceProvider.newFile('/bar/bar.dart', 'library bar;');
     server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return server.onAnalysisComplete.then((_) {
-      expect(server.statusAnalyzing, isFalse);
-      // Make sure getAnalysisContext returns the proper context for each.
-      AnalysisContext fooContext =
-          server.getAnalysisContextForSource(fooSource);
-      expect(fooContext, isNotNull);
-      AnalysisContext barContext =
-          server.getAnalysisContextForSource(barSource);
-      expect(barContext, isNotNull);
-      expect(fooContext, isNot(same(barContext)));
-      expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY);
-      expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(barSource), SourceKind.LIBRARY);
-    });
-  }
-
-  /**
-   * Verify that getAnalysisContextForSource returns the correct contexts even
-   * for sources that haven't been analyzed yet.
-   *
-   * See dartbug.com/21898
-   */
-  Future fail_getAnalysisContextForSource_unanalyzed() {
-    // Subscribe to STATUS so we'll know when analysis is done.
-    server.serverServices = [ServerService.STATUS].toSet();
-    // Analyze project foo containing foo.dart and project bar containing
-    // bar.dart.
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFolder('/bar');
-    File foo = resourceProvider.newFile('/foo/foo.dart', 'library lib;');
-    Source fooSource = foo.createSource();
-    File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;');
-    Source barSource = bar.createSource();
-    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    AnalysisContext fooContext = server.getAnalysisContextForSource(fooSource);
-    expect(fooContext, isNotNull);
-    AnalysisContext barContext = server.getAnalysisContextForSource(barSource);
-    expect(barContext, isNotNull);
-    expect(fooContext, isNot(same(barContext)));
-    return server.onAnalysisComplete.then((_) {
-      expect(server.statusAnalyzing, isFalse);
-      // Make sure getAnalysisContext returned the proper context for each.
-      expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY);
-      expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(barSource), SourceKind.LIBRARY);
-    });
+    Map<AnalysisService, Set<String>> subscriptions =
+        <AnalysisService, Set<String>>{};
+    for (AnalysisService service in AnalysisService.VALUES) {
+      subscriptions[service] = <String>[bar.path].toSet();
+    }
+    // The following line causes the isolate to continue running even though the
+    // test completes.
+    server.setAnalysisSubscriptions(subscriptions);
+    await server.onAnalysisComplete;
+    expect(server.statusAnalyzing, isFalse);
+    channel.notificationsReceived.clear();
+    server.updateContent(
+        '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
+    await server.onAnalysisComplete;
+    expect(server.statusAnalyzing, isFalse);
+    expect(channel.notificationsReceived, isNotEmpty);
+    Set<String> notificationTypesReceived = new Set<String>();
+    for (Notification notification in channel.notificationsReceived) {
+      String notificationType = notification.event;
+      switch (notificationType) {
+        case 'server.status':
+        case 'analysis.errors':
+          // It's normal for these notifications to be sent multiple times.
+          break;
+        case 'analysis.outline':
+          // It's normal for this notification to be sent twice.
+          // TODO(paulberry): why?
+          break;
+        default:
+          if (!notificationTypesReceived.add(notificationType)) {
+            fail('Notification type $notificationType received more than once');
+          }
+          break;
+      }
+    }
   }
 
   void processRequiredPlugins(ServerPlugin serverPlugin) {
@@ -150,71 +119,6 @@
         rethrowExceptions: true);
   }
 
-  Future test_contextDisposed() {
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFile('/foo/bar.dart', 'library lib;');
-    server.setAnalysisRoots('0', ['/foo'], [], {});
-    AnalysisContext context;
-    return pumpEventQueue()
-        .then((_) {
-          context = server.getAnalysisContext('/foo/bar.dart');
-          server.setAnalysisRoots('1', [], [], {});
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(context.isDisposed, isTrue);
-        });
-  }
-
-  Future test_contextsChangedEvent() {
-    resourceProvider.newFolder('/foo');
-
-    bool wasAdded = false;
-    bool wasChanged = false;
-    bool wasRemoved = false;
-    server.onContextsChanged.listen((ContextsChangedEvent event) {
-      wasAdded = event.added.length == 1;
-      if (wasAdded) {
-        expect(event.added[0], isNotNull);
-      }
-      wasChanged = event.changed.length == 1;
-      if (wasChanged) {
-        expect(event.changed[0], isNotNull);
-      }
-      wasRemoved = event.removed.length == 1;
-      if (wasRemoved) {
-        expect(event.removed[0], isNotNull);
-      }
-    });
-
-    server.setAnalysisRoots('0', ['/foo'], [], {});
-    return pumpEventQueue().then((_) {
-      expect(wasAdded, isTrue);
-      expect(wasChanged, isFalse);
-      expect(wasRemoved, isFalse);
-
-      wasAdded = false;
-      wasChanged = false;
-      wasRemoved = false;
-      server.setAnalysisRoots('0', ['/foo'], [], {'/foo': '/bar'});
-      return pumpEventQueue();
-    }).then((_) {
-      expect(wasAdded, isFalse);
-      expect(wasChanged, isTrue);
-      expect(wasRemoved, isFalse);
-
-      wasAdded = false;
-      wasChanged = false;
-      wasRemoved = false;
-      server.setAnalysisRoots('0', [], [], {});
-      return pumpEventQueue();
-    }).then((_) {
-      expect(wasAdded, isFalse);
-      expect(wasChanged, isFalse);
-      expect(wasRemoved, isTrue);
-    });
-  }
-
   Future test_echo() {
     server.handlers = [new EchoHandler()];
     var request = new Request('my22', 'echo');
@@ -224,199 +128,6 @@
     });
   }
 
-  Future test_getAnalysisContextForSource() {
-    // Subscribe to STATUS so we'll know when analysis is done.
-    server.serverServices = [ServerService.STATUS].toSet();
-    // Analyze project foo containing foo.dart and project bar containing
-    // bar.dart.
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFolder('/bar');
-    File foo = resourceProvider.newFile('/foo/foo.dart', 'library lib;');
-    Source fooSource = foo.createSource();
-    File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;');
-    Source barSource = bar.createSource();
-    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return server.onAnalysisComplete.then((_) {
-      expect(server.statusAnalyzing, isFalse);
-      // Make sure getAnalysisContext returns the proper context for each.
-      AnalysisContext fooContext =
-          server.getAnalysisContextForSource(fooSource);
-      expect(fooContext, isNotNull);
-      AnalysisContext barContext =
-          server.getAnalysisContextForSource(barSource);
-      expect(barContext, isNotNull);
-      expect(fooContext, isNot(same(barContext)));
-      expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY);
-      expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN);
-      expect(barContext.getKindOf(barSource), SourceKind.LIBRARY);
-    });
-  }
-
-  test_getContextSourcePair_nested() {
-    String dir1Path = '/dir1';
-    String dir2Path = dir1Path + '/dir2';
-    String filePath = dir2Path + '/file.dart';
-    resourceProvider.newFile('$dir1Path/.packages', '');
-    resourceProvider.newFile('$dir2Path/.packages', '');
-    resourceProvider.newFile(filePath, 'library lib;');
-    // create contexts
-    server.setAnalysisRoots('0', [dir1Path], [], {});
-    // get pair
-    ContextSourcePair pair = server.getContextSourcePair(filePath);
-    _assertContextOfFolder(pair.context, dir2Path);
-    Source source = pair.source;
-    expect(source, isNotNull);
-    expect(source.uri.scheme, 'file');
-    expect(source.fullName, filePath);
-  }
-
-  test_getContextSourcePair_nonFile() {
-    String dirPath = '/dir';
-    Folder dir = resourceProvider.newFolder(dirPath);
-
-    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
-    _configureSourceFactory(context);
-    server.folderMap[dir] = context;
-
-    ContextSourcePair pair = server.getContextSourcePair(dirPath);
-    expect(pair, isNotNull);
-    expect(pair.context, isNull);
-    expect(pair.source, isNull);
-  }
-
-  test_getContextSourcePair_simple() {
-    String dirPath = '/dir';
-    String filePath = dirPath + '/file.dart';
-    resourceProvider.newFile(filePath, 'library lib;');
-    // create contexts
-    server.setAnalysisRoots('0', [dirPath], [], {});
-    // get pair
-    ContextSourcePair pair = server.getContextSourcePair(filePath);
-    _assertContextOfFolder(pair.context, dirPath);
-    Source source = pair.source;
-    expect(source, isNotNull);
-    expect(source.uri.scheme, 'file');
-    expect(source.fullName, filePath);
-  }
-
-  test_getContextSourcePair_withPackagesFile() {
-    String dirPath = '/dir';
-    String packagesFilePath = dirPath + '/.packages';
-    resourceProvider.newFile(packagesFilePath, 'dir:lib/');
-    String filePath = dirPath + '/lib/file.dart';
-    resourceProvider.newFile(filePath, 'library lib;');
-    // create contexts
-    server.setAnalysisRoots('0', [dirPath], [], {});
-    // get pair
-    ContextSourcePair pair = server.getContextSourcePair(filePath);
-    _assertContextOfFolder(pair.context, dirPath);
-    Source source = pair.source;
-    expect(source, isNotNull);
-    expect(source.uri.scheme, 'package');
-    expect(source.fullName, filePath);
-  }
-
-  /**
-   * Test that having multiple analysis contexts analyze the same file doesn't
-   * cause that file to receive duplicate notifications when it's modified.
-   */
-  Future test_no_duplicate_notifications() async {
-    // Subscribe to STATUS so we'll know when analysis is done.
-    server.serverServices = [ServerService.STATUS].toSet();
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFolder('/bar');
-    resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";');
-    File bar = resourceProvider.newFile('/bar/bar.dart', 'library bar;');
-    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    Map<AnalysisService, Set<String>> subscriptions =
-        <AnalysisService, Set<String>>{};
-    for (AnalysisService service in AnalysisService.VALUES) {
-      subscriptions[service] = <String>[bar.path].toSet();
-    }
-    server.setAnalysisSubscriptions(subscriptions);
-    await server.onAnalysisComplete;
-    expect(server.statusAnalyzing, isFalse);
-    channel.notificationsReceived.clear();
-    server.updateContent(
-        '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
-    await server.onAnalysisComplete;
-    expect(server.statusAnalyzing, isFalse);
-    expect(channel.notificationsReceived, isNotEmpty);
-    Set<String> notificationTypesReceived = new Set<String>();
-    for (Notification notification in channel.notificationsReceived) {
-      String notificationType = notification.event;
-      switch (notificationType) {
-        case 'server.status':
-        case 'analysis.errors':
-          // It's normal for these notifications to be sent multiple times.
-          break;
-        case 'analysis.outline':
-          // It's normal for this notification to be sent twice.
-          // TODO(paulberry): why?
-          break;
-        default:
-          if (!notificationTypesReceived.add(notificationType)) {
-            fail('Notification type $notificationType received more than once');
-          }
-          break;
-      }
-    }
-  }
-
-  test_operationsRemovedOnContextDisposal() async {
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFile('/foo/baz.dart', 'library lib;');
-    resourceProvider.newFolder('/bar');
-    resourceProvider.newFile('/bar/baz.dart', 'library lib;');
-    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    await pumpEventQueue();
-    AnalysisContext contextFoo = server.getAnalysisContext('/foo/baz.dart');
-    AnalysisContext contextBar = server.getAnalysisContext('/bar/baz.dart');
-    _MockServerOperation operationFoo = new _MockServerOperation(contextFoo);
-    _MockServerOperation operationBar = new _MockServerOperation(contextBar);
-    server.scheduleOperation(operationFoo);
-    server.scheduleOperation(operationBar);
-    server.setAnalysisRoots('1', ['/foo'], [], {});
-    await pumpEventQueue();
-    expect(operationFoo.isComplete, isTrue);
-    expect(operationBar.isComplete, isFalse);
-  }
-
-  Future test_prioritySourcesChangedEvent() {
-    resourceProvider.newFolder('/foo');
-
-    int eventCount = 0;
-    Source firstSource = null;
-    server.onPriorityChange.listen((PriorityChangeEvent event) {
-      ++eventCount;
-      firstSource = event.firstSource;
-    });
-
-    server.setAnalysisRoots('0', ['/foo'], [], {});
-    return pumpEventQueue().then((_) {
-      expect(eventCount, 0);
-
-      server.setPriorityFiles('1', ['/foo/bar.dart']);
-      return pumpEventQueue();
-    }).then((_) {
-      expect(eventCount, 1);
-      expect(firstSource.fullName, '/foo/bar.dart');
-
-      server.setPriorityFiles('2', ['/foo/b1.dart', '/foo/b2.dart']);
-      return pumpEventQueue();
-    }).then((_) {
-      expect(eventCount, 2);
-      expect(firstSource.fullName, '/foo/b1.dart');
-
-      server.setPriorityFiles('17', []);
-      return pumpEventQueue();
-    }).then((_) {
-      expect(eventCount, 3);
-      expect(firstSource, isNull);
-    });
-  }
-
   void test_rethrowExceptions() {
     Exception exceptionToThrow = new Exception('test exception');
     MockServerOperation operation =
@@ -526,24 +237,6 @@
       expect(response.error, isNotNull);
     });
   }
-
-  void _assertContextOfFolder(
-      AnalysisContext context, String expectedFolderPath) {
-    Folder expectedFolder = resourceProvider.newFolder(expectedFolderPath);
-    ContextInfo expectedContextInfo =
-        (server.contextManager as ContextManagerImpl)
-            .getContextInfoFor(expectedFolder);
-    expect(expectedContextInfo, isNotNull);
-    expect(context, same(expectedContextInfo.context));
-  }
-
-  void _configureSourceFactory(AnalysisContext context) {
-    var resourceUriResolver = new ResourceUriResolver(resourceProvider);
-    var packageUriResolver = new PackageMapUriResolver(
-        resourceProvider, packageMapProvider.packageMap);
-    context.sourceFactory =
-        new SourceFactory([packageUriResolver, resourceUriResolver]);
-  }
 }
 
 class EchoHandler implements RequestHandler {
@@ -555,22 +248,3 @@
     return null;
   }
 }
-
-/**
- * A [ServerOperation] that does nothing but keep track of whether or not it
- * has been performed.
- */
-class _MockServerOperation implements ServerOperation {
-  final AnalysisContext context;
-  bool isComplete = false;
-
-  _MockServerOperation(this.context);
-
-  @override
-  ServerOperationPriority get priority => ServerOperationPriority.ANALYSIS;
-
-  @override
-  void perform(AnalysisServer server) {
-    isComplete = true;
-  }
-}
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 2c60a52..0fbbc65 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -50,8 +50,6 @@
 
 @reflectiveTest
 class AbstractContextManagerTest extends ContextManagerTest {
-  bool get enableAnalysisDriver => true;
-
   void test_contextsInAnalysisRoot_nestedContext() {
     String subProjPath = path.posix.join(projPath, 'subproj');
     Folder subProjFolder = resourceProvider.newFolder(subProjPath);
@@ -69,25 +67,15 @@
     ContextInfo subProjContextInfo = manager.getContextInfoFor(subProjFolder);
     expect(subProjContextInfo, isNotNull);
     expect(subProjContextInfo.folder, subProjFolder);
-    if (enableAnalysisDriver) {
-      expect(projContextInfo.analysisDriver,
-          isNot(equals(subProjContextInfo.analysisDriver)));
-      // Check that getDriversInAnalysisRoot() works.
-      List<AnalysisDriver> drivers =
-          manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, isNotNull);
-      expect(drivers, hasLength(2));
-      expect(drivers, contains(projContextInfo.analysisDriver));
-      expect(drivers, contains(subProjContextInfo.analysisDriver));
-    } else {
-      expect(projContextInfo.context != subProjContextInfo.context, isTrue);
-      // Check that contextsInAnalysisRoot() works.
-      List<AnalysisContext> contexts =
-          manager.contextsInAnalysisRoot(projectFolder);
-      expect(contexts, hasLength(2));
-      expect(contexts, contains(projContextInfo.context));
-      expect(contexts, contains(subProjContextInfo.context));
-    }
+    expect(projContextInfo.analysisDriver,
+        isNot(equals(subProjContextInfo.analysisDriver)));
+    // Check that getDriversInAnalysisRoot() works.
+    List<AnalysisDriver> drivers =
+        manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, isNotNull);
+    expect(drivers, hasLength(2));
+    expect(drivers, contains(projContextInfo.analysisDriver));
+    expect(drivers, contains(subProjContextInfo.analysisDriver));
   }
 
   @failingTest
@@ -127,17 +115,10 @@
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     await pumpEventQueue();
     // Confirm that one driver / context was created.
-    if (enableAnalysisDriver) {
-      List<AnalysisDriver> drivers =
-          manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, isNotNull);
-      expect(drivers, hasLength(1));
-    } else {
-      List<AnalysisContext> contexts =
-          manager.contextsInAnalysisRoot(projectFolder);
-      expect(contexts, isNotNull);
-      expect(contexts, hasLength(1));
-    }
+    List<AnalysisDriver> drivers =
+        manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, isNotNull);
+    expect(drivers, hasLength(1));
 
     // No embedded libs yet.
     expect(sourceFactory.forUri('dart:typed_data'), isNull);
@@ -151,18 +132,9 @@
     await pumpEventQueue();
 
     // Confirm that we still have just one driver / context.
-    if (enableAnalysisDriver) {
-      List<AnalysisDriver> drivers =
-          manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, isNotNull);
-      expect(drivers, hasLength(1));
-    } else {
-      List<AnalysisContext> contexts =
-          manager.contextsInAnalysisRoot(projectFolder);
-
-      expect(contexts, isNotNull);
-      expect(contexts, hasLength(1));
-    }
+    drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, isNotNull);
+    expect(drivers, hasLength(1));
 
     // Embedded lib should be defined now.
     expect(sourceFactory.forUri('dart:typed_data'), isNotNull);
@@ -444,17 +416,10 @@
     Iterable<String> filePaths = callbacks.currentFilePaths;
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
-    if (enableAnalysisDriver) {
-      List<AnalysisDriver> drivers = manager
-          .getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
-      expect(drivers, hasLength(1));
-      expect(drivers[0], isNotNull);
-    } else {
-      List<AnalysisContext> contextsInAnalysisRoot =
-          manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
-      expect(contextsInAnalysisRoot, hasLength(1));
-      expect(contextsInAnalysisRoot[0], isNotNull);
-    }
+    List<AnalysisDriver> drivers =
+        manager.getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
+    expect(drivers, hasLength(1));
+    expect(drivers[0], isNotNull);
     Source result = sourceFactory.forUri('dart:async');
     expect(result, isNotNull);
   }
@@ -992,17 +957,10 @@
     resourceProvider.newFile(filePath, 'contents');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
-    if (enableAnalysisDriver) {
-      var drivers = manager
-          .getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
-      expect(drivers, hasLength(1));
-      expect(drivers[0], isNotNull);
-    } else {
-      List<AnalysisContext> contextsInAnalysisRoot =
-          manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
-      expect(contextsInAnalysisRoot, hasLength(1));
-      expect(contextsInAnalysisRoot[0], isNotNull);
-    }
+    var drivers =
+        manager.getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
+    expect(drivers, hasLength(1));
+    expect(drivers[0], isNotNull);
     Source result = sourceFactory.forUri('package:foo/foo.dart');
     expect(result.fullName, filePath);
   }
@@ -1641,27 +1599,15 @@
     resourceProvider.newFile(filePath, 'contents');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // the file was added
-    if (enableAnalysisDriver) {
-      Iterable<String> filePaths = callbacks.currentFilePaths;
-      expect(filePaths, hasLength(1));
-      expect(filePaths, contains(filePath));
-      // TODO(brianwilkerson) Test when the file was modified
-    } else {
-      Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
-      expect(filePaths, hasLength(1));
-      expect(filePaths, contains(filePath));
-      expect(filePaths[filePath], equals(callbacks.now));
-    }
+    Iterable<String> filePaths = callbacks.currentFilePaths;
+    expect(filePaths, hasLength(1));
+    expect(filePaths, contains(filePath));
+    // TODO(brianwilkerson) Test when the file was modified
     // update the file
     callbacks.now++;
     resourceProvider.modifyFile(filePath, 'new contents');
     return pumpEventQueue().then((_) {
-      if (enableAnalysisDriver) {
-        // TODO(brianwilkerson) Test when the file was modified
-        return null;
-      }
-      Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
-      return expect(filePaths[filePath], equals(callbacks.now));
+      // TODO(brianwilkerson) Test when the file was modified
     });
   }
 
@@ -1797,8 +1743,6 @@
 
   AnalysisOptions get analysisOptions => callbacks.analysisOptions;
 
-  bool get enableAnalysisDriver => false;
-
   List<ErrorProcessor> get errorProcessors => analysisOptions.errorProcessors;
 
   List<Linter> get lints => analysisOptions.lintRules;
@@ -1867,8 +1811,7 @@
         packageMapProvider,
         analysisFilesGlobs,
         InstrumentationService.NULL_SERVICE,
-        new AnalysisOptionsImpl(),
-        enableAnalysisDriver);
+        new AnalysisOptionsImpl());
     PerformanceLog logger = new PerformanceLog(new NullStringSink());
     AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger);
     callbacks = new TestContextManagerCallbacks(
@@ -1892,26 +1835,18 @@
 
   Map<String, List<Folder>> _packageMap(String contextPath) {
     Folder folder = resourceProvider.getFolder(contextPath);
-    if (enableAnalysisDriver) {
-      ContextInfo info = manager.getContextInfoFor(folder);
-      return info.analysisDriver.sourceFactory?.packageMap;
-    } else {
-      return manager.folderMap[folder]?.sourceFactory?.packageMap;
-    }
+    ContextInfo info = manager.getContextInfoFor(folder);
+    return info.analysisDriver.sourceFactory?.packageMap;
   }
 }
 
 @reflectiveTest
 class ContextManagerWithNewOptionsTest extends ContextManagerWithOptionsTest {
-  bool get enableAnalysisDriver => true;
-
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
 }
 
 @reflectiveTest
 class ContextManagerWithOldOptionsTest extends ContextManagerWithOptionsTest {
-  bool get enableAnalysisDriver => true;
-
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_FILE;
 }
 
@@ -2316,25 +2251,13 @@
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     await pumpEventQueue();
 
-    if (enableAnalysisDriver) {
-      AnalysisResult result =
-          await callbacks.currentDriver.getResult(file.path);
+    AnalysisResult result = await callbacks.currentDriver.getResult(file.path);
 
-      // Not strong mode - both in the context and the SDK context.
-      AnalysisContext sdkContext = sourceFactory.dartSdk.context;
-      expect(analysisOptions.strongMode, isFalse);
-      expect(sdkContext.analysisOptions.strongMode, isFalse);
-      expect(result.errors, isEmpty);
-    } else {
-      AnalysisContext context = manager.getContextFor(projPath);
-      Source testSource = context.getSourcesWithFullName(file.path).single;
-
-      // Not strong mode - both in the context and the SDK context.
-      AnalysisContext sdkContext = sourceFactory.dartSdk.context;
-      expect(analysisOptions.strongMode, isFalse);
-      expect(sdkContext.analysisOptions.strongMode, isFalse);
-      expect(context.computeErrors(testSource), isEmpty);
-    }
+    // Not strong mode - both in the context and the SDK context.
+    AnalysisContext sdkContext = sourceFactory.dartSdk.context;
+    expect(analysisOptions.strongMode, isFalse);
+    expect(sdkContext.analysisOptions.strongMode, isFalse);
+    expect(result.errors, isEmpty);
 
     // Update the options file - turn on 'strong-mode'.
     resourceProvider.updateFile(
@@ -2346,27 +2269,15 @@
     await pumpEventQueue();
 
     // Strong mode - both in the context and the SDK context.
-    if (enableAnalysisDriver) {
-      AnalysisResult result =
-          await callbacks.currentDriver.getResult(file.path);
+    result = await callbacks.currentDriver.getResult(file.path);
 
-      // Not strong mode - both in the context and the SDK context.
-      AnalysisContext sdkContext = sourceFactory.dartSdk.context;
-      expect(analysisOptions.strongMode, isTrue);
-      expect(sdkContext.analysisOptions.strongMode, isTrue);
-      // The code is strong-mode clean.
-      // Verify that TypeSystem was reset.
-      expect(result.errors, isEmpty);
-    } else {
-      AnalysisContext context = manager.getContextFor(projPath);
-      Source testSource = context.getSourcesWithFullName(file.path).single;
-      AnalysisContext sdkContext = sourceFactory.dartSdk.context;
-      expect(analysisOptions.strongMode, isTrue);
-      expect(sdkContext.analysisOptions.strongMode, isTrue);
-      // The code is strong-mode clean.
-      // Verify that TypeSystem was reset.
-      expect(context.computeErrors(testSource), isEmpty);
-    }
+    // Not strong mode - both in the context and the SDK context.
+    sdkContext = sourceFactory.dartSdk.context;
+    expect(analysisOptions.strongMode, isTrue);
+    expect(sdkContext.analysisOptions.strongMode, isTrue);
+    // The code is strong-mode clean.
+    // Verify that TypeSystem was reset.
+    expect(result.errors, isEmpty);
   }
 
   @failingTest
@@ -2394,24 +2305,13 @@
 
     // Verify that analysis options was parsed and the ignore patterns applied.
     Folder projectFolder = resourceProvider.newFolder(projPath);
-    if (enableAnalysisDriver) {
-      var drivers = manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, hasLength(1));
-      AnalysisDriver driver = drivers[0];
-      expect(
-          driver.addedFiles,
-          unorderedEquals(
-              ['/my/proj/lib/main.dart', '/my/proj/$optionsFileName']));
-    } else {
-      Map<String, int> fileTimestamps =
-          callbacks.currentContextFilePaths[projPath];
-      expect(fileTimestamps, isNotEmpty);
-      List<String> files = fileTimestamps.keys.toList();
-      expect(
-          files,
-          unorderedEquals(
-              ['/my/proj/lib/main.dart', '/my/proj/$optionsFileName']));
-    }
+    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, hasLength(1));
+    AnalysisDriver driver = drivers[0];
+    expect(
+        driver.addedFiles,
+        unorderedEquals(
+            ['/my/proj/lib/main.dart', '/my/proj/$optionsFileName']));
   }
 
   test_path_filter_child_contexts_option() async {
@@ -2444,18 +2344,10 @@
     // Verify that the context in other_lib wasn't created and that the
     // context in lib was created.
     Folder projectFolder = resourceProvider.newFolder(projPath);
-    if (enableAnalysisDriver) {
-      var drivers = manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, hasLength(2));
-      expect(drivers[0].name, equals('/my/proj'));
-      expect(drivers[1].name, equals('/my/proj/lib'));
-    } else {
-      var contexts =
-          manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
-      expect(contexts.length, 2);
-      expect(contexts[0].name, equals('/my/proj'));
-      expect(contexts[1].name, equals('/my/proj/lib'));
-    }
+    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, hasLength(2));
+    expect(drivers[0].name, equals('/my/proj'));
+    expect(drivers[1].name, equals('/my/proj/lib'));
   }
 
   test_path_filter_recursive_wildcard_child_contexts_option() async {
@@ -2489,17 +2381,10 @@
     // Verify that the context in other_lib wasn't created and that the
     // context in lib was created.
     Folder projectFolder = resourceProvider.newFolder(projPath);
-    if (enableAnalysisDriver) {
-      var drivers = manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, hasLength(2));
-      expect(drivers[0].name, equals('/my/proj'));
-      expect(drivers[1].name, equals('/my/proj/lib'));
-    } else {
-      var contexts = manager.contextsInAnalysisRoot(projectFolder);
-      expect(contexts.length, 2);
-      expect(contexts[0].name, equals('/my/proj'));
-      expect(contexts[1].name, equals('/my/proj/lib'));
-    }
+    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, hasLength(2));
+    expect(drivers[0].name, equals('/my/proj'));
+    expect(drivers[1].name, equals('/my/proj/lib'));
   }
 
   test_path_filter_wildcard_child_contexts_option() async {
@@ -2531,19 +2416,10 @@
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
     Folder projectFolder = resourceProvider.newFolder(projPath);
-    if (enableAnalysisDriver) {
-      var drivers = manager.getDriversInAnalysisRoot(projectFolder);
-      expect(drivers, hasLength(2));
-      expect(drivers[0].name, equals('/my/proj'));
-      expect(drivers[1].name, equals('/my/proj/lib'));
-    } else {
-      // Verify that the context in other_lib wasn't created and that the
-      // context in lib was created.
-      var contexts = manager.contextsInAnalysisRoot(projectFolder);
-      expect(contexts, hasLength(2));
-      expect(contexts[0].name, equals('/my/proj'));
-      expect(contexts[1].name, equals('/my/proj/lib'));
-    }
+    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, hasLength(2));
+    expect(drivers[0].name, equals('/my/proj'));
+    expect(drivers[1].name, equals('/my/proj/lib'));
   }
 
   void test_setRoots_nested_excludedByOuter() {
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index d654f98..a2fa03a 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -67,45 +67,47 @@
   group('updateContent', testUpdateContent);
 
   group('AnalysisDomainHandler', () {
-    group('getReachableSources', () {
-      test('valid sources', () async {
-        String fileA = '/project/a.dart';
-        String fileB = '/project/b.dart';
-        resourceProvider.newFile(fileA, 'import "b.dart";');
-        resourceProvider.newFile(fileB, '');
-
-        server.setAnalysisRoots('0', ['/project/'], [], {});
-
-        await server.onAnalysisComplete;
-
-        var request =
-            new AnalysisGetReachableSourcesParams(fileA).toRequest('0');
-        var response = handler.handleRequest(request);
-
-        Map json = response.toJson()[Response.RESULT];
-
-        // Sanity checks.
-        expect(json['sources'], hasLength(6));
-        expect(json['sources']['file:///project/a.dart'],
-            unorderedEquals(['dart:core', 'file:///project/b.dart']));
-        expect(json['sources']['file:///project/b.dart'], ['dart:core']);
-      });
-
-      test('invalid source', () async {
-        resourceProvider.newFile('/project/a.dart', 'import "b.dart";');
-        server.setAnalysisRoots('0', ['/project/'], [], {});
-
-        await server.onAnalysisComplete;
-
-        var request =
-            new AnalysisGetReachableSourcesParams('/does/not/exist.dart')
-                .toRequest('0');
-        var response = handler.handleRequest(request);
-        expect(response.error, isNotNull);
-        expect(response.error.code,
-            RequestErrorCode.GET_REACHABLE_SOURCES_INVALID_FILE);
-      });
-    });
+    // TODO(brianwilkerson) Re-enable these tests if we re-enable the
+    // analysis.getReachableSources request.
+//    group('getReachableSources', () {
+//      test('valid sources', () async {
+//        String fileA = '/project/a.dart';
+//        String fileB = '/project/b.dart';
+//        resourceProvider.newFile(fileA, 'import "b.dart";');
+//        resourceProvider.newFile(fileB, '');
+//
+//        server.setAnalysisRoots('0', ['/project/'], [], {});
+//
+//        await server.onAnalysisComplete;
+//
+//        var request =
+//            new AnalysisGetReachableSourcesParams(fileA).toRequest('0');
+//        var response = handler.handleRequest(request);
+//
+//        Map json = response.toJson()[Response.RESULT];
+//
+//        // Sanity checks.
+//        expect(json['sources'], hasLength(6));
+//        expect(json['sources']['file:///project/a.dart'],
+//            unorderedEquals(['dart:core', 'file:///project/b.dart']));
+//        expect(json['sources']['file:///project/b.dart'], ['dart:core']);
+//      });
+//
+//      test('invalid source', () async {
+//        resourceProvider.newFile('/project/a.dart', 'import "b.dart";');
+//        server.setAnalysisRoots('0', ['/project/'], [], {});
+//
+//        await server.onAnalysisComplete;
+//
+//        var request =
+//            new AnalysisGetReachableSourcesParams('/does/not/exist.dart')
+//                .toRequest('0');
+//        var response = handler.handleRequest(request);
+//        expect(response.error, isNotNull);
+//        expect(response.error.code,
+//            RequestErrorCode.GET_REACHABLE_SOURCES_INVALID_FILE);
+//      });
+//    });
 
     group('setAnalysisRoots', () {
       Response testSetAnalysisRoots(
@@ -122,13 +124,7 @@
           resourceProvider.newFile(fileA, '// a');
           resourceProvider.newFile(fileB, '// b');
           var response = testSetAnalysisRoots(['/project'], ['/project/bbb']);
-          var serverRef = server;
           expect(response, isResponseSuccess('0'));
-          // unit "a" is resolved eventually
-          // unit "b" is not resolved
-          await server.onAnalysisComplete;
-          expect(await serverRef.getResolvedCompilationUnit(fileA), isNotNull);
-          expect(await serverRef.getResolvedCompilationUnit(fileB), isNull);
         });
 
         test('not absolute', () async {
@@ -195,12 +191,10 @@
 
     group('setPriorityFiles', () {
       test('invalid', () {
-        // TODO(paulberry): under the "eventual consistency" model this request
-        // should not be invalid.
         var request = new AnalysisSetPriorityFilesParams(['/project/lib.dart'])
             .toRequest('0');
         var response = handler.handleRequest(request);
-        expect(response, isResponseFailure('0'));
+        expect(response, isResponseSuccess('0'));
       });
 
       test('valid', () {
@@ -452,7 +446,7 @@
         new MockPackageMapProvider(),
         null,
         serverPlugin,
-        new AnalysisServerOptions()..enableNewAnalysisDriver = true,
+        new AnalysisServerOptions(),
         new DartSdkManager('/', false),
         InstrumentationService.NULL_SERVICE);
     handler = new AnalysisDomainHandler(server);
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index 6c58a73..5ad98b0 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -5,13 +5,10 @@
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_execution.dart';
 import 'package:analysis_server/src/plugin/server_plugin.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -84,115 +81,88 @@
       });
     });
 
-    group('mapUri', () {
-      String contextId;
-
-      void createExecutionContextIdForFile(String path) {
-        Request request = new ExecutionCreateContextParams(path).toRequest('0');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseSuccess('0'));
-        ExecutionCreateContextResult result =
-            new ExecutionCreateContextResult.fromResponse(response);
-        contextId = result.id;
-      }
-
-      setUp(() {
-        Folder folder = provider.newFile('/a/b.dart', '').parent;
-        server.folderMap.putIfAbsent(folder, () {
-          SourceFactory factory =
-              new SourceFactory([new ResourceUriResolver(provider)]);
-          AnalysisContext context =
-              AnalysisEngine.instance.createAnalysisContext();
-          context.sourceFactory = factory;
-          return context;
-        });
-        createExecutionContextIdForFile('/a/b.dart');
-      });
-
-      tearDown(() {
-        Request request =
-            new ExecutionDeleteContextParams(contextId).toRequest('1');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseSuccess('1'));
-      });
-
-      group('file to URI', () {
-        test('does not exist', () {
-          Request request =
-              new ExecutionMapUriParams(contextId, file: '/a/c.dart')
-                  .toRequest('2');
-          Response response = handler.handleRequest(request);
-          expect(response, isResponseFailure('2'));
-        });
-
-        test('directory', () {
-          provider.newFolder('/a/d');
-          Request request =
-              new ExecutionMapUriParams(contextId, file: '/a/d').toRequest('2');
-          Response response = handler.handleRequest(request);
-          expect(response, isResponseFailure('2'));
-        });
-      });
-
-      group('URI to file', () {
-        test('invalid', () {
-          Request request =
-              new ExecutionMapUriParams(contextId, uri: 'foo:///a/b.dart')
-                  .toRequest('2');
-          Response response = handler.handleRequest(request);
-          expect(response, isResponseFailure('2'));
-        });
-      });
-
-      test('invalid context id', () {
-        Request request =
-            new ExecutionMapUriParams('xxx', uri: '').toRequest('4');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseFailure('4'));
-      });
-
-      test('both file and uri', () {
-        Request request =
-            new ExecutionMapUriParams('xxx', file: '', uri: '').toRequest('5');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseFailure('5'));
-      });
-
-      test('neither file nor uri', () {
-        Request request = new ExecutionMapUriParams('xxx').toRequest('6');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseFailure('6'));
-      });
-    });
-
-    group('setSubscriptions', () {
-      test('failure - invalid service name', () {
-        expect(handler.onFileAnalyzed, isNull);
-
-        Request request = new Request('0', EXECUTION_SET_SUBSCRIPTIONS, {
-          SUBSCRIPTIONS: ['noSuchService']
-        });
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseFailure('0'));
-        expect(handler.onFileAnalyzed, isNull);
-      });
-
-      test('success - setting and clearing', () {
-        expect(handler.onFileAnalyzed, isNull);
-
-        Request request =
-            new ExecutionSetSubscriptionsParams([ExecutionService.LAUNCH_DATA])
-                .toRequest('0');
-        Response response = handler.handleRequest(request);
-        expect(response, isResponseSuccess('0'));
-        expect(handler.onFileAnalyzed, isNotNull);
-
-        request = new ExecutionSetSubscriptionsParams([]).toRequest('0');
-        response = handler.handleRequest(request);
-        expect(response, isResponseSuccess('0'));
-        expect(handler.onFileAnalyzed, isNull);
-      });
-    });
+    // TODO(brianwilkerson) Re-enable these tests if we re-enable the
+    // execution.mapUri request.
+//    group('mapUri', () {
+//      String contextId;
+//
+//      void createExecutionContextIdForFile(String path) {
+//        Request request = new ExecutionCreateContextParams(path).toRequest('0');
+//        Response response = handler.handleRequest(request);
+//        expect(response, isResponseSuccess('0'));
+//        ExecutionCreateContextResult result =
+//            new ExecutionCreateContextResult.fromResponse(response);
+//        contextId = result.id;
+//      }
+//
+//      setUp(() {
+//        Folder folder = provider.newFile('/a/b.dart', '').parent;
+//        server.folderMap.putIfAbsent(folder, () {
+//          SourceFactory factory =
+//              new SourceFactory([new ResourceUriResolver(provider)]);
+//          AnalysisContext context =
+//              AnalysisEngine.instance.createAnalysisContext();
+//          context.sourceFactory = factory;
+//          return context;
+//        });
+//        createExecutionContextIdForFile('/a/b.dart');
+//      });
+//
+//      tearDown(() {
+//        Request request =
+//            new ExecutionDeleteContextParams(contextId).toRequest('1');
+//        Response response = handler.handleRequest(request);
+//        expect(response, isResponseSuccess('1'));
+//      });
+//
+//      group('file to URI', () {
+//        test('does not exist', () {
+//          Request request =
+//              new ExecutionMapUriParams(contextId, file: '/a/c.dart')
+//                  .toRequest('2');
+//          Response response = handler.handleRequest(request);
+//          expect(response, isResponseFailure('2'));
+//        });
+//
+//        test('directory', () {
+//          provider.newFolder('/a/d');
+//          Request request =
+//              new ExecutionMapUriParams(contextId, file: '/a/d').toRequest('2');
+//          Response response = handler.handleRequest(request);
+//          expect(response, isResponseFailure('2'));
+//        });
+//      });
+//
+//      group('URI to file', () {
+//        test('invalid', () {
+//          Request request =
+//              new ExecutionMapUriParams(contextId, uri: 'foo:///a/b.dart')
+//                  .toRequest('2');
+//          Response response = handler.handleRequest(request);
+//          expect(response, isResponseFailure('2'));
+//        });
+//      });
+//
+//      test('invalid context id', () {
+//        Request request =
+//            new ExecutionMapUriParams('xxx', uri: '').toRequest('4');
+//        Response response = handler.handleRequest(request);
+//        expect(response, isResponseFailure('4'));
+//      });
+//
+//      test('both file and uri', () {
+//        Request request =
+//            new ExecutionMapUriParams('xxx', file: '', uri: '').toRequest('5');
+//        Response response = handler.handleRequest(request);
+//        expect(response, isResponseFailure('5'));
+//      });
+//
+//      test('neither file nor uri', () {
+//        Request request = new ExecutionMapUriParams('xxx').toRequest('6');
+//        Response response = handler.handleRequest(request);
+//        expect(response, isResponseFailure('6'));
+//      });
+//    });
   });
 }
 
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index dc303a3..ccb388e 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -3977,7 +3977,10 @@
     Token endToken = node.endToken;
     // Don't include synthetic tokens.
     while (endToken != beginToken) {
-      if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
+      // Fasta scanner reports unterminated string literal errors
+      // and generates a synthetic string token with non-zero length.
+      // Because of this, check for length > 0 rather than !isSynthetic.
+      if (endToken.type == TokenType.EOF || endToken.length > 0) {
         break;
       }
       endToken = endToken.previous;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 58b3e7b..a9b5a8b 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -475,7 +475,7 @@
         }
         String variableName =
             argumentCount < 1 ? null : argumentValues[0].toStringValue();
-        if (identical(definingClass, typeProvider.boolType)) {
+        if (definingClass == typeProvider.boolType) {
           DartObject valueFromEnvironment;
           valueFromEnvironment =
               _declaredVariables.getBool(typeProvider, variableName);
@@ -483,7 +483,7 @@
               valueFromEnvironment,
               new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
               namedArgumentValues);
-        } else if (identical(definingClass, typeProvider.intType)) {
+        } else if (definingClass == typeProvider.intType) {
           DartObject valueFromEnvironment;
           valueFromEnvironment =
               _declaredVariables.getInt(typeProvider, variableName);
@@ -491,7 +491,7 @@
               valueFromEnvironment,
               new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
               namedArgumentValues);
-        } else if (identical(definingClass, typeProvider.stringType)) {
+        } else if (definingClass == typeProvider.stringType) {
           DartObject valueFromEnvironment;
           valueFromEnvironment =
               _declaredVariables.getString(typeProvider, variableName);
@@ -501,7 +501,7 @@
               namedArgumentValues);
         }
       } else if (constructor.name == "" &&
-          identical(definingClass, typeProvider.symbolType) &&
+          definingClass == typeProvider.symbolType &&
           argumentCount == 1) {
         if (!checkSymbolArguments(
             arguments, argumentValues, namedArgumentValues)) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 7d9e91e..3e77604 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -7449,7 +7449,7 @@
   @override
   bool get hasImplicitType {
     if (_unlinkedParam != null) {
-      return _unlinkedParam.type == null;
+      return _unlinkedParam.type == null && !_unlinkedParam.isFunctionTyped;
     }
     return super.hasImplicitType;
   }
diff --git a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
index 9a26298..492bb6f 100644
--- a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
+++ b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
@@ -999,7 +999,7 @@
 
   ast.Statement visitAssertStatement(AssertStatement node) {
     return new ast.AssertStatement(scope.buildExpression(node.condition),
-        scope.buildOptionalExpression(node.message));
+        message: scope.buildOptionalExpression(node.message));
   }
 
   ast.Statement visitBlock(Block node) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 42025c2..ef645ec 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -8417,6 +8417,14 @@
     }
   }
 
+  test_function_typed_parameter_implicit() {
+    var library = checkLibrary('f(g()) => null;');
+    expect(
+        library
+            .definingCompilationUnit.functions[0].parameters[0].hasImplicitType,
+        isFalse);
+  }
+
   test_functions() {
     var library = checkLibrary('f() {} g() {}');
     if (isStrongMode) {
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 9ea09a0..daa8904 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -27,6 +27,7 @@
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
+import 'package:front_end/src/scanner/scanner.dart' as fe;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -3261,7 +3262,12 @@
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
     expect(outputs[INCLUDED_PARTS], hasLength(1));
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(2));
-    expect(outputs[PARSE_ERRORS], hasLength(1));
+    if (fe.Scanner.useFasta) {
+      // Missing closing brace error is reported by the Fasta scanner.
+      expect(outputs[PARSE_ERRORS], hasLength(0));
+    } else {
+      expect(outputs[PARSE_ERRORS], hasLength(1));
+    }
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(5));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
@@ -4387,6 +4393,23 @@
     expect(ignoreInfo.hasIgnores, isFalse);
   }
 
+  test_perform_library() {
+    _performScanTask(r'''
+library lib;
+import 'lib2.dart';
+export 'lib3.dart';
+part 'part.dart';
+class A {''');
+    expect(outputs, hasLength(4));
+    expect(outputs[LINE_INFO], isNotNull);
+    // Missing closing brace error is reported by the Fasta scanner.
+    expect(outputs[SCAN_ERRORS], hasLength(fe.Scanner.useFasta ? 1 : 0));
+    expect(outputs[TOKEN_STREAM], isNotNull);
+    IgnoreInfo ignoreInfo = outputs[IGNORE_INFO];
+    expect(ignoreInfo, isNotNull);
+    expect(ignoreInfo.hasIgnores, isFalse);
+  }
+
   test_perform_noErrors() {
     _performScanTask('class A {}');
     expect(outputs, hasLength(4));
@@ -4418,7 +4441,12 @@
 
     computeResult(script, TOKEN_STREAM, matcher: isScanDartTask);
     expect(outputs[LINE_INFO], isNotNull);
-    expect(outputs[SCAN_ERRORS], isEmpty);
+    if (fe.Scanner.useFasta) {
+      // Missing closing brace error is reported by Fasta scanner.
+      expect(outputs[SCAN_ERRORS], hasLength(1));
+    } else {
+      expect(outputs[SCAN_ERRORS], isEmpty);
+    }
     Token tokenStream = outputs[TOKEN_STREAM];
     expect(tokenStream, isNotNull);
     expect(tokenStream.lexeme, 'void');
diff --git a/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart b/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
index 018ffaf..da235af 100644
--- a/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
@@ -452,6 +452,25 @@
     }
   }
 
+  @override
+  visitMethodDeclaration(MethodDeclaration node) {
+    super.visitMethodDeclaration(node);
+    if (node.element.enclosingElement is ClassElement) {
+      if (node.isGetter && node.returnType == null) {
+        _recordTopType(node.name.offset, node.element.returnType);
+      }
+      if (node.isSetter) {
+        for (var parameter in node.parameters.parameters) {
+          // Note: it's tempting to check `parameter.type == null`, but that
+          // doesn't work because of function-typed formal parameter syntax.
+          if (parameter.element.hasImplicitType) {
+            _recordTopType(parameter.identifier.offset, parameter.element.type);
+          }
+        }
+      }
+    }
+  }
+
   visitMethodInvocation(MethodInvocation node) {
     super.visitMethodInvocation(node);
     if (node.typeArguments == null) {
@@ -507,7 +526,7 @@
         VariableElement element = variable.element;
         if (element is LocalVariableElement) {
           _recordType(variable.name.offset, element.type);
-        } else {
+        } else if (!element.isStatic || element.initializer != null) {
           _recordTopType(variable.name.offset, element.type);
         }
       }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 9df4db1..b825a84 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -3,9 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -252,6 +255,51 @@
   }
 
   /**
+   * Return a source range that represents the region of text that should be
+   * replaced when a suggestion based on this target is selected, given that the
+   * completion was requested at the given [requestOffset].
+   */
+  SourceRange computeReplacementRange(int requestOffset) {
+    bool isKeywordOrIdentifier(Token token) =>
+        token.type.isKeyword || token.type == TokenType.IDENTIFIER;
+
+    Token token = entity is AstNode ? (entity as AstNode).beginToken : entity;
+    if (token != null && requestOffset < token.offset) {
+      token = token.previous;
+    }
+    if (token != null) {
+      if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) {
+        // If the insertion point is at the beginning of the current token
+        // and the current token is not an identifier
+        // then check the previous token to see if it should be replaced
+        token = token.previous;
+      }
+      if (token != null && isKeywordOrIdentifier(token)) {
+        if (token.offset <= requestOffset && requestOffset <= token.end) {
+          // Replacement range for typical identifier completion
+          return new SourceRange(token.offset, token.length);
+        }
+      }
+      if (token is StringToken) {
+        SimpleStringLiteral uri =
+            astFactory.simpleStringLiteral(token, token.lexeme);
+        Keyword keyword = token.previous?.keyword;
+        if (keyword == Keyword.IMPORT ||
+            keyword == Keyword.EXPORT ||
+            keyword == Keyword.PART) {
+          int start = uri.contentsOffset;
+          int end = uri.contentsEnd;
+          if (start <= requestOffset && requestOffset <= end) {
+            // Replacement range for import URI
+            return new SourceRange(start, end - start);
+          }
+        }
+      }
+    }
+    return new SourceRange(requestOffset, 0);
+  }
+
+  /**
    * Return `true` if the target is a functional argument in an argument list.
    * The target [AstNode] hierarchy *must* be resolved for this to work.
    * See [maybeFunctionalArgument].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/replacement_range.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/replacement_range.dart
deleted file mode 100644
index 0ec18fc..0000000
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/replacement_range.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
-
-/**
- * Utility class for computing the code completion replacement range
- */
-class ReplacementRange {
-  int offset;
-  int length;
-
-  ReplacementRange(this.offset, this.length);
-
-  factory ReplacementRange.compute(int requestOffset, CompletionTarget target) {
-    bool isKeywordOrIdentifier(Token token) =>
-        token.type.isKeyword || token.type == TokenType.IDENTIFIER;
-
-    //TODO(danrubel) Ideally this needs to be pushed down into the contributors
-    // but that implies that each suggestion can have a different
-    // replacement offsent/length which would mean an API change
-
-    var entity = target.entity;
-    Token token = entity is AstNode ? entity.beginToken : entity;
-    if (token != null && requestOffset < token.offset) {
-      token = token.previous;
-    }
-    if (token != null) {
-      if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) {
-        // If the insertion point is at the beginning of the current token
-        // and the current token is not an identifier
-        // then check the previous token to see if it should be replaced
-        token = token.previous;
-      }
-      if (token != null && isKeywordOrIdentifier(token)) {
-        if (token.offset <= requestOffset && requestOffset <= token.end) {
-          // Replacement range for typical identifier completion
-          return new ReplacementRange(token.offset, token.length);
-        }
-      }
-      if (token is StringToken) {
-        SimpleStringLiteral uri =
-            astFactory.simpleStringLiteral(token, token.lexeme);
-        Keyword keyword = token.previous?.keyword;
-        if (keyword == Keyword.IMPORT ||
-            keyword == Keyword.EXPORT ||
-            keyword == Keyword.PART) {
-          int start = uri.contentsOffset;
-          var end = uri.contentsEnd;
-          if (start <= requestOffset && requestOffset <= end) {
-            // Replacement range for import URI
-            return new ReplacementRange(start, end - start);
-          }
-        }
-      }
-    }
-    return new ReplacementRange(requestOffset, 0);
-  }
-}
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
index ddceaf7..92584f8 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
@@ -17,7 +17,6 @@
 
 import '../../support/abstract_context.dart';
 import 'flutter_util.dart';
-import 'replacement_range.dart';
 
 int suggestionComparator(CompletionSuggestion s1, CompletionSuggestion s2) {
   String c1 = s1.completion.toLowerCase();
@@ -463,7 +462,7 @@
 
     CompletionTarget target =
         new CompletionTarget.forOffset(request.result.unit, request.offset);
-    var range = new ReplacementRange.compute(request.offset, target);
+    var range = target.computeReplacementRange(request.offset);
     replacementOffset = range.offset;
     replacementLength = range.length;
 
diff --git a/pkg/analyzer_plugin/test/utilities/completion/replacement_range.dart b/pkg/analyzer_plugin/test/utilities/completion/replacement_range.dart
deleted file mode 100644
index cb701f4..0000000
--- a/pkg/analyzer_plugin/test/utilities/completion/replacement_range.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
-
-/**
- * Utility class for computing the code completion replacement range.
- */
-class ReplacementRange {
-  // Copied from analysis_server/lib/src/services/completion/dart/completion_manager.dart
-  int offset;
-  int length;
-
-  ReplacementRange(this.offset, this.length);
-
-  factory ReplacementRange.compute(int requestOffset, CompletionTarget target) {
-    bool isKeywordOrIdentifier(Token token) =>
-        token.type.isKeyword || token.type == TokenType.IDENTIFIER;
-
-    //TODO(danrubel) Ideally this needs to be pushed down into the contributors
-    // but that implies that each suggestion can have a different replacement
-    // offset/length which would mean an API change.
-
-    var entity = target.entity;
-    Token token = entity is AstNode ? entity.beginToken : entity;
-    // TODO(brianwilkerson) If this class is every needed outside of tests, move
-    // the code below into RangeFactory and use a SourceRange rather than a
-    // ReplacementRange.
-    if (token != null && requestOffset < token.offset) {
-      token = token.previous;
-    }
-    if (token != null) {
-      if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) {
-        // If the insertion point is at the beginning of the current token
-        // and the current token is not an identifier
-        // then check the previous token to see if it should be replaced
-        token = token.previous;
-      }
-      if (token != null && isKeywordOrIdentifier(token)) {
-        if (token.offset <= requestOffset && requestOffset <= token.end) {
-          // Replacement range for typical identifier completion
-          return new ReplacementRange(token.offset, token.length);
-        }
-      }
-      if (token is StringToken) {
-        SimpleStringLiteral uri =
-            astFactory.simpleStringLiteral(token, token.lexeme);
-        Keyword keyword = token.previous?.keyword;
-        if (keyword == Keyword.IMPORT ||
-            keyword == Keyword.EXPORT ||
-            keyword == Keyword.PART) {
-          int start = uri.contentsOffset;
-          var end = uri.contentsEnd;
-          if (start <= requestOffset && requestOffset <= end) {
-            // Replacement range for import URI
-            return new ReplacementRange(start, end - start);
-          }
-        }
-      }
-    }
-    return new ReplacementRange(requestOffset, 0);
-  }
-}
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index 532b8b5..828c0cc 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  strong-mode: false
+  strong-mode: true
   language:
     enableSuperMixins: false
   errors:
diff --git a/pkg/compiler/analysis_options_dart.yaml b/pkg/compiler/analysis_options_dart.yaml
new file mode 100644
index 0000000..532b8b5
--- /dev/null
+++ b/pkg/compiler/analysis_options_dart.yaml
@@ -0,0 +1,12 @@
+# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+analyzer:
+  strong-mode: false
+  language:
+    enableSuperMixins: false
+  errors:
+    todo: ignore
+
+    deprecated_member_use: ignore
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index ec504bb..1620fda 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -119,7 +119,7 @@
     // setting up the current element of the compiler.
     return new Future.sync(
             () => callUserProvider(resourceUri, api.InputKind.utf8))
-        .then((SourceFile sourceFile) {
+        .then((api.Input sourceFile) {
       // We use [readableUri] as the URI for the script since need to preserve
       // the scheme in the script because [Script.uri] is used for resolving
       // relative URIs mentioned in the script. See the comment on
@@ -199,8 +199,9 @@
       // and we can't depend on 'dart:io' classes.
       packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
     } else if (options.packageConfig != null) {
-      return callUserProvider(options.packageConfig, api.InputKind.binary)
-          .then((Binary binary) {
+      Future<Binary> future =
+          callUserProvider(options.packageConfig, api.InputKind.binary);
+      return future.then((Binary binary) {
         packages =
             new MapPackages(pkgs.parse(binary.data, options.packageConfig));
       }).catchError((error) {
@@ -227,8 +228,9 @@
     if (options.resolutionInputs != null) {
       future = Future.forEach(options.resolutionInputs, (Uri resolutionInput) {
         reporter.log('Reading serialized data from ${resolutionInput}');
-        return callUserProvider(resolutionInput, api.InputKind.utf8)
-            .then((SourceFile sourceFile) {
+        Future<SourceFile> future =
+            callUserProvider(resolutionInput, api.InputKind.utf8);
+        return future.then((SourceFile sourceFile) {
           serialization.deserializeFromText(
               resolutionInput, sourceFile.slowText());
         });
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index fe1ebed..43a7dd4 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -4,6 +4,9 @@
 
 library dart2js.backend_strategy;
 
+import 'closure.dart' show ClosureConversionTask;
+import 'common/tasks.dart';
+import 'compiler.dart' show Compiler;
 import 'enqueue.dart';
 import 'io/source_information.dart';
 import 'js_backend/js_backend.dart';
@@ -19,8 +22,9 @@
   /// Create the [ClosedWorldRefiner] for [closedWorld].
   ClosedWorldRefiner createClosedWorldRefiner(ClosedWorld closedWorld);
 
-  /// Create closure classes for local functions.
-  void convertClosures(ClosedWorldRefiner closedWorldRefiner);
+  /// Create the task that analyzes the code to see what closures need to be
+  /// rewritten.
+  ClosureConversionTask createClosureConversionTask(Compiler compiler);
 
   /// The [Sorter] used for sorting elements in the generated code.
   Sorter get sorter;
@@ -34,8 +38,8 @@
   /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
   WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld);
 
-  /// Creates the [SsaBuilderTask] used for the element model.
-  SsaBuilderTask createSsaBuilderTask(JavaScriptBackend backend,
+  /// Creates the [SsaBuilder] used for the element model.
+  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
       SourceInformationStrategy sourceInformationStrategy);
 
   /// Returns the [SourceInformationStrategy] use for the element model.
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 1b0cb8b..59c0f46 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -2,11 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library closureToClassMapper;
-
 import 'common/names.dart' show Identifiers;
 import 'common/resolution.dart' show ParsingContext, Resolution;
-import 'common/tasks.dart' show CompilerTask;
+import 'common/tasks.dart' show CompilerTask, Measurer;
 import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'constants/expressions.dart';
@@ -25,10 +23,26 @@
 import 'util/util.dart';
 import 'world.dart' show ClosedWorldRefiner;
 
-/// Where T is ir.Node or Node.
-abstract class ClosureClassMaps<T> {
-  ClosureClassMap getMemberMap(MemberEntity member);
-  ClosureClassMap getLocalFunctionMap(Local localFunction);
+abstract class ClosureConversionTask<T> extends CompilerTask
+    implements ClosureDataLookup<T> {
+  ClosureConversionTask(Measurer measurer) : super(measurer);
+
+  //void analyzeClosures();
+  void convertClosures(Iterable<MemberEntity> processedEntities,
+      ClosedWorldRefiner closedWorldRefiner);
+}
+
+/// Class that provides information for how closures are rewritten/represented
+/// to preserve Dart semantics when compiled to JavaScript. Given a particular
+/// node to look up, it returns a information about the internal representation
+/// of how closure conversion is implemented. T is an ir.Node or Node.
+abstract class ClosureDataLookup<T> {
+  /// Look up information about the variables that have been mutated and are
+  /// used inside the scope of [node].
+  // TODO(johnniwinther): Split this up into two functions, one for members and
+  // one for local functions.
+  ClosureRepresentationInfo getClosureRepresentationInfo(
+      covariant Entity member);
 
   /// Look up information about a loop, in case any variables it declares need
   /// to be boxed/snapshotted.
@@ -49,7 +63,7 @@
   /// variable has been "captured"). In this situation, access to this variable
   /// is controlled via a wrapper (box) so that updates to this variable
   /// are done in a way that is in line with Dart's closure rules.
-  bool requiresContextBox() => false;
+  bool get requiresContextBox => false;
 
   /// Accessor to the local environment in which a particular closure node is
   /// executed. This will encapsulate the value of any variables that have been
@@ -76,8 +90,9 @@
 ///
 ///     var lst = [];
 ///     for (int i = 0; i < 5; i++) lst.add(()=>i);
+///     var result = list.map((f) => f()).toList();
 ///
-/// The result of `lst` will be [0, 1, 2, 3, 4], whereas were this JS code
+/// `result` will be [0, 1, 2, 3, 4], whereas were this JS code
 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to
 /// create a closure for these sorts of loops to capture the variable's value at
 /// each iteration, by boxing the iteration variable[s].
@@ -93,7 +108,107 @@
   List<Local> get boxedVariables => const <Local>[];
 }
 
-class ClosureTask extends CompilerTask implements ClosureClassMaps<Node> {
+/// Class that describes the actual mechanics of how the converted, rewritten
+/// closure is implemented. For example, for the following closure (named foo
+/// for convenience):
+///
+///   var foo = (x) => y + x;
+///
+/// We would produce the following class to control access to these variables in
+/// the following way (modulo naming of variables, assuming that y is modified
+/// elsewhere in its scope):
+///
+///    class FooClosure {
+///       int y;
+///       FooClosure(this.y);
+///       call(x) => this.y + x;
+///    }
+///
+///  and then to execute this closure, for example:
+///
+///     var foo = new FooClosure(1);
+///     foo.call(2);
+///
+/// if `y` is modified elsewhere within its scope, accesses to y anywhere in the
+/// code will be controlled via a box object.
+///
+/// Because in these examples `y` was declared in some other, outer scope, but
+/// used in the inner scope of this closure, we say `y` is a "captured"
+/// variable.
+/// TODO(efortuna): Make interface simpler in subsequent refactorings.
+class ClosureRepresentationInfo {
+  const ClosureRepresentationInfo();
+
+  /// The original local function before any translation.
+  ///
+  /// Will be null for methods.
+  Local get closureEntity => null;
+
+  /// The entity for the class used to represent the rewritten closure in the
+  /// emitted JavaScript.
+  ///
+  /// Closures are rewritten in the form of classes that have fields to control
+  /// the redirection and editing of captured variables.
+  ClassEntity get closureClassEntity => null;
+
+  /// The function that implements the [local] function as a `call` method on
+  /// the closure class.
+  FunctionEntity get callMethod => null;
+
+  /// As shown in the example in the comments at the top of this class, we
+  /// create fields in the closure class for each captured variable. This is an
+  /// accessor to that set of fields.
+  List<Local> get createdFieldEntities => const <Local>[];
+
+  /// Convenience reference pointer to the element representing `this`.
+  /// It is only set for instance-members.
+  Local get thisLocal => null;
+
+  /// Convenience pointer to the field entity representation in the closure
+  /// class of the element representing `this`.
+  FieldEntity get thisFieldEntity => null;
+
+  /// Returns true if this [variable] is used inside a `try` block or a `sync*`
+  /// generator (this is important to know because boxing/redirection needs to
+  /// happen for those local variables).
+  ///
+  /// Variables that are used in a try must be treated as boxed because the
+  /// control flow can be non-linear.
+  ///
+  /// Also parameters to a `sync*` generator must be boxed, because of the way
+  /// we rewrite sync* functions. See also comments in
+  /// [ClosureClassMap.useLocal].
+  bool variableIsUsedInTryOrSync(Local variable) => false;
+
+  /// Loop through every variable that has been captured in this closure. This
+  /// consists of all the free variables (variables captured *just* in this
+  /// closure) and all variables captured in nested scopes that we may be
+  /// capturing as well. These nested scopes hold "boxes" to hold the executable
+  /// context for that scope.
+  void forEachCapturedVariable(f(Local from, FieldEntity to)) {}
+
+  /// Loop through each variable that has been boxed in this closure class. Only
+  /// captured variables that are mutated need to be "boxed" (which basically
+  /// puts a thin layer between updates and reads to this variable to ensure
+  /// that every place that accesses it gets the correct updated value).
+  void forEachBoxedVariable(f(Local local, FieldEntity field)) {}
+
+  /// Loop through each free variable in this closure. Free variables are the
+  /// variables that have been captured *just* in this closure, not in nested
+  /// scopes.
+  void forEachFreeVariable(f(Local variable, FieldEntity field)) {}
+
+  /// Return true if [variable] has been captured and mutated (all other
+  /// variables do not require boxing).
+  bool isVariableBoxed(Local variable) => false;
+
+  // TODO(efortuna): Remove this method. The old system was using
+  // ClosureClassMaps for situations other than closure class maps, and that's
+  // just confusing.
+  bool get isClosure => false;
+}
+
+class ClosureTask extends ClosureConversionTask<Node> {
   Map<Node, ClosureScope> _closureInfoMap = <Node, ClosureScope>{};
   Map<Element, ClosureClassMap> _closureMappingCache =
       <Element, ClosureClassMap>{};
@@ -106,25 +221,26 @@
 
   DiagnosticReporter get reporter => compiler.reporter;
 
+  void convertClosures(Iterable<MemberEntity> processedEntities,
+      ClosedWorldRefiner closedWorldRefiner) {
+    createClosureClasses(closedWorldRefiner);
+  }
+
   ClosureAnalysisInfo getClosureAnalysisInfo(Node node) {
     var value = _closureInfoMap[node];
     return value == null ? const ClosureAnalysisInfo() : value;
   }
 
+  ClosureRepresentationInfo getClosureRepresentationInfo(Element member) {
+    return getClosureToClassMapping(member);
+  }
+
   LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
       Node loopNode) {
     var value = _closureInfoMap[loopNode];
     return value == null ? const LoopClosureRepresentationInfo() : value;
   }
 
-  ClosureClassMap getMemberMap(MemberElement member) {
-    return getClosureToClassMapping(member);
-  }
-
-  ClosureClassMap getLocalFunctionMap(LocalFunctionElement localFunction) {
-    return getClosureToClassMapping(localFunction);
-  }
-
   /// Returns the [ClosureClassMap] computed for [resolvedAst].
   ClosureClassMap getClosureToClassMapping(Element element) {
     return measure(() {
@@ -142,7 +258,8 @@
   /// Create [ClosureClassMap]s for all live members.
   void createClosureClasses(ClosedWorldRefiner closedWorldRefiner) {
     compiler.enqueuer.resolution.processedEntities
-        .forEach((MemberElement element) {
+        .forEach((MemberEntity _element) {
+      MemberElement element = _element;
       ResolvedAst resolvedAst = element.resolvedAst;
       if (element.isAbstract) return;
       if (element.isField &&
@@ -236,7 +353,7 @@
 
   bool get hasNode => false;
 
-  Node get node {
+  VariableDefinitions get node {
     throw new SpannableAssertionFailure(
         local, 'Should not access node of ClosureFieldElement.');
   }
@@ -272,7 +389,8 @@
     return visitor.visitClosureFieldElement(this, arg);
   }
 
-  Element get analyzableElement => closureClass.methodElement.analyzableElement;
+  AnalyzableElement get analyzableElement =>
+      closureClass.methodElement.analyzableElement;
 
   @override
   List<FunctionElement> get nestedClosures => const <FunctionElement>[];
@@ -411,7 +529,7 @@
   List<FunctionElement> get nestedClosures => const <FunctionElement>[];
 
   @override
-  Node get node {
+  VariableDefinitions get node {
     throw new UnsupportedError("BoxFieldElement.node");
   }
 
@@ -442,6 +560,7 @@
 }
 
 /// Call method of a closure class.
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class SynthesizedCallMethodElementX extends BaseFunctionElementX
     implements MethodElement {
   final LocalFunctionElement expression;
@@ -470,7 +589,8 @@
 
   FunctionExpression parseNode(ParsingContext parsing) => node;
 
-  Element get analyzableElement => closureClass.methodElement.analyzableElement;
+  AnalyzableElement get analyzableElement =>
+      closureClass.methodElement.analyzableElement;
 
   bool get hasResolvedAst => true;
 
@@ -500,7 +620,7 @@
 
   Local get context => boxElement;
 
-  bool requiresContextBox() => capturedVariables.keys.isNotEmpty;
+  bool get requiresContextBox => capturedVariables.keys.isNotEmpty;
 
   List<Local> get boxedVariables => boxedLoopVariables;
 
@@ -537,24 +657,24 @@
   }
 }
 
-class ClosureClassMap {
+class ClosureClassMap implements ClosureRepresentationInfo {
   /// The local function element before any translation.
   ///
   /// Will be null for methods.
-  final LocalFunctionElement closureElement;
+  final LocalFunctionElement closureEntity;
 
-  /// The synthesized closure class for [closureElement].
+  /// The synthesized closure class for [closureEntity].
   ///
-  /// The closureClassElement will be null for methods that are not local
+  /// The closureClassEntity will be null for methods that are not local
   /// closures.
-  final ClosureClassElement closureClassElement;
+  final ClosureClassElement closureClassEntity;
 
-  /// The synthesized `call` method of the [ closureClassElement].
+  /// The synthesized `call` method of the [closureClassEntity].
   ///
-  /// The callElement will be null for methods that are not local closures.
-  final MethodElement callElement;
+  /// The callMethod will be null for methods that are not local closures.
+  final MethodElement callMethod;
 
-  /// The [thisElement] makes handling 'this' easier by treating it like any
+  /// The [thisLocal] makes handling 'this' easier by treating it like any
   /// other argument. It is only set for instance-members.
   final ThisLocal thisLocal;
 
@@ -576,8 +696,17 @@
   // TODO(johnniwinther): Add variables to this only if the variable is mutated.
   final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>();
 
-  ClosureClassMap(this.closureElement, this.closureClassElement,
-      this.callElement, this.thisLocal);
+  ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod,
+      this.thisLocal);
+
+  List<Local> get createdFieldEntities {
+    List<Local> fields = <Local>[];
+    if (closureClassEntity == null) return const <Local>[];
+    closureClassEntity.closureFields.forEach((field) {
+      fields.add(field.local);
+    });
+    return fields;
+  }
 
   void addFreeVariable(Local element) {
     assert(freeVariableMap[element] == null);
@@ -594,14 +723,16 @@
     freeVariableMap.forEach(f);
   }
 
-  bool isVariableUsedInTryOrSync(Local variable) =>
+  FieldEntity get thisFieldEntity => freeVariableMap[thisLocal];
+
+  bool variableIsUsedInTryOrSync(Local variable) =>
       variablesUsedInTryOrGenerator.contains(variable);
 
   Local getLocalVariableForClosureField(ClosureFieldElement field) {
     return field.local;
   }
 
-  bool get isClosure => closureElement != null;
+  bool get isClosure => closureEntity != null;
 
   bool capturingScopesBox(Local variable) {
     return capturingScopes.values.any((scope) {
@@ -778,7 +909,7 @@
           boxes.add(boxFieldElement.box);
         }
       });
-      ClosureClassElement closureClass = data.closureClassElement;
+      ClosureClassElement closureClass = data.closureClassEntity;
       assert(closureClass != null || (fieldCaptures.isEmpty && boxes.isEmpty));
 
       void addClosureField(Local local, String name) {
@@ -834,7 +965,7 @@
       // things in the builder.
       // Note that nested (named) functions are immutable.
       if (variable != closureData.thisLocal &&
-          variable != closureData.closureElement &&
+          variable != closureData.closureEntity &&
           variable is! TypeVariableLocal) {
         closureData.variablesUsedInTryOrGenerator.add(variable);
       }
@@ -1221,8 +1352,8 @@
     }
     closureMappingCache[element] = closureData;
     closureMappingCache[element.declaration] = closureData;
-    if (closureData.callElement != null) {
-      closureMappingCache[closureData.callElement] = closureData;
+    if (closureData.callMethod != null) {
+      closureMappingCache[closureData.callMethod] = closureData;
     }
 
     inNewScope(node, () {
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index e6bf624..00b4925 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,7 +4,8 @@
 
 library dart2js.common.codegen;
 
-import '../elements/elements.dart' show ClassElement, LocalFunctionElement;
+import '../common_elements.dart';
+import '../elements/elements.dart' show LocalFunctionElement;
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType, InterfaceType;
 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
@@ -109,10 +110,11 @@
 // TODO(johnniwinther): Split this class into interface and implementation.
 // TODO(johnniwinther): Move this implementation to the JS backend.
 class CodegenRegistry {
+  final ElementEnvironment _elementEnvironment;
   final MemberEntity currentElement;
   final _CodegenImpact worldImpact;
 
-  CodegenRegistry(this.currentElement)
+  CodegenRegistry(this._elementEnvironment, this.currentElement)
       : this.worldImpact = new _CodegenImpact();
 
   bool get isForResolution => false;
@@ -120,8 +122,8 @@
   String toString() => 'CodegenRegistry for $currentElement';
 
   @deprecated
-  void registerInstantiatedClass(ClassElement element) {
-    registerInstantiation(element.rawType);
+  void registerInstantiatedClass(ClassEntity element) {
+    registerInstantiation(_elementEnvironment.getRawType(element));
   }
 
   void registerStaticUse(StaticUse staticUse) {
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 02576e0..2b56fd7 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -999,7 +999,7 @@
       CallStructure callStructure,
       List<AstConstant> normalizedArguments,
       List<AstConstant> concreteArguments) {
-    var firstArgument = normalizedArguments[0].value;
+    dynamic firstArgument = normalizedArguments[0].value;
     ConstantValue defaultValue = normalizedArguments[1].value;
 
     if (firstArgument.isNull) {
@@ -1239,7 +1239,8 @@
     // Assign arguments to parameters.
     FunctionSignature signature = constructor.functionSignature;
     int index = 0;
-    signature.orderedForEachParameter((ParameterElement parameter) {
+    signature.orderedForEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       AstConstant argument = arguments[index++];
       Node node = parameter.node;
       if (parameter.isInitializingFormal) {
@@ -1265,7 +1266,8 @@
 
       Map<FieldEntity, ConstantExpression> fields =
           expression.computeInstanceFields(new _CompilerEnvironment(compiler));
-      fields.forEach((FieldElement field, ConstantExpression expression) {
+      fields.forEach((_field, ConstantExpression expression) {
+        FieldElement field = _field;
         ConstantValue value = expression.evaluate(
             new _CompilerEnvironment(compiler), constantSystem);
         fieldValues[field] = new AstConstant(context, null, expression, value);
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index aa3a5ba..131462d 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -8,7 +8,7 @@
 
 import '../compiler_new.dart' as api;
 import 'backend_strategy.dart';
-import 'closure.dart' as closureMapping show ClosureTask;
+import 'closure.dart' as closureMapping show ClosureConversionTask;
 import 'common/names.dart' show Selectors;
 import 'common/names.dart' show Uris;
 import 'common/resolution.dart'
@@ -115,8 +115,7 @@
 
   ResolvedUriTranslator get resolvedUriTranslator;
 
-  LibraryEntity mainApp;
-  FunctionEntity mainFunction;
+  Uri mainLibraryUri;
 
   DiagnosticReporter get reporter => _reporter;
   Resolution get resolution => _resolution;
@@ -144,7 +143,7 @@
   LibraryLoaderTask libraryLoader;
   SerializationTask serialization;
   ResolverTask resolver;
-  closureMapping.ClosureTask closureToClassMapper;
+  closureMapping.ClosureConversionTask closureDataLookup;
   TypeCheckerTask checker;
   GlobalTypeInferenceTask globalInference;
   JavaScriptBackend backend;
@@ -226,7 +225,7 @@
           measurer),
       parser = new ParserTask(this),
       resolver = createResolverTask(),
-      closureToClassMapper = new closureMapping.ClosureTask(this),
+      closureDataLookup = backendStrategy.createClosureConversionTask(this),
       checker = new TypeCheckerTask(this),
       globalInference = new GlobalTypeInferenceTask(this),
       constants = backend.constantCompilerTask,
@@ -433,6 +432,7 @@
   Uri resolvePatchUri(String dartLibraryPath);
 
   Future runInternal(Uri uri) async {
+    mainLibraryUri = uri;
     // TODO(ahe): This prevents memory leaks when invoking the compiler
     // multiple times. Implement a better mechanism where we can store
     // such caches in the compiler and get access to them through a
@@ -457,6 +457,7 @@
         processLoadedLibraries(loadedLibraries);
       });
     }
+    LibraryEntity mainApp;
     if (uri != null) {
       if (options.analyzeOnly) {
         reporter.log('Analyzing $uri (${options.buildId})');
@@ -515,7 +516,8 @@
       selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
         ResolutionEnqueuer resolutionEnqueuer = startResolution();
         WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
-        mainFunction = frontendStrategy.computeMain(rootLibrary, mainImpact);
+        FunctionEntity mainFunction =
+            frontendStrategy.computeMain(rootLibrary, mainImpact);
 
         if (!options.loadFromDill) {
           // TODO(johnniwinther): Support mirrors usages analysis from dill.
@@ -526,7 +528,7 @@
         // compile-time constants that are metadata.  This means adding
         // something to the resolution queue.  So we cannot wait with
         // this until after the resolution queue is processed.
-        deferredLoadTask.beforeResolution(this);
+        deferredLoadTask.beforeResolution(rootLibrary);
         impactStrategy = backend.createImpactStrategy(
             supportDeferredLoad: deferredLoadTask.isProgramSplit,
             supportDumpInfo: options.dumpInfo,
@@ -596,8 +598,9 @@
         if (options.analyzeOnly) return;
         assert(mainFunction != null);
 
-        ClosedWorldRefiner closedWorldRefiner = closeResolution();
+        ClosedWorldRefiner closedWorldRefiner = closeResolution(mainFunction);
         ClosedWorld closedWorld = closedWorldRefiner.closedWorld;
+        mainFunction = closedWorld.elementEnvironment.mainFunction;
 
         reporter.log('Inferring types...');
         globalInference.runGlobalTypeInference(
@@ -610,10 +613,7 @@
         reporter.log('Compiling...');
         phase = PHASE_COMPILING;
 
-        Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld);
-        _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
-        codegenEnqueuer.applyImpact(
-            backend.onCodegenStart(closedWorld, _codegenWorldBuilder));
+        Enqueuer codegenEnqueuer = startCodegen(closedWorld);
         if (compileAll) {
           libraryLoader.libraries.forEach((LibraryEntity library) {
             codegenEnqueuer.applyImpact(computeImpactForLibrary(library));
@@ -636,8 +636,16 @@
         checkQueues(resolutionEnqueuer, codegenEnqueuer);
       });
 
+  Enqueuer startCodegen(ClosedWorld closedWorld) {
+    Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld);
+    _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
+    codegenEnqueuer
+        .applyImpact(backend.onCodegenStart(closedWorld, _codegenWorldBuilder));
+    return codegenEnqueuer;
+  }
+
   /// Perform the steps needed to fully end the resolution phase.
-  ClosedWorldRefiner closeResolution() {
+  ClosedWorldRefiner closeResolution(FunctionEntity mainFunction) {
     phase = PHASE_DONE_RESOLVING;
 
     ClosedWorld closedWorld = resolutionWorldBuilder.closeWorld();
@@ -651,7 +659,8 @@
 
     // TODO(johnniwinther): Move this after rti computation but before
     // reflection members computation, and (re-)close the world afterwards.
-    backendStrategy.convertClosures(closedWorldRefiner);
+    closureDataLookup.convertClosures(
+        enqueuer.resolution.processedEntities, closedWorldRefiner);
     return closedWorldRefiner;
   }
 
@@ -910,8 +919,8 @@
   Iterable<CodeLocation> computeUserCodeLocations(
       {bool assumeInUserCode: false}) {
     List<CodeLocation> userCodeLocations = <CodeLocation>[];
-    if (mainApp != null) {
-      userCodeLocations.add(new CodeLocation(mainApp.canonicalUri));
+    if (mainLibraryUri != null) {
+      userCodeLocations.add(new CodeLocation(mainLibraryUri));
     }
     if (librariesToAnalyzeWhenRun != null) {
       userCodeLocations.addAll(
@@ -955,7 +964,7 @@
         // Record as global error.
         // TODO(zarah): Extend element model to represent compile-time
         // errors instead of using a map.
-        element = mainFunction;
+        element = frontendStrategy.elementEnvironment.mainFunction;
       }
       elementsWithCompileTimeErrors
           .putIfAbsent(element, () => <DiagnosticMessage>[])
diff --git a/pkg/compiler/lib/src/constants/constant_constructors.dart b/pkg/compiler/lib/src/constants/constant_constructors.dart
index 2da30e0..d65b873 100644
--- a/pkg/compiler/lib/src/constants/constant_constructors.dart
+++ b/pkg/compiler/lib/src/constants/constant_constructors.dart
@@ -72,7 +72,7 @@
     internalError(node, template.replaceFirst('#', '$node'));
   }
 
-  internalError(Node node, String message) {
+  internalError(Spannable node, String message) {
     throw new UnsupportedError(message);
   }
 
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index c0b3d12..0e1ec12 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -39,15 +39,19 @@
 abstract class ConstantConstructorVisitor<R, A> {
   const ConstantConstructorVisitor();
 
-  R visit(ConstantConstructor constantConstructor, A context) {
+  R visit(
+      covariant ConstantConstructor constantConstructor, covariant A context) {
     return constantConstructor.accept(this, context);
   }
 
-  R visitGenerative(GenerativeConstantConstructor constructor, A arg);
+  R visitGenerative(
+      covariant GenerativeConstantConstructor constructor, covariant A arg);
   R visitRedirectingGenerative(
-      RedirectingGenerativeConstantConstructor constructor, A arg);
+      covariant RedirectingGenerativeConstantConstructor constructor,
+      covariant A arg);
   R visitRedirectingFactory(
-      RedirectingFactoryConstantConstructor constructor, A arg);
+      covariant RedirectingFactoryConstantConstructor constructor,
+      covariant A arg);
 }
 
 /// A generative constant constructor.
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index d94e552..cc49c0f 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -20,18 +20,20 @@
   String readFromEnvironment(String name);
 
   /// Returns the [ConstantExpression] for the value of the constant [local].
-  ConstantExpression getLocalConstant(Local local);
+  ConstantExpression getLocalConstant(covariant Local local);
 
   /// Returns the [ConstantExpression] for the value of the constant [field].
-  ConstantExpression getFieldConstant(FieldEntity field);
+  ConstantExpression getFieldConstant(covariant FieldEntity field);
 
   /// Returns the [ConstantConstructor] corresponding to the constant
   /// [constructor].
-  ConstantConstructor getConstructorConstant(ConstructorEntity constructor);
+  ConstantConstructor getConstructorConstant(
+      covariant ConstructorEntity constructor);
 
   /// Performs the substitution of the type arguments of [target] for their
   /// corresponding type variables in [type].
-  InterfaceType substByContext(InterfaceType base, InterfaceType target);
+  InterfaceType substByContext(
+      covariant InterfaceType base, covariant InterfaceType target);
 }
 
 /// The normalized arguments passed to a const constructor computed from the
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 1387ca4..159488a 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -98,7 +98,7 @@
 
   int get hashCode => _hashCode ??= _computeHashCode();
 
-  bool _equals(ConstantExpression other);
+  bool _equals(covariant ConstantExpression other);
 
   bool operator ==(other) {
     if (identical(this, other)) return true;
@@ -738,10 +738,12 @@
   final String name;
 
   TypeConstantExpression(this.type, this.name) {
-    assert(type.isInterfaceType ||
-        type.isTypedef ||
-        type.isFunctionType ||
-        type.isDynamic);
+    assert(
+        type.isInterfaceType ||
+            type.isTypedef ||
+            type.isFunctionType ||
+            type.isDynamic,
+        "Unexpected type constant type: $type");
   }
 
   ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 0818f91..73e39c1 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -30,20 +30,22 @@
 abstract class ConstantValueVisitor<R, A> {
   const ConstantValueVisitor();
 
-  R visitFunction(FunctionConstantValue constant, A arg);
-  R visitNull(NullConstantValue constant, A arg);
-  R visitInt(IntConstantValue constant, A arg);
-  R visitDouble(DoubleConstantValue constant, A arg);
-  R visitBool(BoolConstantValue constant, A arg);
-  R visitString(StringConstantValue constant, A arg);
-  R visitList(ListConstantValue constant, A arg);
-  R visitMap(MapConstantValue constant, A arg);
-  R visitConstructed(ConstructedConstantValue constant, A arg);
-  R visitType(TypeConstantValue constant, A arg);
-  R visitInterceptor(InterceptorConstantValue constant, A arg);
-  R visitSynthetic(SyntheticConstantValue constant, A arg);
-  R visitDeferred(DeferredConstantValue constant, A arg);
-  R visitNonConstant(NonConstantValue constant, A arg);
+  R visitFunction(covariant FunctionConstantValue constant, covariant A arg);
+  R visitNull(covariant NullConstantValue constant, covariant A arg);
+  R visitInt(covariant IntConstantValue constant, covariant A arg);
+  R visitDouble(covariant DoubleConstantValue constant, covariant A arg);
+  R visitBool(covariant BoolConstantValue constant, covariant A arg);
+  R visitString(covariant StringConstantValue constant, covariant A arg);
+  R visitList(covariant ListConstantValue constant, covariant A arg);
+  R visitMap(covariant MapConstantValue constant, covariant A arg);
+  R visitConstructed(
+      covariant ConstructedConstantValue constant, covariant A arg);
+  R visitType(covariant TypeConstantValue constant, covariant A arg);
+  R visitInterceptor(
+      covariant InterceptorConstantValue constant, covariant A arg);
+  R visitSynthetic(covariant SyntheticConstantValue constant, covariant A arg);
+  R visitDeferred(covariant DeferredConstantValue constant, covariant A arg);
+  R visitNonConstant(covariant NonConstantValue constant, covariant A arg);
 }
 
 abstract class ConstantValue {
diff --git a/pkg/compiler/lib/src/dart2js_resolver.dart b/pkg/compiler/lib/src/dart2js_resolver.dart
index 2bf460e..46ba18e 100644
--- a/pkg/compiler/lib/src/dart2js_resolver.dart
+++ b/pkg/compiler/lib/src/dart2js_resolver.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/src/serialization/json_serializer.dart';
 import 'package:compiler/src/source_file_provider.dart';
 import 'package:package_config/discovery.dart';
+import 'package:compiler/src/elements/elements.dart';
 
 Future<String> resolve(List<Uri> inputs,
     {List<String> deps: const <String>[],
@@ -52,7 +53,7 @@
   await compiler.setupSdk();
   await compiler.setupPackages(inputs.first);
 
-  var librariesToSerialize = [];
+  var librariesToSerialize = <LibraryElement>[];
   for (var uri in inputs) {
     var library = await compiler.analyzeUri(uri);
     if (library != null) {
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 971a1d9..c3c4d7a 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -70,8 +70,9 @@
 
   String toString() => "OutputUnit($name)";
 
-  bool operator ==(OutputUnit other) {
-    return imports.length == other.imports.length &&
+  bool operator ==(other) {
+    return other is OutputUnit &&
+        imports.length == other.imports.length &&
         imports.containsAll(other.imports);
   }
 
@@ -444,7 +445,8 @@
       // If we see a class, add everything its live instance members refer
       // to.  Static members are not relevant, unless we are processing
       // extra dependencies due to mirrors.
-      void addLiveInstanceMember(_, MemberElement element) {
+      void addLiveInstanceMember(_, _element) {
+        MemberElement element = _element;
         if (!compiler.resolutionWorldBuilder.isMemberUsed(element)) return;
         if (!isMirrorUsage && !element.isInstanceMember) return;
         elements.add(element);
@@ -790,11 +792,11 @@
     compiler.impactStrategy.onImpactUsed(IMPACT_USE);
   }
 
-  void beforeResolution(Compiler compiler) {
-    if (compiler.mainApp == null) return;
+  void beforeResolution(LibraryEntity mainLibrary) {
+    if (mainLibrary == null) return;
     // TODO(johnniwinther): Support deferred load for kernel based elements.
     if (compiler.options.loadFromDill) return;
-    _allDeferredImports[_fakeMainImport] = compiler.mainApp;
+    _allDeferredImports[_fakeMainImport] = mainLibrary;
     var lastDeferred;
     // When detecting duplicate prefixes of deferred libraries there are 4
     // cases of duplicate prefixes:
@@ -854,8 +856,9 @@
                   import, MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
             } else {
               prefixDeferredImport[prefix] = import;
+              Uri mainLibraryUri = compiler.mainLibraryUri;
               _deferredImportDescriptions[key] =
-                  new ImportDescription(import, library, compiler);
+                  new ImportDescription(import, library, mainLibraryUri);
             }
             isProgramSplit = true;
             lastDeferred = import;
@@ -1030,9 +1033,9 @@
   final LibraryElement _importingLibrary;
 
   ImportDescription(
-      ImportElement import, LibraryElement importingLibrary, Compiler compiler)
-      : importingUri = uri_extras.relativize(compiler.mainApp.canonicalUri,
-            importingLibrary.canonicalUri, false),
+      ImportElement import, LibraryElement importingLibrary, Uri mainLibraryUri)
+      : importingUri = uri_extras.relativize(
+            mainLibraryUri, importingLibrary.canonicalUri, false),
         prefix = import.prefix.name,
         _importingLibrary = importingLibrary;
 
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index fcecf0c..c8b36b8 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -32,7 +32,7 @@
   final ClosedWorld closedWorld;
 
   final AllInfo result = new AllInfo();
-  final Map<Element, Info> _elementToInfo = <Element, Info>{};
+  final Map<Entity, Info> _elementToInfo = <Entity, Info>{};
   final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{};
   final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {};
 
@@ -65,7 +65,7 @@
   }
 
   /// Visits [element] and produces it's corresponding info.
-  Info process(Element element) {
+  Info process(Entity element) {
     // TODO(sigmund): change the visit order to eliminate the need to check
     // whether or not an element has been processed.
     return _elementToInfo.putIfAbsent(element, () => visit(element));
@@ -214,11 +214,11 @@
         size: compiler.dumpInfoTask.sizeOf(element));
     _elementToInfo[element] = closureInfo;
 
-    ClosureClassMap closureMap = compiler.closureToClassMapper
-        .getClosureToClassMapping(element.methodElement);
-    assert(closureMap != null && closureMap.closureClassElement == element);
+    ClosureRepresentationInfo closureRepresentation = compiler.closureDataLookup
+        .getClosureRepresentationInfo(element.methodElement);
+    assert(closureRepresentation.closureClassEntity == element);
 
-    FunctionInfo functionInfo = this.process(closureMap.callElement);
+    FunctionInfo functionInfo = this.process(closureRepresentation.callMethod);
     if (functionInfo == null) return null;
     closureInfo.function = functionInfo;
     functionInfo.parent = closureInfo;
@@ -367,7 +367,7 @@
 }
 
 class Selection {
-  final Element selectedElement;
+  final Entity selectedElement;
   final ReceiverConstraint mask;
   Selection(this.selectedElement, this.mask);
 }
@@ -458,7 +458,7 @@
         new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) {
           selections.addAll(closedWorld
               .locateMembers(dynamicUse.selector, dynamicUse.mask)
-              .map((MemberElement e) => new Selection(e, dynamicUse.mask)));
+              .map((MemberEntity e) => new Selection(e, dynamicUse.mask)));
         }, visitStaticUse: (staticUse) {
           selections.add(new Selection(staticUse.element, null));
         }),
@@ -553,7 +553,7 @@
     AllInfo result = infoCollector.result;
 
     // Recursively build links to function uses
-    Iterable<Element> functionElements =
+    Iterable<Entity> functionElements =
         infoCollector._elementToInfo.keys.where((k) => k is FunctionElement);
     for (FunctionElement element in functionElements) {
       FunctionInfo info = infoCollector._elementToInfo[element];
@@ -568,7 +568,7 @@
     }
 
     // Recursively build links to field uses
-    Iterable<Element> fieldElements =
+    Iterable<Entity> fieldElements =
         infoCollector._elementToInfo.keys.where((k) => k is FieldElement);
     for (FieldElement element in fieldElements) {
       FieldInfo info = infoCollector._elementToInfo[element];
@@ -598,7 +598,8 @@
     result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap();
     stopwatch.stop();
     result.program = new ProgramInfo(
-        entrypoint: infoCollector._elementToInfo[compiler.mainFunction],
+        entrypoint: infoCollector
+            ._elementToInfo[closedWorld.elementEnvironment.mainFunction],
         size: _programSize,
         dart2jsVersion:
             compiler.options.hasBuildId ? compiler.options.buildId : null,
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 42fbecc..368e1cc 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -503,20 +503,20 @@
 
   ResolutionDartType get returnType => type.returnType;
 
-  void forEachRequiredParameter(void function(Element parameter)) {
+  void forEachRequiredParameter(void function(FormalElement parameter)) {
     requiredParameters.forEach(function);
   }
 
-  void forEachOptionalParameter(void function(Element parameter)) {
+  void forEachOptionalParameter(void function(FormalElement parameter)) {
     optionalParameters.forEach(function);
   }
 
-  void forEachParameter(void function(Element parameter)) {
+  void forEachParameter(void function(FormalElement parameter)) {
     forEachRequiredParameter(function);
     forEachOptionalParameter(function);
   }
 
-  void orderedForEachParameter(void function(Element parameter)) {
+  void orderedForEachParameter(void function(FormalElement parameter)) {
     forEachRequiredParameter(function);
     orderedOptionalParameters.forEach(function);
   }
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index c0c3834..ba4bdf0 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -746,13 +746,14 @@
     List<T> result = <T>[];
 
     FunctionSignature parameters = element.functionSignature;
-    parameters.forEachRequiredParameter((ParameterElement element) {
+    parameters.forEachRequiredParameter((_) {
       result.add(compileArgument(arguments.head));
       arguments = arguments.tail;
     });
 
     if (!parameters.optionalParametersAreNamed) {
-      parameters.forEachOptionalParameter((ParameterElement element) {
+      parameters.forEachOptionalParameter((_element) {
+        ParameterElement element = _element;
         if (!arguments.isEmpty) {
           result.add(compileArgument(arguments.head));
           arguments = arguments.tail;
@@ -770,7 +771,8 @@
       // Iterate over the optional parameters of the signature, and try to
       // find them in [compiledNamedArguments]. If found, we use the
       // value in the temporary list, otherwise the default value.
-      parameters.orderedOptionalParameters.forEach((ParameterElement element) {
+      parameters.orderedOptionalParameters.forEach((_element) {
+        ParameterElement element = _element;
         int foundIndex = callStructure.namedArguments.indexOf(element.name);
         if (foundIndex != -1) {
           result.add(compiledNamedArguments[foundIndex]);
@@ -815,18 +817,21 @@
     // that we can call [addArgumentsToList].
     Link<Node> computeCallNodesFromParameters() {
       LinkBuilder<Node> builder = new LinkBuilder<Node>();
-      signature.forEachRequiredParameter((ParameterElement element) {
+      signature.forEachRequiredParameter((_element) {
+        ParameterElement element = _element;
         Node node = element.node;
         mapping[node] = element;
         builder.addLast(node);
       });
       if (signature.optionalParametersAreNamed) {
-        signature.forEachOptionalParameter((ParameterElement element) {
+        signature.forEachOptionalParameter((_element) {
+          ParameterElement element = _element;
           mapping[element.initializer] = element;
           builder.addLast(new NamedArgument(null, null, element.initializer));
         });
       } else {
-        signature.forEachOptionalParameter((ParameterElement element) {
+        signature.forEachOptionalParameter((_element) {
+          ParameterElement element = _element;
           Node node = element.node;
           mapping[node] = element;
           builder.addLast(node);
@@ -869,6 +874,7 @@
 /// Code that cannot not handle an [ErroneousElement] should use
 /// `Element.isUnresolved(element)` to check for unresolvable elements instead
 /// of `element == null`.
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class ErroneousElement extends Element implements ConstructorElement {
   MessageKind get messageKind;
   Map get messageArguments;
@@ -1334,7 +1340,8 @@
 
   /// Compute the type of the effective target of this constructor for an
   /// instantiation site with type [:newType:].
-  ResolutionInterfaceType computeEffectiveTargetType(
+  /// May return a malformed type.
+  ResolutionDartType computeEffectiveTargetType(
       ResolutionInterfaceType newType);
 
   /// If this is a synthesized constructor [definingConstructor] points to
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index 062aef7..5779cd8 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -252,6 +252,9 @@
   int get optionalParameters =>
       positionalParameters - requiredParameters + namedParameters.length;
 
+  /// The total number of parameters (required or optional).
+  int get totalParameters => positionalParameters + namedParameters.length;
+
   /// Returns the [CallStructure] corresponding to a call site passing all
   /// parameters both required and optional.
   CallStructure get callStructure {
diff --git a/pkg/compiler/lib/src/elements/jumps.dart b/pkg/compiler/lib/src/elements/jumps.dart
index 65ab8b9..84805d2 100644
--- a/pkg/compiler/lib/src/elements/jumps.dart
+++ b/pkg/compiler/lib/src/elements/jumps.dart
@@ -36,5 +36,5 @@
   void set isBreakTarget(bool value);
   void set isContinueTarget(bool value);
 
-  LabelDefinition<T> addLabel(T label, String labelName);
+  LabelDefinition<T> addLabel(covariant T label, String labelName);
 }
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 0b54b46..e3c819d 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -250,8 +250,8 @@
   get functionSignature => unsupported();
   get parameterStructure => unsupported();
   get parameters => unsupported();
-  get patch => null;
-  get origin => this;
+  Element get patch => null;
+  Element get origin => this;
   get immediateRedirectionTarget => unsupported();
   get nestedClosures => unsupported();
   get memberContext => unsupported();
@@ -381,8 +381,7 @@
   }
 
   @override
-  void setEffectiveTarget(
-      ConstructorElement target, ResolutionInterfaceType type,
+  void setEffectiveTarget(ConstructorElement target, ResolutionDartType type,
       {bool isMalformed: false}) {
     throw new UnsupportedError("setEffectiveTarget");
   }
@@ -461,6 +460,21 @@
   set _redirectionDeferredPrefix(_) {
     throw new UnsupportedError("_redirectionDeferredPrefix=");
   }
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get declaration => super.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get implementation => super.implementation;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get origin => super.origin;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get patch => super.patch;
+
+  ResolutionFunctionType computeType(Resolution resolution) =>
+      super.computeType(resolution);
 }
 
 /// A message attached to a [WarnOnUseElementX].
@@ -498,7 +512,7 @@
         super(wrappedElement.name, ElementKind.WARN_ON_USE, enclosingElement);
 
   Element unwrap(DiagnosticReporter reporter, Spannable usageSpannable) {
-    var unwrapped = wrappedElement;
+    dynamic unwrapped = wrappedElement;
     if (warning != null) {
       Spannable spannable = warning.sourceSpan;
       if (spannable == null) spannable = usageSpannable;
@@ -814,7 +828,7 @@
 
   bool get hasMembers => !localMembers.isEmpty;
 
-  Element get analyzableElement => library;
+  AnalyzableElement get analyzableElement => library;
 
   accept(ElementVisitor visitor, arg) {
     return visitor.visitCompilationUnitElement(this, arg);
@@ -1076,7 +1090,7 @@
 
   CompilationUnitElement get compilationUnit => entryCompilationUnit;
 
-  Element get analyzableElement => this;
+  AnalyzableElement get analyzableElement => this;
 
   void addCompilationUnit(CompilationUnitElement element) {
     compilationUnits = compilationUnits.prepend(element);
@@ -1264,9 +1278,17 @@
     return visitor.visitLibraryElement(this, arg);
   }
 
-  // TODO(johnniwinther): Remove these when issue 18630 is fixed.
-  LibraryElementX get patch => super.patch;
+  // TODO(johnniwinther): Remove this.
+  LibraryElementX get declaration => super.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  LibraryElementX get implementation => super.implementation;
+
+  // TODO(johnniwinther): Remove this.
   LibraryElementX get origin => super.origin;
+
+  // TODO(johnniwinther): Remove this.
+  LibraryElementX get patch => super.patch;
 }
 
 class PrefixElementX extends ElementX implements PrefixElement {
@@ -1312,10 +1334,7 @@
 }
 
 class TypedefElementX extends ElementX
-    with
-        AstElementMixin,
-        AnalyzableElementX,
-        TypeDeclarationElementX<ResolutionTypedefType>
+    with AstElementMixin, AnalyzableElementX, TypeDeclarationElementX
     implements TypedefElement {
   Typedef cachedNode;
 
@@ -1392,6 +1411,10 @@
 
   // A typedef cannot be patched therefore defines itself.
   AstElement get definingElement => this;
+
+  ResolutionTypedefType get thisType => super.thisType;
+
+  ResolutionTypedefType get rawType => super.rawType;
 }
 
 // This class holds common information for a list of variable or field
@@ -1907,6 +1930,8 @@
 
   @override
   bool get isLocal => true;
+
+  ConstructorElement get functionDeclaration => super.functionDeclaration;
 }
 
 class ErroneousInitializingFormalElementX extends ParameterElementX
@@ -1929,6 +1954,8 @@
   bool get isMalformed => true;
 
   ResolutionDynamicType get type => const ResolutionDynamicType();
+
+  ConstructorElement get functionDeclaration => super.functionDeclaration;
 }
 
 class AbstractFieldElementX extends ElementX
@@ -1983,27 +2010,26 @@
 
 // TODO(johnniwinther): [FunctionSignature] should be merged with
 // [FunctionType].
-// TODO(karlklose): all these lists should have element type [FormalElement].
 class FunctionSignatureX extends FunctionSignatureCommon
     implements FunctionSignature {
   final List<ResolutionDartType> typeVariables;
-  final List<Element> requiredParameters;
-  final List<Element> optionalParameters;
+  final List<FormalElement> requiredParameters;
+  final List<FormalElement> optionalParameters;
   final int requiredParameterCount;
   final int optionalParameterCount;
   final bool optionalParametersAreNamed;
-  final List<Element> orderedOptionalParameters;
+  final List<FormalElement> orderedOptionalParameters;
   final ResolutionFunctionType type;
   final bool hasOptionalParameters;
 
   FunctionSignatureX(
       {this.typeVariables: const <ResolutionDartType>[],
-      this.requiredParameters: const <Element>[],
+      this.requiredParameters: const <FormalElement>[],
       this.requiredParameterCount: 0,
-      List<Element> optionalParameters: const <Element>[],
+      List<Element> optionalParameters: const <FormalElement>[],
       this.optionalParameterCount: 0,
       this.optionalParametersAreNamed: false,
-      this.orderedOptionalParameters: const <Element>[],
+      this.orderedOptionalParameters: const <FormalElement>[],
       this.type})
       : optionalParameters = optionalParameters,
         hasOptionalParameters = !optionalParameters.isEmpty;
@@ -2104,6 +2130,18 @@
 
   @override
   List<ResolutionDartType> get typeVariables => functionSignature.typeVariables;
+
+  // TODO(johnniwinther): Remove this.
+  FunctionElement get declaration => super.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  FunctionElement get implementation => super.implementation;
+
+  // TODO(johnniwinther): Remove this.
+  FunctionElement get origin => super.origin;
+
+  // TODO(johnniwinther): Remove this.
+  FunctionElement get patch => super.patch;
 }
 
 abstract class FunctionElementX extends BaseFunctionElementX
@@ -2279,8 +2317,6 @@
   ConstructorElement _immediateRedirectionTarget;
   PrefixElement _redirectionDeferredPrefix;
 
-  ConstructorElementX get patch => super.patch;
-
   bool get isRedirectingGenerative {
     if (isPatched) return patch.isRedirectingGenerative;
     return isRedirectingGenerativeInternal;
@@ -2411,10 +2447,21 @@
   ConstructorElement get definingConstructor => null;
 
   ClassElement get enclosingClass => enclosingElement.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get declaration => super.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get implementation => super.implementation;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get origin => super.origin;
+
+  // TODO(johnniwinther): Remove this.
+  ConstructorElementX get patch => super.patch;
 }
 
-class DeferredLoaderGetterElementX extends GetterElementX
-    implements GetterElement {
+class DeferredLoaderGetterElementX extends GetterElementX {
   final PrefixElement prefix;
 
   DeferredLoaderGetterElementX(PrefixElement prefix)
@@ -2540,7 +2587,7 @@
 
   Element get outermostEnclosingMemberOrTopLevel => constructor;
 
-  Element get analyzableElement => constructor.analyzableElement;
+  AnalyzableElement get analyzableElement => constructor.analyzableElement;
 
   accept(ElementVisitor visitor, arg) {
     return visitor.visitConstructorBodyElement(this, arg);
@@ -2596,7 +2643,7 @@
 
   ResolvedAst get resolvedAst => _resolvedAst;
 
-  ResolutionDartType get type {
+  ResolutionFunctionType get type {
     if (isDefaultConstructor) {
       return super.type;
     } else {
@@ -2624,8 +2671,7 @@
   }
 }
 
-abstract class TypeDeclarationElementX<T extends GenericType>
-    implements TypeDeclarationElement {
+abstract class TypeDeclarationElementX implements TypeDeclarationElement {
   /**
    * The `this type` for this type declaration.
    *
@@ -2637,7 +2683,7 @@
    *
    * This type is computed in [computeType].
    */
-  T thisTypeCache;
+  GenericType thisTypeCache;
 
   /**
    * The raw type for this type declaration.
@@ -2657,21 +2703,21 @@
    *
    * This type is computed together with [thisType] in [computeType].
    */
-  T rawTypeCache;
+  GenericType rawTypeCache;
 
-  T get thisType {
+  GenericType get thisType {
     assert(thisTypeCache != null,
         failedAt(this, 'This type has not been computed for $this'));
     return thisTypeCache;
   }
 
-  T get rawType {
+  GenericType get rawType {
     assert(rawTypeCache != null,
         failedAt(this, 'Raw type has not been computed for $this'));
     return rawTypeCache;
   }
 
-  T createType(List<ResolutionDartType> typeArguments);
+  GenericType createType(List<ResolutionDartType> typeArguments);
 
   void setThisAndRawTypes(List<ResolutionDartType> typeParameters) {
     assert(thisTypeCache == null,
@@ -2725,7 +2771,7 @@
         AstElementMixin,
         AnalyzableElementX,
         ClassElementCommon,
-        TypeDeclarationElementX<ResolutionInterfaceType>,
+        TypeDeclarationElementX,
         PatchMixin<ClassElement>,
         ClassMemberMixin
     implements ClassElement {
@@ -2823,12 +2869,24 @@
     return supertype == null ? null : supertype.element;
   }
 
-  // TODO(johnniwinther): Remove these when issue 18630 is fixed.
-  ClassElement get patch => super.patch;
-  ClassElement get origin => super.origin;
-
   // A class declaration is defined by the declaration element.
   AstElement get definingElement => declaration;
+
+  ResolutionInterfaceType get thisType => super.thisType;
+
+  ResolutionInterfaceType get rawType => super.rawType;
+
+  // TODO(johnniwinther): Remove this.
+  ClassElement get declaration => super.declaration;
+
+  // TODO(johnniwinther): Remove this.
+  ClassElement get implementation => super.implementation;
+
+  // TODO(johnniwinther): Remove this.
+  ClassElement get origin => super.origin;
+
+  // TODO(johnniwinther): Remove this.
+  ClassElement get patch => super.patch;
 }
 
 abstract class ClassElementX extends BaseClassElementX {
@@ -2935,7 +2993,7 @@
 class EnumClassElementX extends ClassElementX
     implements EnumClassElement, DeclarationSite {
   final Enum node;
-  List<FieldElement> _enumValues;
+  List<EnumConstantElement> _enumValues;
 
   EnumClassElementX(String name, Element enclosing, int id, this.node)
       : super(name, enclosing, id, STATE_NOT_STARTED);
@@ -2960,13 +3018,13 @@
   List<ResolutionDartType> computeTypeParameters(ParsingContext parsing) =>
       const <ResolutionDartType>[];
 
-  List<FieldElement> get enumValues {
+  List<EnumConstantElement> get enumValues {
     assert(_enumValues != null,
         failedAt(this, "enumValues has not been computed for $this."));
     return _enumValues;
   }
 
-  void set enumValues(List<FieldElement> values) {
+  void set enumValues(List<EnumConstantElement> values) {
     assert(_enumValues == null,
         failedAt(this, "enumValues has already been computed for $this."));
     _enumValues = values;
@@ -3187,6 +3245,8 @@
     return new SourceSpan(enclosingClass.sourcePosition.uri,
         position.charOffset, position.charEnd);
   }
+
+  EnumClassElement get enclosingClass => super.enclosingClass;
 }
 
 abstract class MixinApplicationElementX extends BaseClassElementX
@@ -3463,11 +3523,11 @@
 
 /// Mixin for the implementation of patched elements.
 ///
-/// See [:patch_parser.dart:] for a description of the terminology.
+/// See `patch_parser.dart` for a description of the terminology.
 abstract class PatchMixin<E extends Element> implements Element {
-  // TODO(johnniwinther): Use type variables when issue 18630 is fixed.
-  Element /*E*/ patch = null;
-  Element /*E*/ origin = null;
+  // TODO(johnniwinther): Use type variables.
+  Element /* E */ patch = null;
+  Element /* E */ origin = null;
 
   bool get isPatch => origin != null;
   bool get isPatched => patch != null;
@@ -3475,8 +3535,8 @@
   bool get isImplementation => !isPatched;
   bool get isDeclaration => !isPatch;
 
-  Element /*E*/ get implementation => isPatched ? patch : this;
-  Element /*E*/ get declaration => isPatch ? origin : this;
+  Element /* E */ get implementation => isPatched ? patch : this;
+  Element /* E */ get declaration => isPatch ? origin : this;
 
   /// Applies a patch to this element. This method must be called at most once.
   void applyPatch(PatchMixin<E> patch) {
diff --git a/pkg/compiler/lib/src/elements/resolution_types.dart b/pkg/compiler/lib/src/elements/resolution_types.dart
index cc309c1..050914f 100644
--- a/pkg/compiler/lib/src/elements/resolution_types.dart
+++ b/pkg/compiler/lib/src/elements/resolution_types.dart
@@ -59,8 +59,8 @@
    *
    * Invariant: There must be the same number of [arguments] and [parameters].
    */
-  ResolutionDartType subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters);
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters);
 
   /// Performs the substitution of the type arguments of [type] for their
   /// corresponding type variables in this type.
@@ -162,12 +162,13 @@
     return new TypeDeclarationFormatter().format(this, name);
   }
 
-  R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument);
+  R accept<R, A>(covariant ResolutionDartTypeVisitor<R, A> visitor, A argument);
 
-  void visitChildren<R, A>(ResolutionDartTypeVisitor visitor, var argument) {}
+  void visitChildren<R, A>(
+      ResolutionDartTypeVisitor<R, A> visitor, A argument) {}
 
-  static void visitList<R, A>(
-      List<ResolutionDartType> types, DartTypeVisitor visitor, var argument) {
+  static void visitList<R, A>(List<ResolutionDartType> types,
+      ResolutionDartTypeVisitor<R, A> visitor, A argument) {
     for (ResolutionDartType type in types) {
       type.accept(visitor, argument);
     }
@@ -216,8 +217,8 @@
 
   String get name => element.name;
 
-  ResolutionDartType subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters) {
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
     assert(arguments.length == parameters.length);
     if (parameters.isEmpty) {
       // Return fast on empty substitutions.
@@ -283,8 +284,8 @@
 
   Element get element => null;
 
-  ResolutionDartType subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters) {
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
     // Void cannot be substituted.
     return this;
   }
@@ -331,8 +332,8 @@
 
   String get name => element.name;
 
-  ResolutionDartType subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters) {
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
     // Malformed types are not substitutable.
     return this;
   }
@@ -343,7 +344,8 @@
   @override
   bool get isMalformed => true;
 
-  R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument) {
+  R accept<R, A>(
+      covariant ResolutionDartTypeVisitor<R, A> visitor, A argument) {
     return visitor.visitMalformedType(this, argument);
   }
 
@@ -367,7 +369,7 @@
   }
 }
 
-abstract class GenericType<T extends GenericType> extends ResolutionDartType {
+abstract class GenericType extends ResolutionDartType {
   final TypeDeclarationElement element;
   final List<ResolutionDartType> typeArguments;
 
@@ -397,10 +399,10 @@
   }
 
   /// Creates a new instance of this type using the provided type arguments.
-  T createInstantiation(List<ResolutionDartType> newTypeArguments);
+  GenericType createInstantiation(List<ResolutionDartType> newTypeArguments);
 
-  T subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters) {
+  GenericType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
     if (typeArguments.isEmpty) {
       // Return fast on non-generic types.
       return this;
@@ -429,7 +431,8 @@
     }
   }
 
-  void visitChildren(DartTypeVisitor visitor, var argument) {
+  void visitChildren<R, A>(
+      ResolutionDartTypeVisitor<R, A> visitor, var argument) {
     ResolutionDartType.visitList(typeArguments, visitor, argument);
   }
 
@@ -488,8 +491,7 @@
   }
 }
 
-class ResolutionInterfaceType extends GenericType<ResolutionInterfaceType>
-    implements InterfaceType {
+class ResolutionInterfaceType extends GenericType implements InterfaceType {
   int _hashCode;
 
   ResolutionInterfaceType(ClassElement element,
@@ -563,6 +565,11 @@
     ResolutionFunctionType type = element.callType;
     return type != null && isGeneric ? type.substByContext(this) : type;
   }
+
+  ResolutionInterfaceType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
+    return super.subst(arguments, parameters);
+  }
 }
 
 /// Special subclass of [ResolutionInterfaceType] used for generic interface
@@ -694,8 +701,8 @@
     return null;
   }
 
-  ResolutionDartType subst(
-      List<ResolutionDartType> arguments, List<ResolutionDartType> parameters) {
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+      covariant List<ResolutionDartType> parameters) {
     if (parameters.isEmpty) {
       assert(arguments.isEmpty);
       // Return fast on empty substitutions.
@@ -755,11 +762,12 @@
     });
   }
 
-  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
+  R accept<R, A>(covariant DartTypeVisitor<R, A> visitor, A argument) {
     return visitor.visitFunctionType(this, argument);
   }
 
-  void visitChildren(DartTypeVisitor visitor, var argument) {
+  void visitChildren<R, A>(
+      ResolutionDartTypeVisitor<R, A> visitor, var argument) {
     returnType.accept(visitor, argument);
     ResolutionDartType.visitList(parameterTypes, visitor, argument);
     ResolutionDartType.visitList(optionalParameterTypes, visitor, argument);
@@ -858,7 +866,7 @@
 bool _typeContainsMethodTypeVariableType(ResolutionDartType type) =>
     type.containsMethodTypeVariableType;
 
-class ResolutionTypedefType extends GenericType<ResolutionTypedefType> {
+class ResolutionTypedefType extends GenericType {
   ResolutionDartType _unaliased;
 
   ResolutionTypedefType(TypedefElement element,
@@ -905,7 +913,8 @@
 
   ResolutionTypedefType asRaw() => super.asRaw();
 
-  R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument) {
+  R accept<R, A>(
+      covariant ResolutionDartTypeVisitor<R, A> visitor, A argument) {
     return visitor.visitTypedefType(this, argument);
   }
 }
@@ -924,8 +933,8 @@
 
   ResolutionTypeKind get kind => ResolutionTypeKind.DYNAMIC;
 
-  ResolutionDartType subst(List<ResolutionDartType> arguments,
-          List<ResolutionDartType> parameters) =>
+  ResolutionDartType subst(covariant List<ResolutionDartType> arguments,
+          covariant List<ResolutionDartType> parameters) =>
       this;
 
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
@@ -998,7 +1007,7 @@
   R visitGenericType(GenericType type, A argument) => visitType(type, argument);
 
   @override
-  R visitInterfaceType(ResolutionInterfaceType type, A argument) =>
+  R visitInterfaceType(covariant ResolutionInterfaceType type, A argument) =>
       visitGenericType(type, argument);
 
   @override
@@ -1007,33 +1016,38 @@
 }
 
 abstract class AbstractTypeRelationMixin
-    implements AbstractTypeRelation, ResolutionDartTypeVisitor<bool, DartType> {
+    implements
+        AbstractTypeRelation<ResolutionDartType>,
+        ResolutionDartTypeVisitor<bool, ResolutionDartType> {
   Resolution get resolution;
 
   @override
   CommonElements get commonElements => resolution.commonElements;
 
   /// Ensures that the super hierarchy of [type] is computed.
-  void ensureResolved(ResolutionInterfaceType type) {
+  void ensureResolved(covariant ResolutionInterfaceType type) {
     // TODO(johnniwinther): Currently needed since literal types like int,
     // double, bool etc. might not have been resolved yet.
     type.element.ensureResolved(resolution);
   }
 
   /// Returns the unaliased version of [type].
-  DartType getUnaliased(ResolutionDartType type) {
+  ResolutionDartType getUnaliased(covariant ResolutionDartType type) {
     type.computeUnaliased(resolution);
     return type.unaliased;
   }
 
   @override
-  DartType getTypeVariableBound(TypeVariableElement element) => element.bound;
+  DartType getTypeVariableBound(covariant TypeVariableElement element) =>
+      element.bound;
 
   @override
-  FunctionType getCallType(ResolutionInterfaceType type) => type.callType;
+  FunctionType getCallType(covariant ResolutionInterfaceType type) =>
+      type.callType;
 
   @override
-  InterfaceType asInstanceOf(ResolutionInterfaceType type, ClassEntity cls) =>
+  InterfaceType asInstanceOf(
+          covariant ResolutionInterfaceType type, ClassEntity cls) =>
       type.asInstanceOf(cls);
 
   /// Handle as dynamic for both subtype and more specific relation to avoid
@@ -1044,21 +1058,23 @@
       visitType(t, s);
 }
 
-class ResolutionMoreSpecificVisitor extends MoreSpecificVisitor
+class ResolutionMoreSpecificVisitor
+    extends MoreSpecificVisitor<ResolutionDartType>
     with AbstractTypeRelationMixin {
   final Resolution resolution;
 
   ResolutionMoreSpecificVisitor(this.resolution);
 }
 
-class ResolutionSubtypeVisitor extends SubtypeVisitor
+class ResolutionSubtypeVisitor extends SubtypeVisitor<ResolutionDartType>
     with AbstractTypeRelationMixin {
   final Resolution resolution;
 
   ResolutionSubtypeVisitor(this.resolution);
 }
 
-class ResolutionPotentialSubtypeVisitor extends PotentialSubtypeVisitor
+class ResolutionPotentialSubtypeVisitor
+    extends PotentialSubtypeVisitor<ResolutionDartType>
     with AbstractTypeRelationMixin {
   final Resolution resolution;
 
@@ -1070,8 +1086,8 @@
  * substitute for the bound of [typeVariable]. [bound] holds the bound against
  * which [typeArgument] should be checked.
  */
-typedef void CheckTypeVariableBound<T extends GenericType>(T type,
-    DartType typeArgument, TypeVariableType typeVariable, DartType bound);
+typedef void CheckTypeVariableBound(GenericType type, DartType typeArgument,
+    TypeVariableType typeVariable, DartType bound);
 
 class Types extends DartTypes {
   final Resolution resolution;
@@ -1096,35 +1112,34 @@
   }
 
   @override
-  InterfaceType asInstanceOf(ResolutionInterfaceType type, ClassEntity cls) {
+  InterfaceType asInstanceOf(
+      covariant ResolutionInterfaceType type, ClassEntity cls) {
     return type.asInstanceOf(cls);
   }
 
   @override
-  ResolutionDartType substByContext(
-      ResolutionDartType base, ResolutionInterfaceType context) {
+  ResolutionDartType substByContext(covariant ResolutionDartType base,
+      covariant ResolutionInterfaceType context) {
     return base.substByContext(context);
   }
 
   @override
-  InterfaceType getThisType(ClassElement cls) {
-    return cls.thisType;
-  }
+  InterfaceType getThisType(covariant ClassElement cls) => cls.thisType;
 
   @override
-  ResolutionInterfaceType getSupertype(ClassElement cls) {
-    return cls.supertype;
-  }
+  ResolutionInterfaceType getSupertype(covariant ClassElement cls) =>
+      cls.supertype;
 
   @override
-  Iterable<InterfaceType> getSupertypes(ClassElement cls) {
+  Iterable<InterfaceType> getSupertypes(covariant ClassElement cls) {
     assert(cls.allSupertypes != null,
         failedAt(cls, 'Supertypes have not been computed for $cls.'));
     return cls.allSupertypes;
   }
 
   @override
-  FunctionType getCallType(ResolutionInterfaceType type) => type.callType;
+  FunctionType getCallType(covariant ResolutionInterfaceType type) =>
+      type.callType;
 
   /// Flatten [type] by recursively removing enclosing `Future` annotations.
   ///
@@ -1177,15 +1192,18 @@
   }
 
   /** Returns true if t is a subtype of s */
-  bool isSubtype(ResolutionDartType t, ResolutionDartType s) {
+  bool isSubtype(
+      covariant ResolutionDartType t, covariant ResolutionDartType s) {
     return subtypeVisitor.isSubtype(t, s);
   }
 
-  bool isAssignable(ResolutionDartType r, ResolutionDartType s) {
+  bool isAssignable(
+      covariant ResolutionDartType r, covariant ResolutionDartType s) {
     return subtypeVisitor.isAssignable(r, s);
   }
 
-  bool isPotentialSubtype(ResolutionDartType t, ResolutionDartType s) {
+  bool isPotentialSubtype(
+      covariant ResolutionDartType t, covariant ResolutionDartType s) {
     // TODO(johnniwinther): Return a set of variable points in the positive
     // cases.
     return potentialSubtypeVisitor.isSubtype(t, s);
@@ -1193,10 +1211,13 @@
 
   @override
   void checkTypeVariableBounds(
-      ResolutionInterfaceType type,
+      covariant ResolutionInterfaceType type,
       void checkTypeVariableBound(InterfaceType type, DartType typeArgument,
           TypeVariableType typeVariable, DartType bound)) {
-    genericCheckTypeVariableBounds(type, checkTypeVariableBound);
+    void f(DartType type, DartType typeArgument, TypeVariableType typeVariable,
+            DartType bound) =>
+        checkTypeVariableBound(type, typeArgument, typeVariable, bound);
+    genericCheckTypeVariableBounds(type, f);
   }
 
   /**
@@ -1204,8 +1225,8 @@
    * declared on [element]. Calls [checkTypeVariableBound] on each type
    * argument and bound.
    */
-  void genericCheckTypeVariableBounds<T extends GenericType>(
-      T type, CheckTypeVariableBound<T> checkTypeVariableBound) {
+  void genericCheckTypeVariableBounds(
+      GenericType type, CheckTypeVariableBound checkTypeVariableBound) {
     TypeDeclarationElement element = type.element;
     List<ResolutionDartType> typeArguments = type.typeArguments;
     List<ResolutionDartType> typeVariables = element.typeVariables;
@@ -1374,7 +1395,8 @@
         ResolutionInterfaceType type, int depth) {
       OrderedTypeSet types = type.element.allSupertypesAndSelf;
       Set<ResolutionDartType> set = new Set<ResolutionDartType>();
-      types.forEach(depth, (ResolutionInterfaceType supertype) {
+      types.forEach(depth, (_supertype) {
+        ResolutionInterfaceType supertype = _supertype;
         set.add(supertype.substByContext(type));
       });
       return set;
@@ -1637,7 +1659,7 @@
     if (supertypeInstance == null) return null;
 
     constraintMap = new Map<ResolutionTypeVariableType, ResolutionDartType>();
-    element.typeVariables.forEach((ResolutionTypeVariableType typeVariable) {
+    element.typeVariables.forEach((ResolutionDartType typeVariable) {
       constraintMap[typeVariable] = const ResolutionDynamicType();
     });
     if (supertypeInstance.accept(this, supertype)) {
@@ -1650,7 +1672,8 @@
     return null;
   }
 
-  bool visitType(ResolutionDartType type, ResolutionDartType argument) {
+  bool visitType(
+      covariant ResolutionDartType type, ResolutionDartType argument) {
     return types.isMoreSpecific(type, argument);
   }
 
@@ -1663,7 +1686,7 @@
   }
 
   bool visitTypeVariableType(
-      ResolutionTypeVariableType type, ResolutionDartType argument) {
+      covariant ResolutionTypeVariableType type, ResolutionDartType argument) {
     ResolutionDartType constraint =
         types.getMostSpecific(constraintMap[type], argument);
     constraintMap[type] = constraint;
@@ -1671,7 +1694,7 @@
   }
 
   bool visitFunctionType(
-      ResolutionFunctionType type, ResolutionDartType argument) {
+      covariant ResolutionFunctionType type, ResolutionDartType argument) {
     if (argument is ResolutionFunctionType) {
       if (type.parameterTypes.length != argument.parameterTypes.length) {
         return false;
@@ -1738,7 +1761,7 @@
     return proposal;
   }
 
-  void visit(ResolutionDartType type, [_]) {
+  void visit(covariant ResolutionDartType type, [_]) {
     type.accept(this, null);
   }
 
@@ -1753,7 +1776,7 @@
     }
   }
 
-  void visitType(ResolutionDartType type, String name) {
+  void visitType(covariant ResolutionDartType type, String name) {
     if (name == null) {
       sb.write(type);
     } else {
@@ -1774,7 +1797,7 @@
     }
   }
 
-  void visitFunctionType(ResolutionFunctionType type, String name) {
+  void visitFunctionType(covariant ResolutionFunctionType type, String name) {
     visit(type.returnType);
     sb.write(' ');
     if (name != null) {
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index bd829cd..260ab34 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -89,6 +89,8 @@
 
   InterfaceType(this.element, this.typeArguments);
 
+  bool get isInterfaceType => true;
+
   bool get containsTypeVariables =>
       typeArguments.any((type) => type.containsTypeVariables);
 
@@ -123,7 +125,7 @@
   }
 
   @override
-  R accept<R, A>(DartTypeVisitor visitor, A argument) =>
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitInterfaceType(this, argument);
 
   int get hashCode {
@@ -188,7 +190,7 @@
   }
 
   @override
-  R accept<R, A>(DartTypeVisitor visitor, A argument) =>
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitTypeVariableType(this, argument);
 
   int get hashCode => 17 * element.hashCode;
@@ -212,7 +214,7 @@
   }
 
   @override
-  R accept<R, A>(DartTypeVisitor visitor, A argument) =>
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitVoidType(this, argument);
 
   int get hashCode => 6007;
@@ -235,7 +237,7 @@
   }
 
   @override
-  R accept<R, A>(DartTypeVisitor visitor, A argument) =>
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitDynamicType(this, argument);
 
   int get hashCode => 91;
@@ -307,7 +309,7 @@
   }
 
   @override
-  R accept<R, A>(DartTypeVisitor visitor, A argument) =>
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitFunctionType(this, argument);
 
   int get hashCode {
@@ -408,53 +410,55 @@
 abstract class DartTypeVisitor<R, A> {
   const DartTypeVisitor();
 
-  R visit(DartType type, A argument) => type.accept(this, argument);
+  R visit(covariant DartType type, A argument) => type.accept(this, argument);
 
-  R visitVoidType(VoidType type, A argument) => null;
+  R visitVoidType(covariant VoidType type, A argument) => null;
 
-  R visitTypeVariableType(TypeVariableType type, A argument) => null;
+  R visitTypeVariableType(covariant TypeVariableType type, A argument) => null;
 
-  R visitFunctionType(FunctionType type, A argument) => null;
+  R visitFunctionType(covariant FunctionType type, A argument) => null;
 
-  R visitInterfaceType(InterfaceType type, A argument) => null;
+  R visitInterfaceType(covariant InterfaceType type, A argument) => null;
 
-  R visitDynamicType(DynamicType type, A argument) => null;
+  R visitDynamicType(covariant DynamicType type, A argument) => null;
 }
 
 abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
   const BaseDartTypeVisitor();
 
-  R visitType(DartType type, A argument);
+  R visitType(covariant DartType type, A argument);
 
   @override
-  R visitVoidType(VoidType type, A argument) => visitType(type, argument);
-
-  @override
-  R visitTypeVariableType(TypeVariableType type, A argument) =>
+  R visitVoidType(covariant VoidType type, A argument) =>
       visitType(type, argument);
 
   @override
-  R visitFunctionType(FunctionType type, A argument) =>
+  R visitTypeVariableType(covariant TypeVariableType type, A argument) =>
       visitType(type, argument);
 
   @override
-  R visitInterfaceType(InterfaceType type, A argument) =>
+  R visitFunctionType(covariant FunctionType type, A argument) =>
       visitType(type, argument);
 
   @override
-  R visitDynamicType(DynamicType type, A argument) => visitType(type, argument);
+  R visitInterfaceType(covariant InterfaceType type, A argument) =>
+      visitType(type, argument);
+
+  @override
+  R visitDynamicType(covariant DynamicType type, A argument) =>
+      visitType(type, argument);
 }
 
 /// Abstract visitor for determining relations between types.
-abstract class AbstractTypeRelation
-    extends BaseDartTypeVisitor<bool, DartType> {
+abstract class AbstractTypeRelation<T extends DartType>
+    extends BaseDartTypeVisitor<bool, T> {
   CommonElements get commonElements;
 
   /// Ensures that the super hierarchy of [type] is computed.
   void ensureResolved(InterfaceType type) {}
 
   /// Returns the unaliased version of [type].
-  DartType getUnaliased(DartType type) => type.unaliased;
+  T getUnaliased(T type) => type.unaliased;
 
   /// Returns [type] as an instance of [cls], or `null` if [type] is not subtype
   /// if [cls].
@@ -467,31 +471,31 @@
   /// Returns the declared bound of [element].
   DartType getTypeVariableBound(TypeVariableEntity element);
 
-  bool visitType(DartType t, DartType s) {
+  bool visitType(T t, T s) {
     throw 'internal error: unknown type ${t}';
   }
 
-  bool visitVoidType(VoidType t, DartType s) {
+  bool visitVoidType(VoidType t, T s) {
     assert(s is! VoidType);
     return false;
   }
 
-  bool invalidTypeArguments(DartType t, DartType s);
+  bool invalidTypeArguments(T t, T s);
 
-  bool invalidFunctionReturnTypes(DartType t, DartType s);
+  bool invalidFunctionReturnTypes(T t, T s);
 
-  bool invalidFunctionParameterTypes(DartType t, DartType s);
+  bool invalidFunctionParameterTypes(T t, T s);
 
-  bool invalidTypeVariableBounds(DartType bound, DartType s);
+  bool invalidTypeVariableBounds(T bound, T s);
 
-  bool invalidCallableType(DartType callType, DartType s);
+  bool invalidCallableType(covariant DartType callType, covariant DartType s);
 
-  bool visitInterfaceType(InterfaceType t, DartType s) {
+  bool visitInterfaceType(InterfaceType t, covariant DartType s) {
     ensureResolved(t);
 
     bool checkTypeArguments(InterfaceType instance, InterfaceType other) {
-      List<DartType> tTypeArgs = instance.typeArguments;
-      List<DartType> sTypeArgs = other.typeArguments;
+      List<T> tTypeArgs = instance.typeArguments;
+      List<T> sTypeArgs = other.typeArguments;
       assert(tTypeArgs.length == sTypeArgs.length);
       for (int i = 0; i < tTypeArgs.length; i++) {
         if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) {
@@ -537,8 +541,8 @@
     //  x.o     : optionalParameterTypes on [:x:], and
     //  len(xs) : length of list [:xs:].
 
-    Iterator<DartType> tps = tf.parameterTypes.iterator;
-    Iterator<DartType> sps = sf.parameterTypes.iterator;
+    Iterator<T> tps = tf.parameterTypes.iterator;
+    Iterator<T> sps = sf.parameterTypes.iterator;
     bool sNotEmpty = sps.moveNext();
     bool tNotEmpty = tps.moveNext();
     tNext() => (tNotEmpty = tps.moveNext());
@@ -569,9 +573,9 @@
       // subset relation with a linear search for [:sf.namedParameters:]
       // within [:tf.namedParameters:].
       List<String> tNames = tf.namedParameters;
-      List<DartType> tTypes = tf.namedParameterTypes;
+      List<T> tTypes = tf.namedParameterTypes;
       List<String> sNames = sf.namedParameters;
-      List<DartType> sTypes = sf.namedParameterTypes;
+      List<T> sTypes = sf.namedParameterTypes;
       int tIndex = 0;
       int sIndex = 0;
       while (tIndex < tNames.length && sIndex < sNames.length) {
@@ -616,7 +620,7 @@
     return true;
   }
 
-  bool visitTypeVariableType(TypeVariableType t, DartType s) {
+  bool visitTypeVariableType(TypeVariableType t, T s) {
     // Identity check is handled in [isSubtype].
     DartType bound = getTypeVariableBound(t.element);
     if (bound.isTypeVariable) {
@@ -644,8 +648,9 @@
   }
 }
 
-abstract class MoreSpecificVisitor extends AbstractTypeRelation {
-  bool isMoreSpecific(DartType t, DartType s) {
+abstract class MoreSpecificVisitor<T extends DartType>
+    extends AbstractTypeRelation<T> {
+  bool isMoreSpecific(T t, T s) {
     if (identical(t, s) || s.treatAsDynamic || t == commonElements.nullType) {
       return true;
     }
@@ -664,55 +669,56 @@
     return t.accept(this, s);
   }
 
-  bool invalidTypeArguments(DartType t, DartType s) {
+  bool invalidTypeArguments(T t, T s) {
     return !isMoreSpecific(t, s);
   }
 
-  bool invalidFunctionReturnTypes(DartType t, DartType s) {
+  bool invalidFunctionReturnTypes(T t, T s) {
     if (s.treatAsDynamic && t.isVoid) return true;
     return !s.isVoid && !isMoreSpecific(t, s);
   }
 
-  bool invalidFunctionParameterTypes(DartType t, DartType s) {
+  bool invalidFunctionParameterTypes(T t, T s) {
     return !isMoreSpecific(t, s);
   }
 
-  bool invalidTypeVariableBounds(DartType bound, DartType s) {
+  bool invalidTypeVariableBounds(T bound, T s) {
     return !isMoreSpecific(bound, s);
   }
 
-  bool invalidCallableType(DartType callType, DartType s) {
+  bool invalidCallableType(covariant DartType callType, covariant DartType s) {
     return !isMoreSpecific(callType, s);
   }
 }
 
 /// Type visitor that determines the subtype relation two types.
-abstract class SubtypeVisitor extends MoreSpecificVisitor {
-  bool isSubtype(DartType t, DartType s) {
+abstract class SubtypeVisitor<T extends DartType>
+    extends MoreSpecificVisitor<T> {
+  bool isSubtype(T t, T s) {
     return t.treatAsDynamic || isMoreSpecific(t, s);
   }
 
-  bool isAssignable(DartType t, DartType s) {
+  bool isAssignable(T t, T s) {
     return isSubtype(t, s) || isSubtype(s, t);
   }
 
-  bool invalidTypeArguments(DartType t, DartType s) {
+  bool invalidTypeArguments(T t, T s) {
     return !isSubtype(t, s);
   }
 
-  bool invalidFunctionReturnTypes(DartType t, DartType s) {
+  bool invalidFunctionReturnTypes(T t, T s) {
     return !s.isVoid && !isAssignable(t, s);
   }
 
-  bool invalidFunctionParameterTypes(DartType t, DartType s) {
+  bool invalidFunctionParameterTypes(T t, T s) {
     return !isAssignable(t, s);
   }
 
-  bool invalidTypeVariableBounds(DartType bound, DartType s) {
+  bool invalidTypeVariableBounds(T bound, T s) {
     return !isSubtype(bound, s);
   }
 
-  bool invalidCallableType(DartType callType, DartType s) {
+  bool invalidCallableType(covariant DartType callType, covariant DartType s) {
     return !isSubtype(callType, s);
   }
 }
@@ -720,8 +726,9 @@
 /// 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.
-abstract class PotentialSubtypeVisitor extends SubtypeVisitor {
-  bool isSubtype(DartType t, DartType s) {
+abstract class PotentialSubtypeVisitor<T extends DartType>
+    extends SubtypeVisitor<T> {
+  bool isSubtype(T t, T s) {
     if (t is TypeVariableType || s is TypeVariableType) {
       return true;
     }
diff --git a/pkg/compiler/lib/src/elements/visitor.dart b/pkg/compiler/lib/src/elements/visitor.dart
index 0779288..339dfba 100644
--- a/pkg/compiler/lib/src/elements/visitor.dart
+++ b/pkg/compiler/lib/src/elements/visitor.dart
@@ -11,196 +11,231 @@
 abstract class ElementVisitor<R, A> {
   const ElementVisitor();
 
-  R visit(Element e, A arg) => e.accept(this, arg);
+  R visit(covariant Element e, covariant A arg) => e.accept(this, arg);
 
-  R visitErroneousElement(ErroneousElement e, A arg) => null;
-  R visitWarnOnUseElement(WarnOnUseElement e, A arg) => null;
-  R visitAmbiguousElement(AmbiguousElement e, A arg) => null;
-  R visitCompilationUnitElement(CompilationUnitElement e, A arg) => null;
-  R visitLibraryElement(LibraryElement e, A arg) => null;
-  R visitImportElement(ImportElement e, A arg) => null;
-  R visitExportElement(ExportElement e, A arg) => null;
-  R visitPrefixElement(PrefixElement e, A arg) => null;
-  R visitTypedefElement(TypedefElement e, A arg) => null;
-  R visitLocalVariableElement(LocalVariableElement e, A arg) => null;
-  R visitParameterElement(ParameterElement e, A arg) => null;
-  R visitFormalElement(FormalElement e, A arg) => null;
-  R visitFieldElement(FieldElement e, A arg) => null;
-  R visitFieldParameterElement(InitializingFormalElement e, A arg) => null;
-  R visitAbstractFieldElement(AbstractFieldElement e, A arg) => null;
-  R visitMethodElement(FunctionElement e, A arg) => null;
-  R visitGetterElement(GetterElement e, A arg) => null;
-  R visitSetterElement(SetterElement e, A arg) => null;
-  R visitLocalFunctionElement(LocalFunctionElement e, A arg) => null;
-  R visitConstructorElement(ConstructorElement e, A arg) => null;
-  R visitConstructorBodyElement(ConstructorBodyElement e, A arg) => null;
-  R visitClassElement(ClassElement e, A arg) => null;
-  R visitMixinApplicationElement(MixinApplicationElement e, A arg) => null;
-  R visitEnumClassElement(EnumClassElement e, A arg) => null;
-  R visitTypeVariableElement(TypeVariableElement e, A arg) => null;
-  R visitBoxFieldElement(BoxFieldElement e, A arg) => null;
-  R visitClosureClassElement(ClosureClassElement e, A arg) => null;
-  R visitClosureFieldElement(ClosureFieldElement e, A arg) => null;
+  R visitErroneousElement(covariant ErroneousElement e, covariant A arg) =>
+      null;
+  R visitWarnOnUseElement(covariant WarnOnUseElement e, covariant A arg) =>
+      null;
+  R visitAmbiguousElement(covariant AmbiguousElement e, covariant A arg) =>
+      null;
+  R visitCompilationUnitElement(
+          covariant CompilationUnitElement e, covariant A arg) =>
+      null;
+  R visitLibraryElement(covariant LibraryElement e, covariant A arg) => null;
+  R visitImportElement(covariant ImportElement e, covariant A arg) => null;
+  R visitExportElement(covariant ExportElement e, covariant A arg) => null;
+  R visitPrefixElement(covariant PrefixElement e, covariant A arg) => null;
+  R visitTypedefElement(covariant TypedefElement e, covariant A arg) => null;
+  R visitLocalVariableElement(
+          covariant LocalVariableElement e, covariant A arg) =>
+      null;
+  R visitParameterElement(covariant ParameterElement e, covariant A arg) =>
+      null;
+  R visitFormalElement(covariant FormalElement e, covariant A arg) => null;
+  R visitFieldElement(covariant FieldElement e, covariant A arg) => null;
+  R visitFieldParameterElement(
+          covariant InitializingFormalElement e, covariant A arg) =>
+      null;
+  R visitAbstractFieldElement(
+          covariant AbstractFieldElement e, covariant A arg) =>
+      null;
+  R visitMethodElement(covariant MethodElement e, covariant A arg) => null;
+  R visitGetterElement(covariant GetterElement e, covariant A arg) => null;
+  R visitSetterElement(covariant SetterElement e, covariant A arg) => null;
+  R visitLocalFunctionElement(
+          covariant LocalFunctionElement e, covariant A arg) =>
+      null;
+  R visitConstructorElement(covariant ConstructorElement e, covariant A arg) =>
+      null;
+  R visitConstructorBodyElement(
+          covariant ConstructorBodyElement e, covariant A arg) =>
+      null;
+  R visitClassElement(covariant ClassElement e, covariant A arg) => null;
+  R visitMixinApplicationElement(
+          covariant MixinApplicationElement e, covariant A arg) =>
+      null;
+  R visitEnumClassElement(covariant EnumClassElement e, covariant A arg) =>
+      null;
+  R visitTypeVariableElement(
+          covariant TypeVariableElement e, covariant A arg) =>
+      null;
+  R visitBoxFieldElement(covariant BoxFieldElement e, covariant A arg) => null;
+  R visitClosureClassElement(
+          covariant ClosureClassElement e, covariant A arg) =>
+      null;
+  R visitClosureFieldElement(
+          covariant ClosureFieldElement e, covariant A arg) =>
+      null;
 }
 
 abstract class BaseElementVisitor<R, A> extends ElementVisitor<R, A> {
   const BaseElementVisitor();
 
-  R visitElement(Element e, A arg);
+  R visitElement(covariant Element e, covariant A arg);
 
   @override
-  R visitErroneousElement(ErroneousElement e, A arg) {
+  R visitErroneousElement(covariant ErroneousElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitWarnOnUseElement(WarnOnUseElement e, A arg) {
+  R visitWarnOnUseElement(covariant WarnOnUseElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitAmbiguousElement(AmbiguousElement e, A arg) {
+  R visitAmbiguousElement(covariant AmbiguousElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
-  R visitScopeContainerElement(ScopeContainerElement e, A arg) {
+  R visitScopeContainerElement(
+      covariant ScopeContainerElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitCompilationUnitElement(CompilationUnitElement e, A arg) {
+  R visitCompilationUnitElement(
+      covariant CompilationUnitElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitLibraryElement(LibraryElement e, A arg) {
+  R visitLibraryElement(covariant LibraryElement e, covariant A arg) {
     return visitScopeContainerElement(e, arg);
   }
 
   @override
-  R visitImportElement(ImportElement e, A arg) {
+  R visitImportElement(covariant ImportElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitExportElement(ExportElement e, A arg) {
+  R visitExportElement(covariant ExportElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitPrefixElement(PrefixElement e, A arg) {
+  R visitPrefixElement(covariant PrefixElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitTypedefElement(TypedefElement e, A arg) {
+  R visitTypedefElement(covariant TypedefElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
-  R visitVariableElement(VariableElement e, A arg) {
+  R visitVariableElement(covariant VariableElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitLocalVariableElement(LocalVariableElement e, A arg) {
+  R visitLocalVariableElement(
+      covariant LocalVariableElement e, covariant A arg) {
     return visitVariableElement(e, arg);
   }
 
   @override
-  R visitParameterElement(ParameterElement e, A arg) {
+  R visitParameterElement(covariant ParameterElement e, covariant A arg) {
     return visitVariableElement(e, arg);
   }
 
   @override
-  R visitFormalElement(FormalElement e, A arg) {
+  R visitFormalElement(covariant FormalElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitFieldElement(FieldElement e, A arg) {
+  R visitFieldElement(covariant FieldElement e, covariant A arg) {
     return visitVariableElement(e, arg);
   }
 
   @override
-  R visitFieldParameterElement(InitializingFormalElement e, A arg) {
+  R visitFieldParameterElement(
+      covariant InitializingFormalElement e, covariant A arg) {
     return visitParameterElement(e, arg);
   }
 
   @override
-  R visitAbstractFieldElement(AbstractFieldElement e, A arg) {
+  R visitAbstractFieldElement(
+      covariant AbstractFieldElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
-  R visitFunctionElement(FunctionElement e, A arg) {
+  R visitFunctionElement(covariant FunctionElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitMethodElement(MethodElement e, A arg) {
+  R visitMethodElement(covariant MethodElement e, covariant A arg) {
     return visitFunctionElement(e, arg);
   }
 
   @override
-  R visitGetterElement(GetterElement e, A arg) {
+  R visitGetterElement(covariant GetterElement e, covariant A arg) {
     return visitFunctionElement(e, arg);
   }
 
   @override
-  R visitSetterElement(SetterElement e, A arg) {
+  R visitSetterElement(covariant SetterElement e, covariant A arg) {
     return visitFunctionElement(e, arg);
   }
 
   @override
-  R visitLocalFunctionElement(LocalFunctionElement e, A arg) {
+  R visitLocalFunctionElement(
+      covariant LocalFunctionElement e, covariant A arg) {
     return visitFunctionElement(e, arg);
   }
 
   @override
-  R visitConstructorElement(ConstructorElement e, A arg) {
+  R visitConstructorElement(covariant ConstructorElement e, covariant A arg) {
     return visitFunctionElement(e, arg);
   }
 
   @override
-  R visitConstructorBodyElement(ConstructorBodyElement e, A arg) {
+  R visitConstructorBodyElement(
+      covariant ConstructorBodyElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitClassElement(ClassElement e, A arg) {
+  R visitClassElement(covariant ClassElement e, covariant A arg) {
     return visitScopeContainerElement(e, arg);
   }
 
-  R visitTypeDeclarationElement(TypeDeclarationElement e, A arg) {
+  R visitTypeDeclarationElement(
+      covariant TypeDeclarationElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitMixinApplicationElement(MixinApplicationElement e, A arg) {
+  R visitMixinApplicationElement(
+      covariant MixinApplicationElement e, covariant A arg) {
     return visitClassElement(e, arg);
   }
 
   @override
-  R visitEnumClassElement(EnumClassElement e, A arg) {
+  R visitEnumClassElement(covariant EnumClassElement e, covariant A arg) {
     return visitClassElement(e, arg);
   }
 
   @override
-  R visitTypeVariableElement(TypeVariableElement e, A arg) {
+  R visitTypeVariableElement(covariant TypeVariableElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitBoxFieldElement(BoxFieldElement e, A arg) {
+  R visitBoxFieldElement(covariant BoxFieldElement e, covariant A arg) {
     return visitElement(e, arg);
   }
 
   @override
-  R visitClosureClassElement(ClosureClassElement e, A arg) {
+  R visitClosureClassElement(covariant ClosureClassElement e, covariant A arg) {
     return visitClassElement(e, arg);
   }
 
   @override
-  R visitClosureFieldElement(ClosureFieldElement e, A arg) {
+  R visitClosureFieldElement(covariant ClosureFieldElement e, covariant A arg) {
     return visitVariableElement(e, arg);
   }
 }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 0925cc9..8347f35 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -396,7 +396,7 @@
           _processedEntities.add(work.element);
         }
       }
-      List recents = _recentClasses.toList(growable: false);
+      List<ClassEntity> recents = _recentClasses.toList(growable: false);
       _recentClasses.clear();
       _recentConstants = false;
       if (!_onQueueEmpty(recents)) {
@@ -602,5 +602,5 @@
 
 /// Interface for creating work items for enqueued member entities.
 abstract class WorkItemBuilder {
-  WorkItem createWorkItem(MemberEntity entity);
+  WorkItem createWorkItem(covariant MemberEntity entity);
 }
diff --git a/pkg/compiler/lib/src/helpers/expensive_map.dart b/pkg/compiler/lib/src/helpers/expensive_map.dart
index 8b382d9..40b426c 100644
--- a/pkg/compiler/lib/src/helpers/expensive_map.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_map.dart
@@ -24,10 +24,10 @@
   Iterable<K> get keys => _maps[0].keys;
   Iterable<V> get values => _maps[0].values;
 
-  bool containsKey(K key) => _maps[0].containsKey(key);
-  bool containsValue(V value) => _maps[0].containsValue(value);
+  bool containsKey(Object key) => _maps[0].containsKey(key);
+  bool containsValue(Object value) => _maps[0].containsValue(value);
 
-  V operator [](K key) => _maps[0][key];
+  V operator [](Object key) => _maps[0][key];
 
   void forEach(void action(K key, V value)) {
     _maps[0].forEach(action);
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 14a7887..f8f617f 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -94,7 +94,7 @@
 }
 
 /// Set of tracked objects used by [track] and [ifTracked].
-var _trackedObjects = new Set();
+var _trackedObjects = new Set<Object>();
 
 /// Global default value for the `printTrace` option of [track] and [ifTracked].
 bool trackWithTrace = false;
diff --git a/pkg/compiler/lib/src/helpers/track_map.dart b/pkg/compiler/lib/src/helpers/track_map.dart
index 8445efe..8a5eb6d 100644
--- a/pkg/compiler/lib/src/helpers/track_map.dart
+++ b/pkg/compiler/lib/src/helpers/track_map.dart
@@ -57,10 +57,10 @@
   Iterable<K> get keys => _map.keys;
   Iterable<V> get values => _map.values;
 
-  bool containsKey(K key) => _map.containsKey(key);
-  bool containsValue(V value) => _map.containsValue(value);
+  bool containsKey(Object key) => _map.containsKey(key);
+  bool containsValue(Object value) => _map.containsValue(value);
 
-  V operator [](K key) => _map[key];
+  V operator [](Object key) => _map[key];
   String toString() => _map.toString();
 
   void forEach(void action(K key, V value)) {
diff --git a/pkg/compiler/lib/src/inferrer/builder.dart b/pkg/compiler/lib/src/inferrer/builder.dart
index 2659a4f..b94bf5b 100644
--- a/pkg/compiler/lib/src/inferrer/builder.dart
+++ b/pkg/compiler/lib/src/inferrer/builder.dart
@@ -4,7 +4,7 @@
 
 library simple_types_inferrer;
 
-import '../closure.dart' show ClosureClassMap;
+import '../closure.dart' show ClosureRepresentationInfo;
 import '../common.dart';
 import '../common/names.dart' show Identifiers, Selectors;
 import '../compiler.dart' show Compiler;
@@ -143,7 +143,7 @@
   ClosedWorld get closedWorld => inferrer.closedWorld;
 
   @override
-  SemanticSendVisitor get sendVisitor => this;
+  SemanticSendVisitor<TypeInformation, dynamic> get sendVisitor => this;
 
   @override
   TypeInformation apply(ast.Node node, _) => visit(node);
@@ -915,8 +915,8 @@
     // be handled specially, in that we are computing their LUB at
     // each update, and reading them yields the type that was found in a
     // previous analysis of [outermostElement].
-    ClosureClassMap closureData =
-        compiler.closureToClassMapper.getClosureToClassMapping(analyzedElement);
+    ClosureRepresentationInfo closureData = compiler.closureDataLookup
+        .getClosureRepresentationInfo(analyzedElement);
     closureData.forEachCapturedVariable((variable, field) {
       locals.setCaptured(variable, field);
     });
@@ -929,7 +929,8 @@
 
     FunctionElement function = analyzedElement;
     FunctionSignature signature = function.functionSignature;
-    signature.forEachOptionalParameter((ParameterElement element) {
+    signature.forEachOptionalParameter((FormalElement _element) {
+      ParameterElement element = _element;
       ast.Expression defaultValue = element.initializer;
       // TODO(25566): The default value of a parameter of a redirecting factory
       // constructor comes from the corresponding parameter of the target.
@@ -958,7 +959,8 @@
 
     if (analyzedElement.isGenerativeConstructor) {
       isThisExposed = false;
-      signature.forEachParameter((ParameterElement element) {
+      signature.forEachParameter((FormalElement _element) {
+        ParameterElement element = _element;
         TypeInformation parameterType = inferrer.typeOfElement(element);
         if (element.isInitializingFormal) {
           InitializingFormalElement initializingFormal = element;
@@ -1034,7 +1036,8 @@
         returnType = types.nonNullExact(cls);
       }
     } else {
-      signature.forEachParameter((LocalParameterElement element) {
+      signature.forEachParameter((FormalElement _element) {
+        ParameterElement element = _element;
         locals.update(element, inferrer.typeOfElement(element), node);
       });
       visit(node.body);
@@ -1099,8 +1102,8 @@
     // Record the types of captured non-boxed variables. Types of
     // these variables may already be there, because of an analysis of
     // a previous closure.
-    ClosureClassMap nestedClosureData =
-        compiler.closureToClassMapper.getClosureToClassMapping(element);
+    ClosureRepresentationInfo nestedClosureData =
+        compiler.closureDataLookup.getClosureRepresentationInfo(element);
     nestedClosureData.forEachCapturedVariable((variable, field) {
       if (!nestedClosureData.isVariableBoxed(variable)) {
         if (variable == nestedClosureData.thisLocal) {
@@ -1194,7 +1197,7 @@
 
   void checkIfExposesThis(Selector selector, TypeMask mask) {
     if (isThisExposed) return;
-    inferrer.forEachElementMatching(selector, mask, (element) {
+    inferrer.forEachElementMatching(selector, mask, (dynamic element) {
       if (element.isField) {
         ResolvedAst elementResolvedAst = element.resolvedAst;
         if (!selector.isSetter &&
@@ -1512,7 +1515,7 @@
 
   @override
   TypeInformation visitUnresolvedSuperCompoundIndexSet(
-      ast.Send node,
+      ast.SendSet node,
       Element element,
       ast.Node index,
       op.AssignmentOperator operator,
@@ -1635,7 +1638,7 @@
   TypeInformation visitSuperFieldSetterCompound(
       ast.Send node,
       FieldElement field,
-      FunctionElement setter,
+      SetterElement setter,
       op.AssignmentOperator operator,
       ast.Node rhs,
       _) {
@@ -1645,7 +1648,7 @@
   @override
   TypeInformation visitSuperGetterFieldCompound(
       ast.Send node,
-      FunctionElement getter,
+      GetterElement getter,
       FieldElement field,
       op.AssignmentOperator operator,
       ast.Node rhs,
@@ -1656,8 +1659,8 @@
   @override
   TypeInformation visitSuperGetterSetterCompound(
       ast.Send node,
-      FunctionElement getter,
-      FunctionElement setter,
+      GetterElement getter,
+      SetterElement setter,
       op.AssignmentOperator operator,
       ast.Node rhs,
       _) {
@@ -1668,7 +1671,7 @@
   TypeInformation visitSuperMethodSetterCompound(
       ast.Send node,
       FunctionElement method,
-      FunctionElement setter,
+      SetterElement setter,
       op.AssignmentOperator operator,
       ast.Node rhs,
       _) {
@@ -1683,7 +1686,7 @@
 
   @override
   TypeInformation visitUnresolvedSuperGetterCompound(
-      ast.Send node,
+      ast.SendSet node,
       Element getter,
       SetterElement setter,
       op.AssignmentOperator operator,
@@ -1717,19 +1720,19 @@
 
   @override
   TypeInformation visitSuperFieldSetterSetIfNull(ast.Send node,
-      FieldElement field, FunctionElement setter, ast.Node rhs, _) {
+      FieldElement field, SetterElement setter, ast.Node rhs, _) {
     return handleSuperCompound(node, field, setter, rhs);
   }
 
   @override
   TypeInformation visitSuperGetterFieldSetIfNull(ast.Send node,
-      FunctionElement getter, FieldElement field, ast.Node rhs, _) {
+      GetterElement getter, FieldElement field, ast.Node rhs, _) {
     return handleSuperCompound(node, getter, field, rhs);
   }
 
   @override
   TypeInformation visitSuperGetterSetterSetIfNull(ast.Send node,
-      FunctionElement getter, FunctionElement setter, ast.Node rhs, _) {
+      GetterElement getter, SetterElement setter, ast.Node rhs, _) {
     return handleSuperCompound(node, getter, setter, rhs);
   }
 
@@ -1741,7 +1744,7 @@
 
   @override
   TypeInformation visitSuperMethodSetterSetIfNull(ast.Send node,
-      FunctionElement method, FunctionElement setter, ast.Node rhs, _) {
+      FunctionElement method, SetterElement setter, ast.Node rhs, _) {
     return handleSuperCompound(node, method, setter, rhs);
   }
 
@@ -1784,50 +1787,34 @@
   }
 
   @override
-  TypeInformation visitSuperFieldSetterPostfix(
-      ast.SendSet node,
-      FieldElement field,
-      FunctionElement setter,
-      op.IncDecOperator operator,
-      _) {
+  TypeInformation visitSuperFieldSetterPostfix(ast.SendSet node,
+      FieldElement field, SetterElement setter, op.IncDecOperator operator, _) {
     return handleSuperPrefixPostfix(node, field, setter);
   }
 
   @override
-  TypeInformation visitSuperFieldSetterPrefix(
-      ast.SendSet node,
-      FieldElement field,
-      FunctionElement setter,
-      op.IncDecOperator operator,
-      _) {
+  TypeInformation visitSuperFieldSetterPrefix(ast.SendSet node,
+      FieldElement field, SetterElement setter, op.IncDecOperator operator, _) {
     return handleSuperPrefixPostfix(node, field, setter);
   }
 
   @override
-  TypeInformation visitSuperGetterFieldPostfix(
-      ast.SendSet node,
-      FunctionElement getter,
-      FieldElement field,
-      op.IncDecOperator operator,
-      _) {
+  TypeInformation visitSuperGetterFieldPostfix(ast.SendSet node,
+      GetterElement getter, FieldElement field, op.IncDecOperator operator, _) {
     return handleSuperPrefixPostfix(node, getter, field);
   }
 
   @override
-  TypeInformation visitSuperGetterFieldPrefix(
-      ast.SendSet node,
-      FunctionElement getter,
-      FieldElement field,
-      op.IncDecOperator operator,
-      _) {
+  TypeInformation visitSuperGetterFieldPrefix(ast.SendSet node,
+      GetterElement getter, FieldElement field, op.IncDecOperator operator, _) {
     return handleSuperPrefixPostfix(node, getter, field);
   }
 
   @override
   TypeInformation visitSuperGetterSetterPostfix(
       ast.SendSet node,
-      FunctionElement getter,
-      FunctionElement setter,
+      GetterElement getter,
+      SetterElement setter,
       op.IncDecOperator operator,
       _) {
     return handleSuperPrefixPostfix(node, getter, setter);
@@ -1836,8 +1823,8 @@
   @override
   TypeInformation visitSuperGetterSetterPrefix(
       ast.SendSet node,
-      FunctionElement getter,
-      FunctionElement setter,
+      GetterElement getter,
+      SetterElement setter,
       op.IncDecOperator operator,
       _) {
     return handleSuperPrefixPostfix(node, getter, setter);
@@ -1847,7 +1834,7 @@
   TypeInformation visitSuperMethodSetterPostfix(
       ast.SendSet node,
       FunctionElement method,
-      FunctionElement setter,
+      SetterElement setter,
       op.IncDecOperator operator,
       _) {
     return handleSuperPrefixPostfix(node, method, setter);
@@ -1857,7 +1844,7 @@
   TypeInformation visitSuperMethodSetterPrefix(
       ast.SendSet node,
       FunctionElement method,
-      FunctionElement setter,
+      SetterElement setter,
       op.IncDecOperator operator,
       _) {
     return handleSuperPrefixPostfix(node, method, setter);
@@ -1968,8 +1955,8 @@
   }
 
   @override
-  TypeInformation visitUnresolvedSuperIndexSet(
-      ast.SendSet node, Element element, ast.Node index, ast.Node rhs, _) {
+  TypeInformation visitUnresolvedSuperIndexSet(ast.SendSet node,
+      ErroneousElement element, ast.Node index, ast.Node rhs, _) {
     return handleSuperIndexSet(node, element, index, rhs);
   }
 
@@ -2115,7 +2102,7 @@
 
   @override
   TypeInformation visitSuperSetterSet(
-      ast.Send node, SetterElement field, ast.Node rhs, _) {
+      ast.SendSet node, SetterElement field, ast.Node rhs, _) {
     return handleSuperSet(node, field, rhs);
   }
 
@@ -2149,13 +2136,13 @@
 
   @override
   TypeInformation visitSuperGetterSet(
-      ast.Send node, MethodElement getter, ast.Node rhs, _) {
+      ast.Send node, GetterElement getter, ast.Node rhs, _) {
     return handleErroneousSuperSend(node);
   }
 
   @override
   TypeInformation visitSuperMethodSet(
-      ast.Send node, MethodElement method, ast.Node rhs, _) {
+      ast.SendSet node, MethodElement method, ast.Node rhs, _) {
     return handleErroneousSuperSend(node);
   }
 
@@ -2199,7 +2186,7 @@
   }
 
   @override
-  TypeInformation visitSuperGetterInvoke(ast.Send node, MethodElement getter,
+  TypeInformation visitSuperGetterInvoke(ast.Send node, GetterElement getter,
       ast.NodeList arguments, CallStructure callStructure, _) {
     return handleSuperClosureCall(node, getter, arguments);
   }
@@ -2212,7 +2199,7 @@
   }
 
   @override
-  TypeInformation visitSuperSetterInvoke(ast.Send node, FunctionElement setter,
+  TypeInformation visitSuperSetterInvoke(ast.Send node, SetterElement setter,
       ast.NodeList arguments, CallStructure callStructure, _) {
     return handleErroneousSuperSend(node);
   }
@@ -2457,7 +2444,7 @@
   }
 
   @override
-  TypeInformation visitStaticGetterInvoke(ast.Send node, FunctionElement getter,
+  TypeInformation visitStaticGetterInvoke(ast.Send node, GetterElement getter,
       ast.NodeList arguments, CallStructure callStructure, _) {
     return handleStaticFieldOrGetterInvoke(node, getter);
   }
@@ -2489,12 +2476,8 @@
   }
 
   @override
-  TypeInformation visitTopLevelGetterInvoke(
-      ast.Send node,
-      FunctionElement getter,
-      ast.NodeList arguments,
-      CallStructure callStructure,
-      _) {
+  TypeInformation visitTopLevelGetterInvoke(ast.Send node, GetterElement getter,
+      ast.NodeList arguments, CallStructure callStructure, _) {
     return handleStaticFieldOrGetterInvoke(node, getter);
   }
 
@@ -2569,7 +2552,7 @@
   }
 
   /// Invoke a static or top level getter.
-  TypeInformation handleStaticGetterGet(ast.Send node, MethodElement getter) {
+  TypeInformation handleStaticGetterGet(ast.Send node, GetterElement getter) {
     Selector selector = elements.getSelector(node);
     TypeMask mask = inTreeData.typeOfSend(node);
     return handleStaticSend(node, selector, mask, getter, null);
@@ -2625,8 +2608,7 @@
   }
 
   @override
-  TypeInformation visitStaticGetterGet(
-      ast.Send node, FunctionElement getter, _) {
+  TypeInformation visitStaticGetterGet(ast.Send node, GetterElement getter, _) {
     return handleStaticGetterGet(node, getter);
   }
 
@@ -2648,7 +2630,7 @@
 
   @override
   TypeInformation visitTopLevelGetterGet(
-      ast.Send node, FunctionElement getter, _) {
+      ast.Send node, GetterElement getter, _) {
     return handleStaticGetterGet(node, getter);
   }
 
@@ -2838,7 +2820,8 @@
     }
 
     List<TypeInformation> unnamed = <TypeInformation>[];
-    signature.forEachRequiredParameter((ParameterElement element) {
+    signature.forEachRequiredParameter((FormalElement _element) {
+      ParameterElement element = _element;
       assert(locals.use(element) != null);
       unnamed.add(locals.use(element));
     });
@@ -2846,11 +2829,13 @@
     Map<String, TypeInformation> named;
     if (signature.optionalParametersAreNamed) {
       named = new Map<String, TypeInformation>();
-      signature.forEachOptionalParameter((ParameterElement element) {
+      signature.forEachOptionalParameter((FormalElement _element) {
+        ParameterElement element = _element;
         named[element.name] = locals.use(element);
       });
     } else {
-      signature.forEachOptionalParameter((ParameterElement element) {
+      signature.forEachOptionalParameter((FormalElement _element) {
+        ParameterElement element = _element;
         unnamed.add(locals.use(element));
       });
     }
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 1e2f9a6..b5ede14 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -68,7 +68,7 @@
       Compiler compiler, InferrerEngine inferrer,
       [LocalsHandler handler]) {
     var adapter = _createKernelAdapter(compiler, resolvedAst);
-    var node = adapter.getInitialKernelNode(element);
+    var node = adapter.getMemberNode(element);
     return new KernelTypeGraphBuilder.internal(
         element,
         resolvedAst,
@@ -103,8 +103,8 @@
     // be handled specially, in that we are computing their LUB at
     // each update, and reading them yields the type that was found in a
     // previous analysis of [outermostElement].
-    ClosureClassMap closureData = compiler.closureToClassMapper
-        .getClosureToClassMapping(resolvedAst.element);
+    ClosureRepresentationInfo closureData = compiler.closureDataLookup
+        .getClosureRepresentationInfo(resolvedAst.element);
     closureData.forEachCapturedVariable((variable, field) {
       locals.setCaptured(variable, field);
     });
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 1fbdc63..e325a2f 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -336,20 +336,20 @@
     refine();
 
     // Try to infer element types of lists and compute their escape information.
-    types.allocatedLists.values.forEach((ListTypeInformation info) {
+    types.allocatedLists.values.forEach((TypeInformation info) {
       analyzeListAndEnqueue(info);
     });
 
     // Try to infer the key and value types for maps and compute the values'
     // escape information.
-    types.allocatedMaps.values.forEach((MapTypeInformation info) {
+    types.allocatedMaps.values.forEach((TypeInformation info) {
       analyzeMapAndEnqueue(info);
     });
 
     Set<FunctionElement> bailedOutOn = new Set<FunctionElement>();
 
     // Trace closures to potentially infer argument types.
-    types.allocatedClosures.forEach((info) {
+    types.allocatedClosures.forEach((dynamic info) {
       void trace(
           Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) {
         tracer.run();
@@ -434,13 +434,15 @@
     refine();
 
     if (debug.PRINT_SUMMARY) {
-      types.allocatedLists.values.forEach((ListTypeInformation info) {
+      types.allocatedLists.values.forEach((_info) {
+        ListTypeInformation info = _info;
         print('${info.type} '
             'for ${info.originalType.allocationNode} '
             'at ${info.originalType.allocationElement} '
             'after ${info.refineCount}');
       });
-      types.allocatedMaps.values.forEach((MapTypeInformation info) {
+      types.allocatedMaps.values.forEach((_info) {
+        MapTypeInformation info = _info;
         print('${info.type} '
             'for ${info.originalType.allocationNode} '
             'at ${info.originalType.allocationElement} '
@@ -553,7 +555,7 @@
       if (Elements.isStaticOrTopLevelField(element) &&
           resolvedAst.body != null &&
           !element.isConst) {
-        var argument = resolvedAst.body;
+        dynamic argument = resolvedAst.body;
         // TODO(13429): We could do better here by using the
         // constant handler to figure out if it's a lazy field or not.
         if (argument.asSend() != null ||
@@ -567,7 +569,7 @@
   }
 
   void processLoopInformation() {
-    types.allocatedCalls.forEach((info) {
+    types.allocatedCalls.forEach((dynamic info) {
       if (!info.inLoop) return;
       if (info is StaticCallSiteTypeInformation) {
         closedWorldRefiner
@@ -899,7 +901,8 @@
           arguments, sideEffects, inLoop);
     }
 
-    closedWorld.locateMembers(selector, mask).forEach((MemberElement callee) {
+    closedWorld.locateMembers(selector, mask).forEach((_callee) {
+      MemberElement callee = _callee;
       updateSideEffects(sideEffects, selector, callee);
     });
 
@@ -981,8 +984,8 @@
   Iterable<ResolvedAst> sortResolvedAsts() {
     int max = 0;
     Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{};
-    compiler.enqueuer.resolution.processedEntities
-        .forEach((MemberElement element) {
+    compiler.enqueuer.resolution.processedEntities.forEach((_element) {
+      MemberElement element = _element;
       ResolvedAst resolvedAst = element.resolvedAst;
       element = element.implementation;
       if (element.impliesType) return;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index 945572f..b445529 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -190,10 +190,11 @@
     for (int i = 0; i < positional.length; i++) {
       if (positional[i] != other.positional[i]) return false;
     }
+    var result = true;
     named.forEach((name, type) {
-      if (other.named[name] != type) return false;
+      if (other.named[name] != type) result = false;
     });
-    return true;
+    return result;
   }
 
   int get hashCode => throw new UnsupportedError('ArgumentsTypes.hashCode');
@@ -209,7 +210,7 @@
     return positional.every(f) && named.values.every(f);
   }
 
-  bool contains(TypeInformation type) {
+  bool contains(Object type) {
     return positional.contains(type) || named.containsValue(type);
   }
 }
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index df7dd31..2310d8d 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -7,6 +7,7 @@
 import '../common/names.dart' show Identifiers;
 import '../compiler.dart' show Compiler;
 import '../elements/elements.dart';
+import '../elements/entities.dart';
 import '../types/types.dart' show ContainerTypeMask, MapTypeMask;
 import '../util/util.dart' show Setlet;
 import 'debug.dart' as debug;
@@ -220,7 +221,7 @@
       bailout('Stored in a list that bailed out');
     } else {
       list.flowsInto.forEach((flow) {
-        flow.users.forEach((user) {
+        flow.users.forEach((dynamic user) {
           if (user is! DynamicCallSiteTypeInformation) return;
           if (user.receiver != flow) return;
           if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
@@ -239,7 +240,7 @@
       bailout('Stored in a map that bailed out');
     } else {
       map.flowsInto.forEach((flow) {
-        flow.users.forEach((user) {
+        flow.users.forEach((dynamic user) {
           if (user is! DynamicCallSiteTypeInformation) return;
           if (user.receiver != flow) return;
           if (user.selector.isIndex) {
@@ -390,8 +391,9 @@
       bailout('Passed to noSuchMethod');
     }
 
-    Iterable<Element> inferredTargetTypes =
-        info.targets.map((MemberElement element) {
+    Iterable<TypeInformation> inferredTargetTypes =
+        info.targets.map((MemberEntity entity) {
+      MemberElement element = entity;
       return inferrer.types.getInferredTypeOf(element);
     });
     if (inferredTargetTypes.any((user) => user == currentUser)) {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index f79637b..c1a19fa 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -296,7 +296,7 @@
       append('$id [shape=record,label="$label",$style]');
       // Add assignment edges. Color the edges based on whether they were
       // added, removed, temporary, or unchanged.
-      var originalSet = global.assignmentsBeforeAnalysis[node] ?? const [];
+      dynamic originalSet = global.assignmentsBeforeAnalysis[node] ?? const [];
       var tracerSet = global.assignmentsBeforeTracing[node] ?? const [];
       var currentSet = node.assignments.toSet();
       for (TypeInformation assignment in currentSet) {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 96b5923..5d983ca 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -310,7 +310,7 @@
   Iterator<TypeInformation> get iterator => assignments.keys.iterator;
   Iterable<TypeInformation> where(Function f) => assignments.keys.where(f);
 
-  bool contains(TypeInformation info) => assignments.containsKey(info);
+  bool contains(Object info) => assignments.containsKey(info);
 
   String toString() => assignments.keys.toList().toString();
 }
@@ -408,7 +408,7 @@
 
   void addCall(Element caller, Spannable node) {
     assert(node is ast.Node || node is Element);
-    _callers ??= <Element, Setlet>{};
+    _callers ??= <Element, Setlet<Spannable>>{};
     _callers.putIfAbsent(caller, () => new Setlet()).add(node);
   }
 
@@ -837,8 +837,10 @@
     }
   }
 
-  Iterable<Element> get callees =>
-      targets.map((MemberElement e) => e.implementation);
+  Iterable<Element> get callees => targets.map((_e) {
+        MemberElement e = _e;
+        return e.implementation;
+      });
 
   TypeMask computeTypedSelector(InferrerEngine inferrer) {
     TypeMask receiverType = receiver.type;
@@ -853,7 +855,8 @@
   }
 
   bool targetsIncludeComplexNoSuchMethod(InferrerEngine inferrer) {
-    return targets.any((MemberElement e) {
+    return targets.any((_e) {
+      MemberElement e = _e;
       return e is MethodElement &&
           e.isInstanceMember &&
           e.name == Identifiers.noSuchMethod_ &&
@@ -994,7 +997,8 @@
       // Add calls to new targets to the graph.
       targets
           .where((target) => !oldTargets.contains(target))
-          .forEach((MemberElement element) {
+          .forEach((MemberEntity _element) {
+        MemberElement element = _element;
         MemberTypeInformation callee =
             inferrer.types.getInferredTypeOf(element);
         callee.addCall(caller, call);
@@ -1007,7 +1011,8 @@
       // Walk over the old targets, and remove calls that cannot happen anymore.
       oldTargets
           .where((target) => !targets.contains(target))
-          .forEach((MemberElement element) {
+          .forEach((MemberEntity _element) {
+        MemberElement element = _element;
         MemberTypeInformation callee =
             inferrer.types.getInferredTypeOf(element);
         callee.removeCall(caller, call);
@@ -1020,8 +1025,8 @@
 
     // Walk over the found targets, and compute the joined union type mask
     // for all these targets.
-    TypeMask result =
-        inferrer.types.joinTypeMasks(targets.map((MemberElement element) {
+    TypeMask result = inferrer.types.joinTypeMasks(targets.map((_element) {
+      MemberElement element = _element;
       // If [canReachAll] is true, then we are iterating over all
       // targets that satisfy the untyped selector. We skip the return
       // type of the targets that can only be reached through
@@ -1116,8 +1121,10 @@
 
   bool hasStableType(InferrerEngine inferrer) {
     return receiver.isStable &&
-        targets.every((MemberElement element) =>
-            inferrer.types.getInferredTypeOf(element).isStable) &&
+        targets.every((_element) {
+          MemberElement element = _element;
+          return inferrer.types.getInferredTypeOf(element).isStable;
+        }) &&
         (arguments == null || arguments.every((info) => info.isStable)) &&
         super.hasStableType(inferrer);
   }
@@ -1368,7 +1375,7 @@
   }
 
   TypeMask computeType(InferrerEngine inferrer) {
-    var mask = type;
+    dynamic mask = type;
     if (!mask.isContainer ||
         mask.elementType != elementType.type ||
         mask.length != inferredLength) {
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index c2bb4ae..371b038 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -47,7 +47,8 @@
   const SourceInformationStrategy();
 
   /// Create a [SourceInformationBuilder] for [member].
-  SourceInformationBuilder createBuilderForContext(MemberEntity member) {
+  SourceInformationBuilder createBuilderForContext(
+      covariant MemberEntity member) {
     return const SourceInformationBuilder();
   }
 
@@ -63,10 +64,10 @@
   const SourceInformationBuilder();
 
   /// Create a [SourceInformationBuilder] for [member].
-  SourceInformationBuilder forContext(MemberEntity member) => this;
+  SourceInformationBuilder forContext(covariant MemberEntity member) => this;
 
   /// Generate [SourceInformation] the declaration of the [member].
-  SourceInformation buildDeclaration(MemberEntity member) => null;
+  SourceInformation buildDeclaration(covariant MemberEntity member) => null;
 
   /// Generate [SourceInformation] for the generic [node].
   @deprecated
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 06437d7..179a37f 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -2036,7 +2036,7 @@
     List<int> enclosingFinallyLabels = <int>[exitLabel];
     enclosingFinallyLabels.addAll(jumpTargets
         .where((js.Node node) => finallyLabels[node] != null)
-        .map((js.Block node) => finallyLabels[node]));
+        .map((js.Node node) => finallyLabels[node]));
     addStatement(js.js.statement("# = #;", [
       nextWhenCanceled,
       new js.ArrayInitializer(enclosingFinallyLabels.map(js.number).toList())
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 541cf9e..9093b24 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -78,6 +78,8 @@
 const VERBOSE_OPTIMIZER_HINTS = false;
 
 abstract class FunctionCompiler {
+  void onCodegenStart();
+
   /// Generates JavaScript code for `work.element`.
   jsAst.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld);
 
@@ -969,8 +971,9 @@
       int mirrorCount =
           totalMethodCount - mirrorsCodegenAnalysis.preMirrorsMethodCount;
       double percentage = (mirrorCount / totalMethodCount) * 100;
-      DiagnosticMessage hint =
-          reporter.createMessage(compiler.mainApp, MessageKind.MIRROR_BLOAT, {
+      DiagnosticMessage hint = reporter.createMessage(
+          closedWorld.elementEnvironment.mainLibrary,
+          MessageKind.MIRROR_BLOAT, {
         'count': mirrorCount,
         'total': totalMethodCount,
         'percentage': percentage.round()
@@ -1061,6 +1064,7 @@
   /// [WorldImpact] of enabled backend features is returned.
   WorldImpact onCodegenStart(
       ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) {
+    functionCompiler.onCodegenStart();
     _oneShotInterceptorData = new OneShotInterceptorData(
         closedWorld.interceptorData, closedWorld.commonElements);
     _namer = determineNamer(closedWorld, codegenWorldBuilder);
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index 8aa4c06..907d617 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -107,7 +107,7 @@
   }
 
   @override
-  void onData(NativeBehavior behavior, ObjectEncoder encoder) {
+  void onData(covariant NativeBehavior behavior, ObjectEncoder encoder) {
     NativeBehaviorSerialization.serializeNativeBehavior(behavior, encoder);
   }
 }
@@ -266,7 +266,7 @@
         .addAll(decoder.getTypes(DART_TYPES_RETURNED, isOptional: true));
     behavior.typesReturned.addAll(decoder
         .getElements(THIS_TYPES_RETURNED, isOptional: true)
-        .map((element) => element.thisType)
+        .map((dynamic element) => element.thisType)
         .toList());
     behavior.typesReturned.addAll(decoder
         .getStrings(SPECIAL_TYPES_RETURNED, isOptional: true)
@@ -276,7 +276,7 @@
         .addAll(decoder.getTypes(DART_TYPES_INSTANTIATED, isOptional: true));
     behavior.typesInstantiated.addAll(decoder
         .getElements(THIS_TYPES_INSTANTIATED, isOptional: true)
-        .map((element) => element.thisType)
+        .map((dynamic element) => element.thisType)
         .toList());
     behavior.typesInstantiated.addAll(decoder
         .getStrings(SPECIAL_TYPES_INSTANTIATED, isOptional: true)
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 7296ce5..4d2a959 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -5,13 +5,16 @@
 import '../common.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
-import '../elements/resolution_types.dart';
 import '../elements/elements.dart';
+import '../elements/types.dart' show TypeVariableType;
+import '../elements/entities.dart';
+import '../elements/resolution_types.dart';
 import '../io/code_output.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../js_emitter/code_emitter_task.dart';
 import '../options.dart';
+import '../universe/world_builder.dart';
 import 'constant_system_javascript.dart';
 import 'js_backend.dart';
 import 'namer.dart';
@@ -36,6 +39,7 @@
 
   final CompilerOptions _options;
   final CommonElements _commonElements;
+  final CodegenWorldBuilder _worldBuilder;
   final RuntimeTypesNeed _rtiNeed;
   final RuntimeTypesEncoder _rtiEncoder;
   final Namer _namer;
@@ -51,6 +55,7 @@
   ConstantEmitter(
       this._options,
       this._commonElements,
+      this._worldBuilder,
       this._rtiNeed,
       this._rtiEncoder,
       this._namer,
@@ -283,7 +288,7 @@
 
   @override
   jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) {
-    ClassElement interceptorClass = constant.cls;
+    ClassEntity interceptorClass = constant.cls;
     return _task.interceptorPrototypeAccess(interceptorClass);
   }
 
@@ -304,7 +309,7 @@
 
   @override
   jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) {
-    ClassElement element = constant.type.element;
+    ClassEntity element = constant.type.element;
     if (element == _commonElements.jsConstClass) {
       StringConstantValue str = constant.fields.values.single;
       String value = str.primitiveValue;
@@ -313,9 +318,9 @@
     jsAst.Expression constructor =
         _emitter.constructorAccess(constant.type.element);
     List<jsAst.Expression> fields = <jsAst.Expression>[];
-    element.forEachInstanceField((_, FieldElement field) {
+    _worldBuilder.forEachInstanceField(element, (_, FieldEntity field) {
       fields.add(constantReferenceGenerator(constant.fields[field]));
-    }, includeSuperAndInjectedMembers: true);
+    });
     if (_rtiNeed.classNeedsRtiField(constant.type.element)) {
       fields.add(_reifiedTypeArguments(constant.type));
     }
@@ -340,7 +345,8 @@
   }
 
   jsAst.Expression _reifiedTypeArguments(ResolutionInterfaceType type) {
-    jsAst.Expression unexpected(ResolutionTypeVariableType variable) {
+    jsAst.Expression unexpected(TypeVariableType _variable) {
+      ResolutionTypeVariableType variable = _variable;
       throw new SpannableAssertionFailure(
           NO_LOCATION_SPANNABLE,
           "Unexpected type variable '${variable.getStringAsDeclared(null)}'"
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 953a30c..b0ccafa 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -8,6 +8,7 @@
 import '../constants/expressions.dart';
 import '../constants/values.dart';
 import '../elements/elements.dart';
+import '../elements/entities.dart';
 import '../elements/visitor.dart' show BaseElementVisitor;
 import '../resolution/tree_elements.dart' show TreeElements;
 import '../tree/tree.dart';
@@ -98,7 +99,7 @@
   // TODO(johnniwinther): Remove this when values are computed from the
   // expressions.
   @override
-  void copyConstantValues(JavaScriptConstantTask task) {
+  void copyConstantValues(covariant JavaScriptConstantTask task) {
     jsConstantCompiler.constantValueMap
         .addAll(task.jsConstantCompiler.constantValueMap);
     dartConstantCompiler.constantValueMap
@@ -115,7 +116,7 @@
     implements BackendConstantEnvironment {
   // TODO(johnniwinther): Move this to the backend constant handler.
   /** Caches the statics where the initial value cannot be eagerly compiled. */
-  final Set<FieldElement> lazyStatics = new Set<FieldElement>();
+  final Set<FieldEntity> lazyStatics = new Set<FieldEntity>();
 
   // Constants computed for constant expressions.
   final Map<Node, ConstantExpression> nodeConstantMap =
@@ -140,18 +141,19 @@
         element, definitions,
         isConst: isConst, checkType: checkType);
     if (!isConst && value == null) {
-      registerLazyStatic(element);
+      FieldElement field = element;
+      registerLazyStatic(field);
     }
     return value;
   }
 
   @override
-  void registerLazyStatic(FieldElement element) {
+  void registerLazyStatic(FieldEntity element) {
     lazyStatics.add(element);
   }
 
-  List<FieldElement> getLazilyInitializedFieldsForEmission() {
-    return new List<FieldElement>.from(lazyStatics);
+  List<FieldEntity> getLazilyInitializedFieldsForEmission() {
+    return new List<FieldEntity>.from(lazyStatics);
   }
 
   ConstantExpression compileNode(Node node, TreeElements elements,
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 4b3cb36..19afd3c 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -359,7 +359,7 @@
     bool onlyStringKeys = true;
     ConstantValue protoValue = null;
     for (int i = 0; i < keys.length; i++) {
-      var key = keys[i];
+      dynamic key = keys[i];
       if (key.isString) {
         if (key.primitiveValue == JavaScriptMapConstant.PROTO_PROPERTY) {
           protoValue = values[i];
@@ -393,7 +393,7 @@
     ConstantValue argument = createString(text);
     // TODO(johnniwinther): Use type arguments when all uses no longer expect
     // a [FieldElement].
-    Map<FieldEntity, ConstantValue> fields = /*<FieldElement, ConstantValue>*/ {
+    Map<dynamic, ConstantValue> fields = <dynamic, ConstantValue>{
       field: argument
     };
     return new ConstructedConstantValue(type, fields);
diff --git a/pkg/compiler/lib/src/js_backend/element_strategy.dart b/pkg/compiler/lib/src/js_backend/element_strategy.dart
index cd014c8..ee4c02a 100644
--- a/pkg/compiler/lib/src/js_backend/element_strategy.dart
+++ b/pkg/compiler/lib/src/js_backend/element_strategy.dart
@@ -5,8 +5,10 @@
 library dart2js.js_backend.element_strategy;
 
 import '../backend_strategy.dart';
+import '../closure.dart' show ClosureConversionTask, ClosureTask;
 import '../common.dart';
 import '../common/codegen.dart';
+import '../common/tasks.dart';
 import '../common/work.dart';
 import '../compiler.dart';
 import '../elements/elements.dart';
@@ -36,22 +38,27 @@
 
   ElementBackendStrategy(this._compiler);
 
-  ClosedWorldRefiner createClosedWorldRefiner(ClosedWorldImpl closedWorld) =>
+  ClosedWorldRefiner createClosedWorldRefiner(
+          covariant ClosedWorldImpl closedWorld) =>
       closedWorld;
 
   Sorter get sorter => const ElementSorter();
 
-  void convertClosures(ClosedWorldRefiner closedWorldRefiner) {
-    _compiler.closureToClassMapper.createClosureClasses(closedWorldRefiner);
-  }
+  @override
+  ClosureConversionTask createClosureConversionTask(Compiler compiler) =>
+      new ClosureTask(compiler);
 
   @override
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
       ClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy) {
-    return new ElementCodegenWorldBuilderImpl(closedWorld.elementEnvironment,
-        nativeBasicData, closedWorld, selectorConstraintsStrategy);
+    return new ElementCodegenWorldBuilderImpl(
+        _compiler.backend.constants,
+        closedWorld.elementEnvironment,
+        nativeBasicData,
+        closedWorld,
+        selectorConstraintsStrategy);
   }
 
   @override
@@ -61,11 +68,11 @@
   }
 
   @override
-  SsaBuilderTask createSsaBuilderTask(JavaScriptBackend backend,
+  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
       SourceInformationStrategy sourceInformationStrategy) {
     return _compiler.options.useKernel
-        ? new RastaSsaBuilderTask(backend, sourceInformationStrategy)
-        : new SsaAstBuilderTask(backend, sourceInformationStrategy);
+        ? new RastaSsaBuilder(task, backend, sourceInformationStrategy)
+        : new SsaAstBuilder(task, backend, sourceInformationStrategy);
   }
 
   SourceInformationStrategy get sourceInformationStrategy {
@@ -154,7 +161,7 @@
   MemberElement get element => resolvedAst.element;
 
   WorldImpact run() {
-    registry = new CodegenRegistry(element);
+    registry = new CodegenRegistry(_closedWorld.elementEnvironment, element);
     return _backend.codegen(this, _closedWorld);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 245c7ec..ee6500a 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -229,7 +229,7 @@
           _processedEntities.add(work.element);
         }
       }
-      List recents = _recentClasses.toList(growable: false);
+      List<ClassEntity> recents = _recentClasses.toList(growable: false);
       _recentClasses.clear();
       _recentConstants = false;
       if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents);
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 419b7a9..a213223 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -97,7 +97,7 @@
 class _FieldNamingScope {
   final _FieldNamingScope superScope;
   final Entity container;
-  final Map<Element, jsAst.Name> names = new Maplet<Element, jsAst.Name>();
+  final Map<Entity, jsAst.Name> names = new Maplet<Entity, jsAst.Name>();
   final _FieldNamingRegistry registry;
 
   /// Naming counter used for fields of ordinary classes.
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 697ff21..854405a 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -67,7 +67,7 @@
   }
 
   @override
-  jsAst.Name instanceFieldPropertyName(FieldElement element) {
+  jsAst.Name instanceFieldPropertyName(FieldEntity element) {
     jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element);
     if (proposed != null) {
       return proposed;
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index 234042e..4fddd0c 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -307,10 +307,9 @@
       key.isPrimitive || _inUse.contains(key) || _overridesEquals(key);
 
   void _addClassUse(ClassEntity cls) {
-    ConstantValue key = _typeConstants.putIfAbsent(
-        cls,
-        () => _constantSystem.createType(
-            _commonElements, _elementEnvironment.getRawType(cls)));
+    TypeConstantValue f() => _constantSystem.createType(
+        _commonElements, _elementEnvironment.getRawType(cls));
+    ConstantValue key = _typeConstants.putIfAbsent(cls, f);
     _addUse(key);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 54314ad..8fdb82b 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -294,7 +294,7 @@
   }
 
   @override
-  jsAst.Name instanceFieldPropertyName(FieldElement element) {
+  jsAst.Name instanceFieldPropertyName(FieldEntity element) {
     jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element);
     if (proposed != null) {
       return proposed;
diff --git a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
index faf8fb1..cf3fa31 100644
--- a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
@@ -61,7 +61,7 @@
   /// `mirrorsData.targetsUsed`. If the target is a library or class all nested
   /// static fields are included too.
   Iterable<Element> _findStaticFieldTargets() {
-    List staticFields = [];
+    List<Element> staticFields = <Element>[];
 
     void addFieldsInContainer(ScopeContainerElement container) {
       container.forEachLocalMember((Element member) {
@@ -193,7 +193,7 @@
       }
     }
 
-    entities.forEach((MemberElement member) => processElementMetadata(member));
+    entities.forEach((member) => processElementMetadata(member));
   }
 
   void onResolutionComplete() {
@@ -371,7 +371,7 @@
     // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
     if (recents.contains(cls.declaration)) {
       _logEnqueueReflectiveAction(cls, "members");
-      cls.constructors.forEach((ConstructorElement element) {
+      cls.constructors.forEach((Element element) {
         _enqueueReflectiveConstructor(element.declaration,
             enclosingWasIncluded: includeClass);
       });
@@ -463,7 +463,8 @@
     } else if (recents.isNotEmpty) {
       // Keep looking at new classes until fixpoint is reached.
       _logEnqueueReflectiveAction("!START enqueueRecents");
-      recents.forEach((ClassElement cls) {
+      recents.forEach((ClassEntity _cls) {
+        ClassElement cls = _cls;
         _enqueueReflectiveElementsInClass(cls, recents,
             enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library,
                 includedEnclosing: false));
diff --git a/pkg/compiler/lib/src/js_backend/mirrors_data.dart b/pkg/compiler/lib/src/js_backend/mirrors_data.dart
index 0ceaafc..904e646 100644
--- a/pkg/compiler/lib/src/js_backend/mirrors_data.dart
+++ b/pkg/compiler/lib/src/js_backend/mirrors_data.dart
@@ -78,7 +78,7 @@
   /// reflection is used in the program (and thus [isTreeShakingDisabled] is
   /// still false). Therefore _do not_ use this predicate to decide inclusion
   /// in the tree, use [requiredByMirrorSystem] instead.
-  bool isClassReferencedFromMirrorSystem(ClassEntity element);
+  bool isClassReferencedFromMirrorSystem(covariant ClassEntity element);
 
   /// Returns `true` if the member [element] is covered by a `MirrorsUsed`
   /// annotation.
@@ -87,11 +87,11 @@
   /// reflection is used in the program (and thus [isTreeShakingDisabled] is
   /// still false). Therefore _do not_ use this predicate to decide inclusion
   /// in the tree, use [requiredByMirrorSystem] instead.
-  bool isMemberReferencedFromMirrorSystem(MemberEntity element);
+  bool isMemberReferencedFromMirrorSystem(covariant MemberEntity element);
 
   /// Returns `true` if the library [element] is covered by a `MirrorsUsed`
   /// annotation.
-  bool isLibraryReferencedFromMirrorSystem(LibraryEntity element);
+  bool isLibraryReferencedFromMirrorSystem(covariant LibraryEntity element);
 
   /// Returns `true` if the typedef [element] needs reflection information at
   /// runtime.
@@ -124,11 +124,11 @@
   @deprecated
   bool isAccessibleByReflection(Element element);
 
-  bool retainMetadataOfLibrary(LibraryEntity element,
+  bool retainMetadataOfLibrary(covariant LibraryEntity element,
       {bool addForEmission: true});
   bool retainMetadataOfTypedef(TypedefElement element);
-  bool retainMetadataOfClass(ClassEntity element);
-  bool retainMetadataOfMember(MemberEntity element);
+  bool retainMetadataOfClass(covariant ClassEntity element);
+  bool retainMetadataOfMember(covariant MemberEntity element);
   bool retainMetadataOfParameter(ParameterElement element);
 
   bool invokedReflectively(Element element);
@@ -153,8 +153,8 @@
 
   void maybeMarkClosureAsNeededForReflection(
       ClosureClassElement globalizedElement,
-      FunctionElement callFunction,
-      FunctionElement function);
+      MethodElement callFunction,
+      LocalFunctionElement function);
 
   void computeMembersNeededForReflection(
       ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld);
@@ -372,7 +372,7 @@
       }
     }
     if (metaTargets != null) {
-      for (var element in metaTargets) {
+      for (dynamic element in metaTargets) {
         if (element is ClassEntity) {
           metaTargetsUsed.add(element);
         }
@@ -569,7 +569,8 @@
         assert(cls.isResolved, failedAt(cls));
         _classesNeededForReflection.add(cls);
         // 2) its constructors (if resolved)
-        cls.constructors.forEach((ConstructorElement constructor) {
+        cls.constructors.forEach((Element _constructor) {
+          ConstructorElement constructor = _constructor;
           if (worldBuilder.isMemberUsed(constructor)) {
             _membersNeededForReflection.add(constructor);
           }
@@ -580,8 +581,8 @@
           if (worldBuilder.isMemberUsed(element)) {
             memberNames.add(member.name);
             _membersNeededForReflection.add(element);
-            element.nestedClosures
-                .forEach((SynthesizedCallMethodElementX callFunction) {
+            element.nestedClosures.forEach((FunctionElement _callFunction) {
+              SynthesizedCallMethodElementX callFunction = _callFunction;
               _membersNeededForReflection.add(callFunction);
               _classesNeededForReflection.add(callFunction.closureClass);
             });
@@ -589,7 +590,8 @@
         });
         // 4) all overriding members of subclasses/subtypes (should be resolved)
         if (closedWorld.hasAnyStrictSubtype(cls)) {
-          closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
+          closedWorld.forEachStrictSubtypeOf(cls, (ClassEntity _subcls) {
+            ClassElement subcls = _subcls;
             subcls.forEachClassMember((Member member) {
               if (memberNames.contains(member.name)) {
                 // TODO(20993): find out why this assertion fails.
@@ -610,7 +612,8 @@
         }
       } else {
         // check members themselves
-        cls.constructors.forEach((ConstructorElement element) {
+        cls.constructors.forEach((Element _element) {
+          ConstructorElement element = _element;
           if (!worldBuilder.isMemberUsed(element)) return;
           if (_memberReferencedFromMirrorSystem(element)) {
             _membersNeededForReflection.add(element);
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 3f284c4..798e827 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -14,7 +14,20 @@
 import '../constants/values.dart';
 import '../common_elements.dart' show CommonElements;
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../elements/elements.dart';
+import '../elements/elements.dart'
+    show
+        ClassElement,
+        ConstructorBodyElement,
+        Element,
+        Elements,
+        FieldElement,
+        FormalElement,
+        FunctionElement,
+        FunctionSignature,
+        MemberElement,
+        TypeDeclarationElement,
+        MixinApplicationElement,
+        TypedefElement;
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/jumps.dart';
@@ -22,7 +35,6 @@
 import '../elements/resolution_types.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
-import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector, SelectorKind;
 import '../universe/world_builder.dart' show CodegenWorldBuilder;
@@ -542,8 +554,8 @@
 
   final Map<String, int> popularNameCounters = <String, int>{};
 
-  final Map<LibraryElement, String> libraryLongNames =
-      new HashMap<LibraryElement, String>();
+  final Map<LibraryEntity, String> libraryLongNames =
+      new HashMap<LibraryEntity, String>();
 
   final Map<ConstantValue, jsAst.Name> constantNames =
       new HashMap<ConstantValue, jsAst.Name>();
@@ -553,8 +565,8 @@
 
   /// Maps private names to a library that may use that name without prefixing
   /// itself. Used for building proposed names.
-  final Map<String, LibraryElement> shortPrivateNameOwners =
-      <String, LibraryElement>{};
+  final Map<String, LibraryEntity> shortPrivateNameOwners =
+      <String, LibraryEntity>{};
 
   final Map<String, String> suggestedGlobalNames = <String, String>{};
   final Map<String, String> suggestedInstanceNames = <String, String>{};
@@ -562,8 +574,8 @@
   /// Used to store unique keys for library names. Keys are not used as names,
   /// nor are they visible in the output. The only serve as an internal
   /// key into maps.
-  final Map<LibraryElement, String> _libraryKeys =
-      new HashMap<LibraryElement, String>();
+  final Map<LibraryEntity, String> _libraryKeys =
+      new HashMap<LibraryEntity, String>();
 
   Namer(this._closedWorld, this._codegenWorldBuilder) {
     _literalAsyncPrefix = new StringBackedName(asyncPrefix);
@@ -596,7 +608,7 @@
 
   /// Returns the string that is to be used as the result of a call to
   /// [JS_GET_NAME] at [node] with argument [name].
-  jsAst.Name getNameForJsGetName(Node node, JsGetName name) {
+  jsAst.Name getNameForJsGetName(Spannable spannable, JsGetName name) {
     switch (name) {
       case JsGetName.GETTER_PREFIX:
         return asName(getterPrefix);
@@ -653,17 +665,14 @@
       case JsGetName.IS_INDEXABLE_FIELD_NAME:
         return operatorIs(_commonElements.jsIndexingBehaviorInterface);
       case JsGetName.NULL_CLASS_TYPE_NAME:
-        ClassElement nullClass = _commonElements.nullClass;
-        return runtimeTypeName(nullClass);
+        return runtimeTypeName(_commonElements.nullClass);
       case JsGetName.OBJECT_CLASS_TYPE_NAME:
-        ClassElement objectClass = _commonElements.objectClass;
-        return runtimeTypeName(objectClass);
+        return runtimeTypeName(_commonElements.objectClass);
       case JsGetName.FUNCTION_CLASS_TYPE_NAME:
-        ClassElement functionClass = _commonElements.functionClass;
-        return runtimeTypeName(functionClass);
+        return runtimeTypeName(_commonElements.functionClass);
       default:
         throw new SpannableAssertionFailure(
-            node, 'Error: Namer has no name for "$name".');
+            spannable, 'Error: Namer has no name for "$name".');
     }
   }
 
@@ -741,10 +750,10 @@
     // Public names are easy.
     if (!originalName.isPrivate) return text;
 
-    LibraryElement library = originalName.library;
+    LibraryEntity library = originalName.library;
 
     // The first library asking for a short private name wins.
-    LibraryElement owner =
+    LibraryEntity owner =
         shortPrivateNameOwners.putIfAbsent(text, () => library);
 
     if (owner == library) {
@@ -1036,7 +1045,7 @@
   /// Generates a unique key for [library].
   ///
   /// Keys are meant to be used in maps and should not be visible in the output.
-  String _generateLibraryKey(LibraryElement library) {
+  String _generateLibraryKey(LibraryEntity library) {
     return _libraryKeys.putIfAbsent(library, () {
       String keyBase = library.name;
       int counter = 0;
@@ -1884,7 +1893,7 @@
   }
 
   @override
-  void visitMap(JavaScriptMapConstant constant, [_]) {
+  void visitMap(covariant JavaScriptMapConstant constant, [_]) {
     // TODO(9476): Incorporate type parameters into name.
     addRoot('Map');
     if (constant.length == 0) {
@@ -1924,7 +1933,7 @@
 
     // TODO(johnniwinther): This should be accessed from a codegen closed world.
     codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldElement field) {
+        (_, FieldEntity field) {
       if (failed) return;
       _visit(constant.fields[field]);
     });
@@ -2051,7 +2060,7 @@
   int visitConstructed(ConstructedConstantValue constant, [_]) {
     int hash = _hashString(3, constant.type.element.name);
     codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldElement field) {
+        (_, FieldEntity field) {
       hash = _combine(hash, _visit(constant.fields[field]));
     });
     return hash;
@@ -2178,15 +2187,15 @@
     return sb.toString();
   }
 
-  visit(ResolutionDartType type, [_]) {
+  visit(covariant ResolutionDartType type, [_]) {
     type.accept(this, null);
   }
 
-  visitType(ResolutionDartType type, _) {
+  visitType(covariant ResolutionDartType type, _) {
     sb.write(type.name);
   }
 
-  visitFunctionType(ResolutionFunctionType type, _) {
+  visitFunctionType(covariant ResolutionFunctionType type, _) {
     if (rtiEncoder.isSimpleFunctionType(type)) {
       sb.write('args${type.parameterTypes.length}');
       return;
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index d33c869..981e3a8 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -34,7 +34,7 @@
 
   int get hashCode => name.hashCode;
 
-  int compareTo(_NamerName other) {
+  int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
     return name.compareTo(other.name);
@@ -63,7 +63,7 @@
 
   int get hashCode => base.hashCode * 13 + prefix.hashCode;
 
-  int compareTo(_NamerName other) {
+  int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
     _PrefixedName otherSameKind = other;
@@ -139,7 +139,7 @@
     return _cachedHashCode;
   }
 
-  int compareTo(_NamerName other) {
+  int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
     CompoundName otherSameKind = other;
@@ -171,7 +171,7 @@
   }
 
   @override
-  int compareTo(_NamerName other) {
+  int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
     TokenName otherToken = other;
@@ -212,7 +212,7 @@
   String get name => _target.name;
 
   @override
-  int compareTo(_NamerName other) => _target.compareTo(other);
+  int compareTo(covariant _NamerName other) => _target.compareTo(other);
 
   @override
   bool operator ==(other) => _target == other;
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index bfd4df4..a8cb23f 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -195,14 +195,14 @@
   ///
   ///     noSuchMethod(i) => super.noSuchMethod(i);
   ///
-  bool hasForwardingSyntax(FunctionEntity method);
+  bool hasForwardingSyntax(covariant FunctionEntity method);
 
   /// Computes whether [method] is of the form
   ///
   ///     noSuchMethod(i) => throw new Error();
   ///
-  bool hasThrowingSyntax(FunctionEntity method);
+  bool hasThrowingSyntax(covariant FunctionEntity method);
 
   /// Returns the `noSuchMethod` that [method] overrides.
-  FunctionEntity getSuperNoSuchMethod(FunctionEntity method);
+  FunctionEntity getSuperNoSuchMethod(covariant FunctionEntity method);
 }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 9533f68..01050c3 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -237,7 +237,7 @@
       this.localFunctionsNeedingRti,
       this.classesUsingTypeVariableExpression);
 
-  bool checkClass(ClassEntity cls) => true;
+  bool checkClass(covariant ClassEntity cls) => true;
 
   bool classNeedsRti(ClassEntity cls) {
     assert(checkClass(cls));
@@ -300,7 +300,7 @@
   RuntimeTypesNeedBuilderImpl(this._elementEnvironment, DartTypes types)
       : super(types);
 
-  bool checkClass(ClassEntity cls) => true;
+  bool checkClass(covariant ClassEntity cls) => true;
 
   @override
   void registerClassUsingTypeVariableExpression(ClassEntity cls) {
@@ -845,7 +845,8 @@
         parameters = _elementEnvironment
             .getThisType(contextClass)
             .typeArguments
-            .map((TypeVariableType type) {
+            .map((DartType _type) {
+          TypeVariableType type = _type;
           return type.element.name;
         }).toList();
       }
@@ -951,7 +952,8 @@
   }
 }
 
-class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
+class TypeRepresentationGenerator
+    implements ResolutionDartTypeVisitor<dynamic, Emitter> {
   final Namer namer;
   OnVariableCallback onVariable;
   ShouldEncodeTypedefCallback shouldEncodeTypedef;
@@ -1179,7 +1181,7 @@
   }
 }
 
-class ArgumentCollector extends ResolutionDartTypeVisitor {
+class ArgumentCollector extends ResolutionDartTypeVisitor<dynamic, bool> {
   final Set<ClassEntity> classes = new Set<ClassEntity>();
 
   collect(DartType type, {bool isTypeArgument: false}) {
@@ -1211,7 +1213,8 @@
   }
 }
 
-class FunctionArgumentCollector extends ResolutionDartTypeVisitor {
+class FunctionArgumentCollector
+    extends ResolutionDartTypeVisitor<dynamic, bool> {
   final Set<ClassEntity> classes = new Set<ClassEntity>();
 
   FunctionArgumentCollector();
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 1b087c5..1441f9a 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -44,9 +44,9 @@
     //            fields.map(
     //                (name) => js('this.# = #', [name, name]))]));
     var typeParameters = const <jsAst.Parameter>[];
-    var typeInits = const <jsAst.Expression>[];
+    dynamic typeInits = const <jsAst.Expression>[];
     if (hasRtiField) {
-      var rtiName = _namer.rtiFieldJsName;
+      dynamic rtiName = _namer.rtiFieldJsName;
       typeParameters = rtiName;
       typeInits = js('this.# = #', [rtiName, rtiName]);
     }
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 59c06ae..07c8cff 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -196,7 +196,7 @@
           closedWorld.commonElements,
           compiler.types,
           compiler.deferredLoadTask,
-          compiler.closureToClassMapper,
+          compiler.closureDataLookup,
           compiler.codegenWorldBuilder,
           backend.nativeCodegenEnqueuer,
           closedWorld.backendUsage,
@@ -217,7 +217,7 @@
           this,
           closedWorld,
           typeTestRegistry.rtiNeededClasses,
-          compiler.mainFunction,
+          closedWorld.elementEnvironment.mainFunction,
           isMockCompilation: compiler.isMockCompilation);
       int size = emitter.emitProgram(programBuilder);
       // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
@@ -243,10 +243,10 @@
 
   /// Returns the JS function that must be invoked to get the value of the
   /// lazily initialized static.
-  jsAst.Expression isolateLazyInitializerAccess(FieldEntity element);
+  jsAst.Expression isolateLazyInitializerAccess(covariant FieldEntity element);
 
   /// Returns the closure expression of a static function.
-  jsAst.Expression isolateStaticClosureAccess(FunctionEntity element);
+  jsAst.Expression isolateStaticClosureAccess(covariant FunctionEntity element);
 
   /// Returns the JS code for accessing the embedded [global].
   jsAst.Expression generateEmbeddedGlobalAccess(String global);
@@ -264,7 +264,8 @@
   jsAst.Expression constructorAccess(ClassEntity e);
 
   /// Returns the JS prototype of the given class [e].
-  jsAst.Expression prototypeAccess(ClassEntity e, bool hasBeenInstantiated);
+  jsAst.Expression prototypeAccess(
+      covariant ClassEntity e, bool hasBeenInstantiated);
 
   /// Returns the JS constructor of the given interceptor class [e].
   jsAst.Expression interceptorClassAccess(ClassEntity e);
@@ -328,12 +329,12 @@
   }
 
   @override
-  jsAst.PropertyAccess interceptorClassAccess(ClassEntity element) {
+  jsAst.Expression interceptorClassAccess(ClassEntity element) {
     return globalPropertyAccessForClass(element);
   }
 
   @override
-  jsAst.PropertyAccess typeAccess(Entity element) {
+  jsAst.Expression typeAccess(Entity element) {
     return globalPropertyAccessForType(element);
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
index 9ae3b43..7f55142 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
@@ -18,7 +18,7 @@
 
   jsAst.Name superName;
   jsAst.Node functionType;
-  List<jsAst.Node> fieldMetadata;
+  List<jsAst.Expression> fieldMetadata;
 
   final Entity element;
   final Namer namer;
@@ -75,7 +75,7 @@
     }
     // See [fieldEncodingDescription] above.
     parts.addAll(js.joinLiterals(fields, js.stringPart(',')));
-    var classData = js.concatenateStrings(parts, addQuotes: true);
+    dynamic classData = js.concatenateStrings(parts, addQuotes: true);
     if (fieldMetadata != null) {
       // If we need to store fieldMetadata, classData is turned into an array,
       // and the field metadata is appended. So if classData is just a string,
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 97d244e..2a2d944 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -125,7 +125,7 @@
       fields = container.staticFieldsForReflection;
     }
 
-    var fieldMetadata = [];
+    var fieldMetadata = <jsAst.Expression>[];
     bool hasMetadata = false;
     bool fieldsAdded = false;
 
@@ -144,7 +144,7 @@
       // accessors at runtime.
       bool needsFieldsForConstructor = !emitStatics && !classIsNative;
       if (needsFieldsForConstructor || needsAccessor) {
-        var metadata =
+        dynamic metadata =
             task.metadataCollector.buildFieldMetadataFunction(fieldElement);
         if (metadata != null) {
           hasMetadata = true;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
index fbcfd6f..53a4777 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
@@ -119,7 +119,7 @@
     int optionalParameterCount = parameters.optionalParameters << 1;
     if (parameters.namedParameters.isNotEmpty) optionalParameterCount++;
 
-    List tearOffInfo = [callSelectorString];
+    var tearOffInfo = <jsAst.Expression>[callSelectorString];
 
     for (ParameterStubMethod stub in method.parameterStubs) {
       jsAst.Name invocationName = stub.name;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index 33e986a..d740746 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -19,13 +19,7 @@
 import '../../elements/resolution_types.dart' show ResolutionDartType;
 import '../../deferred_load.dart' show OutputUnit;
 import '../../elements/elements.dart'
-    show
-        ClassElement,
-        ConstructorBodyElement,
-        FieldElement,
-        LibraryElement,
-        MethodElement,
-        TypedefElement;
+    show ConstructorBodyElement, LibraryElement, TypedefElement;
 import '../../elements/entities.dart';
 import '../../elements/entity_utils.dart' as utils;
 import '../../elements/names.dart';
@@ -39,7 +33,6 @@
     show
         ConstantEmitter,
         JavaScriptBackend,
-        JavaScriptConstantCompiler,
         Namer,
         SetterName,
         TypeVariableCodegenAnalysis;
@@ -125,6 +118,7 @@
   TypeTestRegistry get typeTestRegistry => task.typeTestRegistry;
   CommonElements get commonElements => _closedWorld.commonElements;
   ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
+  CodegenWorldBuilder get _worldBuilder => compiler.codegenWorldBuilder;
 
   // The full code that is written to each hunk part-file.
   Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>();
@@ -184,6 +178,7 @@
     constantEmitter = new ConstantEmitter(
         compiler.options,
         _closedWorld.commonElements,
+        compiler.codegenWorldBuilder,
         compiler.backend.rtiNeed,
         compiler.backend.rtiEncoder,
         namer,
@@ -303,7 +298,7 @@
   }
 
   @override
-  jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
+  jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) {
     return jsAst.js('#.#', [
       namer.globalObjectForMember(element),
       namer.lazyInitializerName(element)
@@ -311,7 +306,7 @@
   }
 
   @override
-  jsAst.Expression isolateStaticClosureAccess(MethodElement element) {
+  jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) {
     return jsAst.js('#.#()', [
       namer.globalObjectForMember(element),
       namer.staticClosureName(element)
@@ -320,7 +315,7 @@
 
   @override
   jsAst.PropertyAccess prototypeAccess(
-      ClassElement element, bool hasBeenInstantiated) {
+      ClassEntity element, bool hasBeenInstantiated) {
     return jsAst.js('#.prototype', constructorAccess(element));
   }
 
@@ -633,22 +628,22 @@
   jsAst.Statement buildStaticNonFinalFieldInitializations(
       OutputUnit outputUnit) {
     jsAst.Statement buildInitialization(
-        FieldElement element, jsAst.Expression initialValue) {
+        FieldEntity element, jsAst.Expression initialValue) {
       return js.statement('${namer.staticStateHolder}.# = #',
           [namer.globalPropertyNameForMember(element), initialValue]);
     }
 
     bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit);
-    JavaScriptConstantCompiler handler = backend.constants;
     List<jsAst.Statement> parts = <jsAst.Statement>[];
 
     Iterable<FieldEntity> fields = outputStaticNonFinalFieldLists[outputUnit];
     // If the outputUnit does not contain any static non-final fields, then
     // [fields] is `null`.
     if (fields != null) {
-      for (FieldElement element in fields) {
+      for (FieldEntity element in fields) {
         reporter.withCurrentElement(element, () {
-          ConstantValue constant = handler.getConstantValue(element.constant);
+          ConstantValue constant =
+              _worldBuilder.getConstantFieldInitializer(element);
           parts.add(buildInitialization(element, constantReference(constant)));
         });
       }
@@ -1065,7 +1060,7 @@
 
   jsAst.Expression generateLibraryDescriptor(
       LibraryEntity library, Fragment fragment) {
-    var uri = "";
+    dynamic uri = "";
     if (!compiler.options.enableMinification ||
         backend.mirrorsData.mustPreserveUris) {
       uri = library.canonicalUri;
@@ -1106,7 +1101,7 @@
       ..add(metadata == null ? new jsAst.ArrayHole() : metadata)
       ..add(js('#', namer.globalObjectForLibrary(library)))
       ..add(initializer);
-    if (library == compiler.mainApp) {
+    if (library == _closedWorld.elementEnvironment.mainLibrary) {
       parts.add(js.number(1));
     }
 
@@ -1628,7 +1623,7 @@
     deferredParts.forEach(counter.countTokens);
     task.metadataCollector.finalizeTokens();
     if (backend.namer is jsAst.TokenFinalizer) {
-      var finalizer = backend.namer;
+      dynamic finalizer = backend.namer;
       finalizer.finalizeTokens();
     }
   }
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index 44c8866..fa56b88 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -58,6 +58,7 @@
     this.constantEmitter = new ConstantEmitter(
         compiler.options,
         _closedWorld.commonElements,
+        compiler.codegenWorldBuilder,
         compiler.backend.rtiNeed,
         compiler.backend.rtiEncoder,
         namer,
@@ -148,8 +149,7 @@
     // We have to emit the deferred fragments first, since we need their
     // deferred hash (which depends on the output) when emitting the main
     // fragment.
-    List<js.Expression> fragmentsCode =
-        deferredFragments.map((DeferredFragment deferredUnit) {
+    List<js.Expression> fragmentsCode = deferredFragments.map((deferredUnit) {
       js.Expression types =
           program.metadataTypesForOutputUnit(deferredUnit.outputUnit);
       return emitDeferredFragment(types, deferredUnit, program.holders);
@@ -399,14 +399,13 @@
     List<js.Property> globals = <js.Property>[];
 
     js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
-      return js.stringArray(fragments.map((DeferredFragment fragment) =>
-          "${fragment.outputFileName}.$deferredExtension"));
+      return js.stringArray(fragments
+          .map((fragment) => "${fragment.outputFileName}.$deferredExtension"));
     }
 
     js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
       // TODO(floitsch): the hash must depend on the generated code.
-      return js.numArray(
-          fragments.map((DeferredFragment fragment) => fragment.hashCode));
+      return js.numArray(fragments.map((fragment) => fragment.hashCode));
     }
 
     List<js.Property> uris = new List<js.Property>(loadMap.length);
@@ -896,7 +895,7 @@
         return [js.quoteName(method.name), new js.ArrayInitializer(data)];
       } else {
         // TODO(floitsch): not the most efficient way...
-        return ([method]..addAll(method.parameterStubs))
+        return (<dynamic>[method]..addAll(method.parameterStubs))
             .expand(makeNameCodePair);
       }
     } else {
@@ -931,7 +930,7 @@
         /// field whether the method is intercepted.
         // [name, [function, callName, tearOffName, functionType,
         //     stub1_name, stub1_callName, stub1_code, ...]
-        var data = [unparse(compiler, method.code)];
+        var data = <js.Expression>[unparse(compiler, method.code)];
         data.add(js.quoteName(method.callName));
         data.add(js.quoteName(method.tearOffName));
         data.add(method.functionType);
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 681626f..e2573c6 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -78,7 +78,7 @@
     if (_rc == 1) entry.accept(visitor);
   }
 
-  int compareTo(_MetadataEntry other) => other._rc - this._rc;
+  int compareTo(covariant _MetadataEntry other) => other._rc - this._rc;
 }
 
 abstract class Placeholder implements jsAst.DeferredNumber {
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index a7f1562..70e3e35 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -268,7 +268,7 @@
     FunctionEntity converter = _commonElements.closureConverter;
     jsAst.Expression closureConverter =
         _emitterTask.staticFunctionAccess(converter);
-    _worldBuilder.forEachParameter(member, (DartType type, String name) {
+    _worldBuilder.forEachParameter(member, (DartType type, String name, _) {
       // If [name] is not in [stubParameters], then the parameter is an optional
       // parameter that was not provided for this stub.
       for (jsAst.Parameter stubParameter in stubParameters) {
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 637d581..1754c54 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -8,18 +8,9 @@
 import '../common.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
-import '../elements/elements.dart'
-    show
-        ClassElement,
-        FunctionElement,
-        FunctionSignature,
-        MethodElement,
-        ParameterElement;
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
-import '../js_backend/constant_handler_javascript.dart'
-    show JavaScriptConstantCompiler;
 import '../js_backend/namer.dart' show Namer;
 import '../js_backend/native_data.dart';
 import '../js_backend/interceptor_data.dart';
@@ -38,7 +29,6 @@
 
   final CommonElements _commonElements;
   final CodeEmitterTask _emitterTask;
-  final JavaScriptConstantCompiler _constants;
   final Namer _namer;
   final NativeData _nativeData;
   final InterceptorData _interceptorData;
@@ -48,7 +38,6 @@
   ParameterStubGenerator(
       this._commonElements,
       this._emitterTask,
-      this._constants,
       this._namer,
       this._nativeData,
       this._interceptorData,
@@ -57,7 +46,7 @@
 
   Emitter get _emitter => _emitterTask.emitter;
 
-  bool needsSuperGetter(FunctionElement element) =>
+  bool needsSuperGetter(FunctionEntity element) =>
       _codegenWorldBuilder.methodsNeedingSuperGetter.contains(element);
 
   /**
@@ -77,21 +66,23 @@
    * the input selector is non-null (and the member needs a stub).
    */
   ParameterStubMethod generateParameterStub(
-      MethodElement member, Selector selector, Selector callSelector) {
+      FunctionEntity member, Selector selector, Selector callSelector) {
     CallStructure callStructure = selector.callStructure;
-    FunctionSignature parameters = member.functionSignature;
+    ParameterStructure parameterStructure = member.parameterStructure;
     int positionalArgumentCount = callStructure.positionalArgumentCount;
-    if (positionalArgumentCount == parameters.parameterCount) {
+    if (positionalArgumentCount == parameterStructure.totalParameters) {
       assert(callStructure.isUnnamed);
       return null;
     }
-    if (parameters.optionalParametersAreNamed &&
-        callStructure.namedArgumentCount == parameters.optionalParameterCount) {
+    if (parameterStructure.namedParameters.isNotEmpty &&
+        callStructure.namedArgumentCount ==
+            parameterStructure.namedParameters.length) {
       // If the selector has the same number of named arguments as the element,
       // we don't need to add a stub. The call site will hit the method
       // directly.
       return null;
     }
+
     List<String> names = callStructure.getOrderedNamedArguments();
 
     bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member);
@@ -108,7 +99,7 @@
         new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
     // The arguments that will be passed to the real method.
     List<jsAst.Expression> argumentsBuffer = new List<jsAst.Expression>(
-        parameters.parameterCount + extraArgumentCount);
+        parameterStructure.totalParameters + extraArgumentCount);
 
     int count = 0;
     if (isInterceptedMethod) {
@@ -121,14 +112,15 @@
     // Includes extra receiver argument when using interceptor convention
     int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
 
-    parameters.orderedForEachParameter((ParameterElement element) {
-      String jsName = _namer.safeVariableName(element.name);
+    _codegenWorldBuilder.forEachParameter(member,
+        (_, String name, ConstantValue value) {
+      String jsName = _namer.safeVariableName(name);
       assert(jsName != receiverArgumentName);
       if (count < optionalParameterStart) {
         parametersBuffer[count] = new jsAst.Parameter(jsName);
         argumentsBuffer[count] = js('#', jsName);
       } else {
-        int index = names.indexOf(element.name);
+        int index = names.indexOf(name);
         if (index != -1) {
           indexOfLastOptionalArgumentInParameters = count;
           // The order of the named arguments is not the same as the
@@ -137,7 +129,6 @@
           parametersBuffer[optionalParameterStart + index] =
               new jsAst.Parameter(jsName);
         } else {
-          ConstantValue value = _constants.getConstantValue(element.constant);
           if (value == null) {
             argumentsBuffer[count] =
                 _emitter.constantReference(new NullConstantValue());
@@ -165,7 +156,7 @@
           indexOfLastOptionalArgumentInParameters);
     } else if (member.isInstanceMember) {
       if (needsSuperGetter(member)) {
-        ClassElement superClass = member.enclosingClass;
+        ClassEntity superClass = member.enclosingClass;
         jsAst.Name methodName = _namer.instanceMethodName(member);
         // When redirecting, we must ensure that we don't end up in a subclass.
         // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index f298bbe..b9d53cd 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -70,8 +70,8 @@
       this._generatedCode,
       this._sorter);
 
-  Set<ClassElement> computeInterceptorsReferencedFromConstants() {
-    Set<ClassElement> classes = new Set<ClassElement>();
+  Set<ClassEntity> computeInterceptorsReferencedFromConstants() {
+    Set<ClassEntity> classes = new Set<ClassEntity>();
     List<ConstantValue> constants = _worldBuilder.getConstantsForEmission();
     for (ConstantValue constant in constants) {
       if (constant is InterceptorConstantValue) {
@@ -145,8 +145,8 @@
                   element.isConstructor ||
                   element.isSetter)) {
             MethodElement function = element;
-            function.functionSignature
-                .forEachParameter(_mirrorsData.retainMetadataOfParameter);
+            function.functionSignature.forEachParameter((parameter) =>
+                _mirrorsData.retainMetadataOfParameter(parameter));
           }
         }
       }
@@ -156,7 +156,7 @@
           _mirrorsData.retainMetadataOfClass(cls);
           new FieldVisitor(_options, _elementEnvironment, _worldBuilder,
                   _nativeData, _mirrorsData, _namer, _closedWorld)
-              .visitFields((FieldElement member,
+              .visitFields((FieldEntity member,
                   js.Name name,
                   js.Name accessorName,
                   bool needsGetter,
@@ -321,12 +321,10 @@
     Iterable<FieldEntity> fields =
         // TODO(johnniwinther): This should be accessed from a codegen closed
         // world.
-        _worldBuilder.allReferencedStaticFields.where((FieldElement field) {
+        _worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
       if (!field.isConst) {
-        return field.isField &&
-            !field.isInstanceMember &&
-            !field.isFinal &&
-            field.constant != null;
+        return field.isAssignable &&
+            _worldBuilder.hasConstantFieldInitializer(field);
       } else {
         // We also need to emit static const fields if they are available for
         // reflection.
@@ -334,7 +332,7 @@
       }
     });
 
-    _sorter.sortMembers(fields).forEach(addToOutputUnit);
+    _sorter.sortMembers(fields).forEach((MemberEntity e) => addToOutputUnit(e));
   }
 
   void computeNeededLibraries() {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 4c79ead..01b1c65 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 import 'dart:convert' show JSON;
 
-import '../../closure.dart' show ClosureTask, ClosureFieldElement;
+import '../../closure.dart' show ClosureConversionTask, ClosureFieldElement;
 import '../../common.dart';
 import '../../common/names.dart' show Names, Selectors;
 import '../../constants/values.dart'
@@ -80,7 +80,7 @@
   final CommonElements _commonElements;
   final DartTypes _types;
   final DeferredLoadTask _deferredLoadTask;
-  final ClosureTask _closureToClassMapper;
+  final ClosureConversionTask _closureDataLookup;
   final CodegenWorldBuilder _worldBuilder;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
   final BackendUsage _backendUsage;
@@ -123,7 +123,7 @@
       this._commonElements,
       this._types,
       this._deferredLoadTask,
-      this._closureToClassMapper,
+      this._closureDataLookup,
       this._worldBuilder,
       this._nativeCodegenEnqueuer,
       this._backendUsage,
@@ -195,6 +195,8 @@
   /// interceptors, ...).
   Set<ClassElement> _notSoftDeferred;
 
+  Sorter get _sorter => _task.sorter;
+
   Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
     collector.collect();
     _initializeSoftDeferredMap();
@@ -343,7 +345,7 @@
       // For every known class, see if it was allocated in the profile. If yes,
       // collect its dependencies (supers and mixins) and mark them as
       // not-soft-deferrable.
-      collector.outputClassLists.forEach((_, List<ClassElement> elements) {
+      collector.outputClassLists.forEach((_, List<ClassEntity> elements) {
         for (ClassElement element in elements) {
           // TODO(29574): share the encoding of the element with the code
           // that emits the profile-run.
@@ -438,9 +440,9 @@
     return staticNonFinalFields.map(_buildStaticField).toList(growable: false);
   }
 
-  StaticField _buildStaticField(FieldElement element) {
+  StaticField _buildStaticField(FieldEntity element) {
     ConstantValue initialValue =
-        _constantHandler.getConstantValue(element.constant);
+        _worldBuilder.getConstantFieldInitializer(element);
     // TODO(zarah): The holder should not be registered during building of
     // a static field.
     _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
@@ -460,19 +462,19 @@
 
   List<StaticField> _buildStaticLazilyInitializedFields(
       LibrariesMap librariesMap) {
-    Iterable<FieldElement> lazyFields = _constantHandler
+    Iterable<FieldEntity> lazyFields = _constantHandler
         .getLazilyInitializedFieldsForEmission()
-        .where((element) =>
-            _deferredLoadTask.outputUnitForElement(element) ==
+        .where((FieldEntity element) =>
+            _deferredLoadTask.outputUnitForMember(element) ==
             librariesMap.outputUnit);
-    return Elements
-        .sortedByPosition(lazyFields)
+    return _sorter
+        .sortMembers(lazyFields)
         .map(_buildLazyField)
         .where((field) => field != null) // Happens when the field was unused.
         .toList(growable: false);
   }
 
-  StaticField _buildLazyField(FieldElement element) {
+  StaticField _buildLazyField(FieldEntity element) {
     js.Expression code = _generatedCode[element];
     // The code is null if we ended up not needing the lazily
     // initialized field after all because of constant folding
@@ -480,7 +482,7 @@
     if (code == null) return null;
 
     js.Name name = _namer.globalPropertyNameForMember(element);
-    bool isFinal = element.isFinal;
+    bool isFinal = !element.isAssignable;
     bool isLazy = true;
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // building a static field. (Note that the static-state holder was
@@ -525,7 +527,8 @@
         if (_nativeData.isJsInteropClass(cls)) {
           // TODO(johnniwinther): Handle class entities.
           ClassElement e = cls;
-          e.declaration.forEachMember((_, MemberElement member) {
+          e.declaration.forEachMember((_, _member) {
+            MemberElement member = _member;
             var jsName = _nativeData.computeUnescapedJSInteropName(member.name);
             if (!member.isInstanceMember) return;
             if (member.isGetter || member.isField || member.isFunction) {
@@ -691,7 +694,7 @@
         enableMinification: _options.enableMinification);
     RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator(
         _commonElements,
-        _closureToClassMapper,
+        _closureDataLookup,
         _task,
         _namer,
         _nativeData,
@@ -867,14 +870,16 @@
     var /* Map | List */ optionalParameterDefaultValues;
     if (signature.optionalParametersAreNamed) {
       optionalParameterDefaultValues = new Map<String, ConstantValue>();
-      signature.forEachOptionalParameter((ParameterElement parameter) {
+      signature.forEachOptionalParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         ConstantValue def =
             _constantHandler.getConstantValue(parameter.constant);
         optionalParameterDefaultValues[parameter.name] = def;
       });
     } else {
       optionalParameterDefaultValues = <ConstantValue>[];
-      signature.forEachOptionalParameter((ParameterElement parameter) {
+      signature.forEachOptionalParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         ConstantValue def =
             _constantHandler.getConstantValue(parameter.constant);
         optionalParameterDefaultValues.add(def);
@@ -980,7 +985,6 @@
     ParameterStubGenerator generator = new ParameterStubGenerator(
         _commonElements,
         _task,
-        _constantHandler,
         _namer,
         _nativeData,
         _interceptorData,
@@ -1005,7 +1009,7 @@
     Iterable<js.Name> names =
         _oneShotInterceptorData.specializedGetInterceptorNames;
     for (js.Name name in names) {
-      for (ClassElement element
+      for (ClassEntity element
           in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) {
         Class cls = _classes[element];
         if (cls != null) cls.isEager = true;
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index ef47eff..692676b 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -4,7 +4,8 @@
 
 library dart2js.js_emitter.runtime_type_generator;
 
-import '../closure.dart' show ClosureClassMap, ClosureFieldElement, ClosureTask;
+import '../closure.dart'
+    show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask;
 import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../common_elements.dart' show CommonElements;
@@ -13,6 +14,7 @@
 import '../elements/elements.dart'
     show ClassElement, Element, FunctionElement, MixinApplicationElement;
 import '../elements/entities.dart';
+import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../js_backend/js_interop_analysis.dart';
@@ -56,7 +58,7 @@
 
 class RuntimeTypeGenerator {
   final CommonElements _commonElements;
-  final ClosureTask _closureToClassMapper;
+  final ClosureConversionTask _closureDataLookup;
   final CodeEmitterTask emitterTask;
   final Namer _namer;
   final NativeData _nativeData;
@@ -68,7 +70,7 @@
 
   RuntimeTypeGenerator(
       this._commonElements,
-      this._closureToClassMapper,
+      this._closureDataLookup,
       this.emitterTask,
       this._namer,
       this._nativeData,
@@ -80,12 +82,12 @@
 
   TypeTestRegistry get _typeTestRegistry => emitterTask.typeTestRegistry;
 
-  Set<ClassElement> get checkedClasses => _typeTestRegistry.checkedClasses;
+  Set<ClassEntity> get checkedClasses => _typeTestRegistry.checkedClasses;
 
-  Iterable<ClassElement> get classesUsingTypeVariableTests =>
+  Iterable<ClassEntity> get classesUsingTypeVariableTests =>
       _typeTestRegistry.classesUsingTypeVariableTests;
 
-  Set<ResolutionFunctionType> get checkedFunctionTypes =>
+  Set<FunctionType> get checkedFunctionTypes =>
       _typeTestRegistry.checkedFunctionTypes;
 
   /// Generates all properties necessary for is-checks on the [classElement].
@@ -124,11 +126,10 @@
       assert(method.isImplementation);
       jsAst.Expression thisAccess = new jsAst.This();
       if (!method.isAbstract) {
-        ClosureClassMap closureData =
-            _closureToClassMapper.getClosureToClassMapping(method);
+        ClosureRepresentationInfo closureData =
+            _closureDataLookup.getClosureRepresentationInfo(method);
         if (closureData != null) {
-          ClosureFieldElement thisLocal =
-              closureData.freeVariableMap[closureData.thisLocal];
+          ClosureFieldElement thisLocal = closureData.thisFieldEntity;
           if (thisLocal != null) {
             jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal);
             thisAccess = js('this.#', thisName);
@@ -177,8 +178,14 @@
       }
     }
 
-    _generateIsTestsOn(classElement, generateIsTest,
-        generateFunctionTypeSignature, generateSubstitution, generateTypeCheck);
+    _generateIsTestsOn(classElement, (Element e) {
+      generateIsTest(e);
+    }, (Element e, ResolutionFunctionType t) {
+      generateFunctionTypeSignature(e, t);
+    },
+        (Element e, {bool emitNull: false}) =>
+            generateSubstitution(e, emitNull: emitNull),
+        generateTypeCheck);
 
     if (classElement == _commonElements.jsJavaScriptFunctionClass) {
       var type = _jsInteropAnalysis.buildJsFunctionType();
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 d5a7f0e..7a3f627 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
@@ -1168,7 +1168,7 @@
       }
       for (Class cls in library.classes) {
         if (cls.isSoftDeferred != softDeferred) continue;
-        var methods = cls.methods.where((m) => m.needsTearOff).toList();
+        var methods = cls.methods.where((dynamic m) => m.needsTearOff).toList();
         js.Expression container = js.js("#.prototype", classReference(cls));
         js.Expression reference = container;
         if (methods.length > 1) {
@@ -1260,7 +1260,7 @@
     List<js.Property> globals = <js.Property>[];
 
     js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
-      return js.stringArray(fragments.map((DeferredFragment fragment) =>
+      return js.stringArray(fragments.map((Fragment fragment) =>
           "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
     }
 
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 f4739b5..4a354ac 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
@@ -83,6 +83,7 @@
     this.constantEmitter = new ConstantEmitter(
         compiler.options,
         _closedWorld.commonElements,
+        compiler.codegenWorldBuilder,
         compiler.backend.rtiNeed,
         compiler.backend.rtiEncoder,
         namer,
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index 1409b1c3..2fd279d 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -8,12 +8,9 @@
 import '../common_elements.dart';
 import '../elements/elements.dart' show ClassElement, MethodElement;
 import '../elements/entities.dart';
+import '../elements/types.dart' show DartType;
 import '../elements/resolution_types.dart'
-    show
-        ResolutionDartType,
-        ResolutionFunctionType,
-        ResolutionInterfaceType,
-        ResolutionTypeVariableType;
+    show ResolutionFunctionType, ResolutionTypeVariableType;
 import '../elements/types.dart';
 import '../js_backend/runtime_types.dart'
     show
@@ -34,26 +31,28 @@
    * `x is Set<String>` then the ClassElement `Set` will occur once in
    * [checkedClasses].
    */
-  Set<ClassElement> checkedClasses;
+  Set<ClassEntity> checkedClasses;
 
   /**
    * The set of function types that checked, both explicity through tests of
    * typedefs and implicitly through type annotations in checked mode.
    */
-  Set<ResolutionFunctionType> checkedFunctionTypes;
+  Set<FunctionType> checkedFunctionTypes;
 
   /// After [computeNeededClasses] this set only contains classes that are only
   /// used for RTI.
   Set<ClassEntity> _rtiNeededClasses;
 
-  Iterable<ClassElement> cachedClassesUsingTypeVariableTests;
+  Iterable<ClassEntity> cachedClassesUsingTypeVariableTests;
 
-  Iterable<ClassElement> get classesUsingTypeVariableTests {
+  Iterable<ClassEntity> get classesUsingTypeVariableTests {
     if (cachedClassesUsingTypeVariableTests == null) {
       cachedClassesUsingTypeVariableTests = _codegenWorldBuilder.isChecks
-          .where((ResolutionDartType t) => t is ResolutionTypeVariableType)
-          .map((ResolutionTypeVariableType v) => v.element.enclosingClass)
-          .toList();
+          .where((DartType t) => t is ResolutionTypeVariableType)
+          .map((DartType _v) {
+        ResolutionTypeVariableType v = _v;
+        return v.element.enclosingClass;
+      }).toList();
     }
     return cachedClassesUsingTypeVariableTests;
   }
@@ -121,7 +120,9 @@
     //     argument checks.
     // TODO(karlklose): merge this case with 2 when unifying argument and
     // object checks.
-    rtiChecks.getRequiredArgumentClasses().forEach(addClassWithSuperclasses);
+    rtiChecks
+        .getRequiredArgumentClasses()
+        .forEach((e) => addClassWithSuperclasses(e));
 
     // 2.  Add classes that are referenced by substitutions in object checks and
     //     their superclasses.
@@ -167,7 +168,8 @@
     // reflected on 'as functions'.
     liveMembers.where((MemberEntity element) {
       return canBeReflectedAsFunction(element) && canBeReified(element);
-    }).forEach((MethodElement function) {
+    }).forEach((_function) {
+      MethodElement function = _function;
       FunctionType type = function.type;
       for (ClassEntity cls in _rtiChecks.getReferencedClasses(type)) {
         while (cls != null) {
@@ -185,12 +187,12 @@
         _codegenWorldBuilder, classesUsingTypeVariableTests);
     _rtiChecks = rtiChecksBuilder.computeRequiredChecks(_codegenWorldBuilder);
 
-    checkedClasses = new Set<ClassElement>();
-    checkedFunctionTypes = new Set<ResolutionFunctionType>();
-    _codegenWorldBuilder.isChecks.forEach((ResolutionDartType t) {
-      if (t is ResolutionInterfaceType) {
+    checkedClasses = new Set<ClassEntity>();
+    checkedFunctionTypes = new Set<FunctionType>();
+    _codegenWorldBuilder.isChecks.forEach((DartType t) {
+      if (t is InterfaceType) {
         checkedClasses.add(t.element);
-      } else if (t is ResolutionFunctionType) {
+      } else if (t is FunctionType) {
         checkedFunctionTypes.add(t);
       }
     });
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 5b24580..5d12e2c 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -6,8 +6,10 @@
 
 import '../common_elements.dart';
 import '../constants/constant_system.dart';
+import '../constants/values.dart';
 import '../elements/elements.dart';
 import '../elements/entities.dart';
+import '../elements/names.dart';
 import '../elements/types.dart';
 import '../js_backend/backend_usage.dart';
 import '../js_backend/interceptor_data.dart';
@@ -39,7 +41,425 @@
   MemberEntity toFrontendMember(MemberEntity member) => member;
 
   DartType toBackendType(DartType type) => type;
-  DartType fromFrontendType(DartType type) => type;
+  DartType toFrontendType(DartType type) => type;
+}
+
+class JsToFrontendMapImpl implements JsToFrontendMap {
+  final Map<LibraryEntity, LibraryEntity> _toBackendLibrary =
+      <LibraryEntity, LibraryEntity>{};
+  final List<LibraryEntity> _frontendLibraryList = <LibraryEntity>[];
+
+  LibraryEntity toBackendLibrary(LibraryEntity library) {
+    return _toBackendLibrary.putIfAbsent(library, () {
+      JLibrary newLibrary = new JLibrary(
+          _toBackendLibrary.length, library.name, library.canonicalUri);
+      _frontendLibraryList.add(library);
+      return newLibrary;
+    });
+  }
+
+  LibraryEntity toFrontendLibrary(covariant JLibrary library) =>
+      _frontendLibraryList[library.libraryIndex];
+
+  final Map<ClassEntity, ClassEntity> _toBackendClass =
+      <ClassEntity, ClassEntity>{};
+  final List<ClassEntity> _frontendClassList = <ClassEntity>[];
+
+  ClassEntity toBackendClass(ClassEntity cls) {
+    return _toBackendClass.putIfAbsent(cls, () {
+      LibraryEntity library = toBackendLibrary(cls.library);
+      JClass newClass = new JClass(library, _toBackendClass.length, cls.name,
+          isAbstract: cls.isAbstract);
+      _frontendClassList.add(cls);
+      return newClass;
+    });
+  }
+
+  ClassEntity toFrontendClass(covariant JClass cls) =>
+      _frontendClassList[cls.classIndex];
+
+  final Map<MemberEntity, MemberEntity> _toBackendMember =
+      <MemberEntity, MemberEntity>{};
+  final List<MemberEntity> _frontendMemberList = <MemberEntity>[];
+
+  MemberEntity toBackendMember(MemberEntity member) {
+    return _toBackendMember.putIfAbsent(member, () {
+      LibraryEntity library = toBackendLibrary(member.library);
+      ClassEntity cls;
+      if (member.enclosingClass != null) {
+        cls = toBackendClass(member.enclosingClass);
+      }
+
+      JMember newMember;
+      Name memberName = new Name(member.memberName.text, library,
+          isSetter: member.memberName.isSetter);
+      if (member.isField) {
+        FieldEntity field = member;
+        newMember = new JField(
+            _toBackendMember.length, library, cls, memberName,
+            isStatic: field.isStatic,
+            isAssignable: field.isAssignable,
+            isConst: field.isConst);
+      } else if (member.isConstructor) {
+        ConstructorEntity constructor = member;
+        if (constructor.isFactoryConstructor) {
+          // TODO(johnniwinther): This should be a JFunction.
+          newMember = new JFactoryConstructor(_toBackendMember.length, cls,
+              memberName, constructor.parameterStructure,
+              isExternal: constructor.isExternal,
+              isConst: constructor.isConst,
+              isFromEnvironmentConstructor:
+                  constructor.isFromEnvironmentConstructor);
+        } else {
+          newMember = new JGenerativeConstructor(_toBackendMember.length, cls,
+              memberName, constructor.parameterStructure,
+              isExternal: constructor.isExternal, isConst: constructor.isConst);
+        }
+      } else if (member.isGetter) {
+        FunctionEntity getter = member;
+        newMember = new JGetter(_toBackendMember.length, library, cls,
+            memberName, getter.asyncMarker,
+            isStatic: getter.isStatic,
+            isExternal: getter.isExternal,
+            isAbstract: getter.isAbstract);
+      } else if (member.isSetter) {
+        FunctionEntity setter = member;
+        newMember = new JSetter(
+            _toBackendMember.length, library, cls, memberName,
+            isStatic: setter.isStatic,
+            isExternal: setter.isExternal,
+            isAbstract: setter.isAbstract);
+      } else {
+        FunctionEntity function = member;
+        newMember = new JMethod(_toBackendMember.length, library, cls,
+            memberName, function.parameterStructure, function.asyncMarker,
+            isStatic: function.isStatic,
+            isExternal: function.isExternal,
+            isAbstract: function.isAbstract);
+      }
+      _frontendMemberList.add(member);
+      return newMember;
+    });
+  }
+
+  MemberEntity toFrontendMember(covariant JMember member) =>
+      _frontendMemberList[member.memberIndex];
+
+  DartType toBackendType(DartType type) =>
+      const TypeConverter().visit(type, _toBackendEntity);
+  DartType toFrontendType(DartType type) =>
+      const TypeConverter().visit(type, _toFrontendEntity);
+
+  Entity _toBackendEntity(Entity entity) {
+    if (entity is ClassEntity) return toBackendClass(entity);
+    assert(entity is TypeVariableEntity);
+    return _toBackendTypeVariable(entity);
+  }
+
+  final Map<TypeVariableEntity, TypeVariableEntity> _toBackendTypeVariableMap =
+      <TypeVariableEntity, TypeVariableEntity>{};
+
+  final Map<TypeVariableEntity, TypeVariableEntity> _toFrontendTypeVariableMap =
+      <TypeVariableEntity, TypeVariableEntity>{};
+
+  TypeVariableEntity _toBackendTypeVariable(TypeVariableEntity typeVariable) {
+    return _toBackendTypeVariableMap.putIfAbsent(typeVariable, () {
+      Entity typeDeclaration;
+      if (typeVariable.typeDeclaration is ClassEntity) {
+        typeDeclaration = toBackendClass(typeVariable.typeDeclaration);
+      } else {
+        typeDeclaration = toBackendMember(typeVariable.typeDeclaration);
+      }
+      TypeVariableEntity newTypeVariable = new JTypeVariable(
+          typeDeclaration, typeVariable.name, typeVariable.index);
+      _toFrontendTypeVariableMap[newTypeVariable] = typeVariable;
+      return newTypeVariable;
+    });
+  }
+
+  Entity _toFrontendEntity(Entity entity) {
+    if (entity is ClassEntity) return toFrontendClass(entity);
+    assert(entity is TypeVariableEntity);
+    TypeVariableEntity typeVariable = _toFrontendTypeVariableMap[entity];
+    assert(typeVariable != null, "No front end type variable for $entity");
+    return typeVariable;
+  }
+}
+
+typedef Entity EntityConverter(Entity cls);
+
+class TypeConverter implements DartTypeVisitor<DartType, EntityConverter> {
+  const TypeConverter();
+
+  @override
+  DartType visit(DartType type, EntityConverter converter) {
+    return type.accept(this, converter);
+  }
+
+  List<DartType> visitList(List<DartType> types, EntityConverter converter) {
+    List<DartType> list = <DartType>[];
+    for (DartType type in types) {
+      list.add(visit(type, converter));
+    }
+    return list;
+  }
+
+  @override
+  DartType visitDynamicType(DynamicType type, EntityConverter converter) {
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitInterfaceType(InterfaceType type, EntityConverter converter) {
+    return new InterfaceType(
+        converter(type.element), visitList(type.typeArguments, converter));
+  }
+
+  @override
+  DartType visitFunctionType(FunctionType type, EntityConverter converter) {
+    return new FunctionType(
+        visit(type.returnType, converter),
+        visitList(type.parameterTypes, converter),
+        visitList(type.optionalParameterTypes, converter),
+        type.namedParameters,
+        visitList(type.namedParameterTypes, converter));
+  }
+
+  @override
+  DartType visitTypeVariableType(
+      TypeVariableType type, EntityConverter converter) {
+    return new TypeVariableType(converter(type.element));
+  }
+
+  @override
+  DartType visitVoidType(VoidType type, EntityConverter converter) {
+    return const VoidType();
+  }
+}
+
+class JLibrary implements LibraryEntity {
+  /// Library index used for fast lookup in [JsToFrontendMapImpl].
+  final int libraryIndex;
+  final String name;
+  final Uri canonicalUri;
+
+  JLibrary(this.libraryIndex, this.name, this.canonicalUri);
+
+  String toString() => 'library($name)';
+}
+
+class JClass implements ClassEntity {
+  final JLibrary library;
+
+  /// Class index used for fast lookup in [JsToFrontendMapImpl].
+  final int classIndex;
+
+  final String name;
+  final bool isAbstract;
+
+  JClass(this.library, this.classIndex, this.name, {this.isAbstract});
+
+  @override
+  bool get isClosure => false;
+
+  String toString() => 'class($name)';
+}
+
+abstract class JMember implements MemberEntity {
+  /// Member index used for fast lookup in [JsToFrontendMapImpl].
+  final int memberIndex;
+  final JLibrary library;
+  final JClass enclosingClass;
+  final Name _name;
+  final bool _isStatic;
+
+  JMember(this.memberIndex, this.library, this.enclosingClass, this._name,
+      {bool isStatic: false})
+      : _isStatic = isStatic;
+
+  String get name => _name.text;
+
+  Name get memberName => _name;
+
+  @override
+  bool get isAssignable => false;
+
+  @override
+  bool get isConst => false;
+
+  @override
+  bool get isAbstract => false;
+
+  @override
+  bool get isSetter => false;
+
+  @override
+  bool get isGetter => false;
+
+  @override
+  bool get isFunction => false;
+
+  @override
+  bool get isField => false;
+
+  @override
+  bool get isConstructor => false;
+
+  @override
+  bool get isInstanceMember => enclosingClass != null && !_isStatic;
+
+  @override
+  bool get isStatic => enclosingClass != null && _isStatic;
+
+  @override
+  bool get isTopLevel => enclosingClass == null;
+
+  String get _kind;
+
+  String toString() =>
+      '$_kind(${enclosingClass != null ? '${enclosingClass.name}.' : ''}$name)';
+}
+
+abstract class JFunction extends JMember implements FunctionEntity {
+  final ParameterStructure parameterStructure;
+  final bool isExternal;
+  final AsyncMarker asyncMarker;
+
+  JFunction(int memberIndex, JLibrary library, JClass enclosingClass, Name name,
+      this.parameterStructure, this.asyncMarker,
+      {bool isStatic: false, this.isExternal: false})
+      : super(memberIndex, library, enclosingClass, name, isStatic: isStatic);
+}
+
+abstract class JConstructor extends JFunction implements ConstructorEntity {
+  final bool isConst;
+
+  JConstructor(int memberIndex, JClass enclosingClass, Name name,
+      ParameterStructure parameterStructure, {bool isExternal, this.isConst})
+      : super(memberIndex, enclosingClass.library, enclosingClass, name,
+            parameterStructure, AsyncMarker.SYNC,
+            isExternal: isExternal);
+
+  @override
+  bool get isConstructor => true;
+
+  @override
+  bool get isInstanceMember => false;
+
+  @override
+  bool get isStatic => false;
+
+  @override
+  bool get isTopLevel => false;
+
+  @override
+  bool get isFromEnvironmentConstructor => false;
+
+  String get _kind => 'constructor';
+}
+
+class JGenerativeConstructor extends JConstructor {
+  JGenerativeConstructor(int constructorIndex, JClass enclosingClass, Name name,
+      ParameterStructure parameterStructure, {bool isExternal, bool isConst})
+      : super(constructorIndex, enclosingClass, name, parameterStructure,
+            isExternal: isExternal, isConst: isConst);
+
+  @override
+  bool get isFactoryConstructor => false;
+
+  @override
+  bool get isGenerativeConstructor => true;
+}
+
+class JFactoryConstructor extends JConstructor {
+  @override
+  final bool isFromEnvironmentConstructor;
+
+  JFactoryConstructor(int memberIndex, JClass enclosingClass, Name name,
+      ParameterStructure parameterStructure,
+      {bool isExternal, bool isConst, this.isFromEnvironmentConstructor})
+      : super(memberIndex, enclosingClass, name, parameterStructure,
+            isExternal: isExternal, isConst: isConst);
+
+  @override
+  bool get isFactoryConstructor => true;
+
+  @override
+  bool get isGenerativeConstructor => false;
+}
+
+class JMethod extends JFunction {
+  final bool isAbstract;
+
+  JMethod(int memberIndex, JLibrary library, JClass enclosingClass, Name name,
+      ParameterStructure parameterStructure, AsyncMarker asyncMarker,
+      {bool isStatic, bool isExternal, this.isAbstract})
+      : super(memberIndex, library, enclosingClass, name, parameterStructure,
+            asyncMarker,
+            isStatic: isStatic, isExternal: isExternal);
+
+  @override
+  bool get isFunction => true;
+
+  String get _kind => 'method';
+}
+
+class JGetter extends JFunction {
+  final bool isAbstract;
+
+  JGetter(int memberIndex, JLibrary library, JClass enclosingClass, Name name,
+      AsyncMarker asyncMarker,
+      {bool isStatic, bool isExternal, this.isAbstract})
+      : super(memberIndex, library, enclosingClass, name,
+            const ParameterStructure.getter(), asyncMarker,
+            isStatic: isStatic, isExternal: isExternal);
+
+  @override
+  bool get isGetter => true;
+
+  String get _kind => 'getter';
+}
+
+class JSetter extends JFunction {
+  final bool isAbstract;
+
+  JSetter(int memberIndex, JLibrary library, JClass enclosingClass, Name name,
+      {bool isStatic, bool isExternal, this.isAbstract})
+      : super(memberIndex, library, enclosingClass, name,
+            const ParameterStructure.setter(), AsyncMarker.SYNC,
+            isStatic: isStatic, isExternal: isExternal);
+
+  @override
+  bool get isAssignable => true;
+
+  @override
+  bool get isSetter => true;
+
+  String get _kind => 'setter';
+}
+
+class JField extends JMember implements FieldEntity {
+  final bool isAssignable;
+  final bool isConst;
+
+  JField(int memberIndex, JLibrary library, JClass enclosingClass, Name name,
+      {bool isStatic, this.isAssignable, this.isConst})
+      : super(memberIndex, library, enclosingClass, name, isStatic: isStatic);
+
+  @override
+  bool get isField => true;
+
+  String get _kind => 'field';
+}
+
+class JTypeVariable implements TypeVariableEntity {
+  final Entity typeDeclaration;
+  final String name;
+  final int index;
+
+  JTypeVariable(this.typeDeclaration, this.name, this.index);
+
+  String toString() => 'type_variable(${typeDeclaration.name}.$name)';
 }
 
 class JsClosedWorld extends ClosedWorldBase {
@@ -270,7 +690,8 @@
 
   @override
   Iterable<FunctionEntity> get globalFunctionDependencies {
-    return _backendUsage.globalFunctionDependencies.map(_map.toBackendMember);
+    FunctionEntity f(FunctionEntity e) => _map.toBackendMember(e);
+    return _backendUsage.globalFunctionDependencies.map(f);
   }
 
   @override
@@ -297,6 +718,178 @@
   bool get isNoSuchMethodUsed => _backendUsage.isNoSuchMethodUsed;
 }
 
+class JsElementEnvironment implements ElementEnvironment {
+  final JsToFrontendMap _map;
+  final ElementEnvironment _elementEnvironment;
+
+  JsElementEnvironment(this._map, this._elementEnvironment);
+
+  @override
+  Iterable<ConstantValue> getMemberMetadata(MemberEntity member) {
+    throw new UnimplementedError('JsElementEnvironment.getMemberMetadata');
+  }
+
+  @override
+  bool isDeferredLoadLibraryGetter(MemberEntity member) {
+    throw new UnimplementedError(
+        'JsElementEnvironment.isDeferredLoadLibraryGetter');
+  }
+
+  @override
+  DartType getUnaliasedType(DartType type) {
+    throw new UnimplementedError('JsElementEnvironment.getUnaliasedType');
+  }
+
+  @override
+  FunctionType getLocalFunctionType(Local local) {
+    throw new UnimplementedError('JsElementEnvironment.getLocalFunctionType');
+  }
+
+  @override
+  FunctionType getFunctionType(FunctionEntity function) {
+    return _map.toBackendType(
+        _elementEnvironment.getFunctionType(_map.toFrontendMember(function)));
+  }
+
+  @override
+  DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
+    throw new UnimplementedError('JsElementEnvironment.getTypeVariableBound');
+  }
+
+  @override
+  ClassEntity getEffectiveMixinClass(ClassEntity cls) {
+    throw new UnimplementedError('JsElementEnvironment.getEffectiveMixinClass');
+  }
+
+  @override
+  bool isUnnamedMixinApplication(ClassEntity cls) {
+    throw new UnimplementedError(
+        'JsElementEnvironment.isUnnamedMixinApplication');
+  }
+
+  @override
+  bool isMixinApplication(ClassEntity cls) {
+    throw new UnimplementedError('JsElementEnvironment.isMixinApplication');
+  }
+
+  @override
+  bool isGenericClass(ClassEntity cls) {
+    throw new UnimplementedError('JsElementEnvironment.isGenericClass');
+  }
+
+  @override
+  InterfaceType getThisType(ClassEntity cls) {
+    throw new UnimplementedError('JsElementEnvironment.getThisType');
+  }
+
+  @override
+  InterfaceType getRawType(ClassEntity cls) {
+    throw new UnimplementedError('JsElementEnvironment.getRawType');
+  }
+
+  @override
+  DartType get dynamicType {
+    throw new UnimplementedError('JsElementEnvironment.dynamicType');
+  }
+
+  @override
+  InterfaceType createInterfaceType(
+      ClassEntity cls, List<DartType> typeArguments) {
+    throw new UnimplementedError('JsElementEnvironment.createInterfaceType');
+  }
+
+  @override
+  void forEachMixin(ClassEntity cls, void f(ClassEntity mixin)) {
+    throw new UnimplementedError('JsElementEnvironment.forEachMixin');
+  }
+
+  @override
+  void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) {
+    throw new UnimplementedError('JsElementEnvironment.forEachSupertype');
+  }
+
+  @override
+  ClassEntity getSuperClass(ClassEntity cls,
+      {bool skipUnnamedMixinApplications: false}) {
+    throw new UnimplementedError('JsElementEnvironment.getSuperClass');
+  }
+
+  @override
+  void forEachConstructor(
+      ClassEntity cls, void f(ConstructorEntity constructor)) {
+    throw new UnimplementedError('JsElementEnvironment.forEachConstructor');
+  }
+
+  @override
+  void forEachClassMember(
+      ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) {
+    throw new UnimplementedError('JsElementEnvironment.forEachClassMember');
+  }
+
+  @override
+  ConstructorEntity lookupConstructor(ClassEntity cls, String name,
+      {bool required: false}) {
+    throw new UnimplementedError('JsElementEnvironment.lookupConstructor');
+  }
+
+  @override
+  MemberEntity lookupClassMember(ClassEntity cls, String name,
+      {bool setter: false, bool required: false}) {
+    throw new UnimplementedError('JsElementEnvironment.lookupClassMember');
+  }
+
+  @override
+  MemberEntity lookupLibraryMember(LibraryEntity library, String name,
+      {bool setter: false, bool required: false}) {
+    throw new UnimplementedError('JsElementEnvironment.lookupLibraryMember');
+  }
+
+  @override
+  void forEachLibraryMember(
+      LibraryEntity library, void f(MemberEntity member)) {
+    _elementEnvironment.forEachLibraryMember(_map.toFrontendLibrary(library),
+        (MemberEntity member) {
+      f(_map.toBackendMember(member));
+    });
+  }
+
+  @override
+  ClassEntity lookupClass(LibraryEntity library, String name,
+      {bool required: false}) {
+    throw new UnimplementedError('JsElementEnvironment.lookupClass');
+  }
+
+  @override
+  void forEachClass(LibraryEntity library, void f(ClassEntity cls)) {
+    throw new UnimplementedError('JsElementEnvironment.forEachClass');
+  }
+
+  @override
+  LibraryEntity lookupLibrary(Uri uri, {bool required: false}) {
+    throw new UnimplementedError('JsElementEnvironment.lookupLibrary');
+  }
+
+  @override
+  String getLibraryName(LibraryEntity library) {
+    return _elementEnvironment.getLibraryName(_map.toFrontendLibrary(library));
+  }
+
+  @override
+  Iterable<LibraryEntity> get libraries {
+    throw new UnimplementedError('JsElementEnvironment.libraries');
+  }
+
+  @override
+  FunctionEntity get mainFunction {
+    return _map.toBackendMember(_elementEnvironment.mainFunction);
+  }
+
+  @override
+  LibraryEntity get mainLibrary {
+    return _map.toBackendLibrary(_elementEnvironment.mainLibrary);
+  }
+}
+
 class JsCommonElements implements CommonElements {
   final JsToFrontendMap _map;
   final CommonElements _commonElements;
@@ -997,7 +1590,7 @@
 
   @override
   InterfaceType get symbolImplementationType {
-    return _map.fromFrontendType(_commonElements.symbolImplementationType);
+    return _map.toBackendType(_commonElements.symbolImplementationType);
   }
 
   @override
@@ -1007,8 +1600,8 @@
   @override
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
       {bool hasProtoKey: false, bool onlyStringKeys: false}) {
-    return _map.fromFrontendType(_commonElements.getConstantMapTypeFor(
-        _map.toBackendType(sourceType),
+    return _map.toBackendType(_commonElements.getConstantMapTypeFor(
+        _map.toFrontendType(sourceType),
         hasProtoKey: hasProtoKey,
         onlyStringKeys: onlyStringKeys));
   }
@@ -1031,84 +1624,84 @@
 
   @override
   InterfaceType streamType([DartType elementType]) {
-    return _map.fromFrontendType(
-        _commonElements.streamType(_map.toBackendType(elementType)));
+    return _map.toBackendType(
+        _commonElements.streamType(_map.toFrontendType(elementType)));
   }
 
   @override
   InterfaceType futureType([DartType elementType]) {
-    return _map.fromFrontendType(
-        _commonElements.futureType(_map.toBackendType(elementType)));
+    return _map.toBackendType(
+        _commonElements.futureType(_map.toFrontendType(elementType)));
   }
 
   @override
   InterfaceType iterableType([DartType elementType]) {
-    return _map.fromFrontendType(
-        _commonElements.iterableType(_map.toBackendType(elementType)));
+    return _map.toBackendType(
+        _commonElements.iterableType(_map.toFrontendType(elementType)));
   }
 
   @override
   InterfaceType mapType([DartType keyType, DartType valueType]) {
-    return _map.fromFrontendType(_commonElements.mapType(
-        _map.toBackendType(keyType), _map.toBackendType(valueType)));
+    return _map.toBackendType(_commonElements.mapType(
+        _map.toFrontendType(keyType), _map.toFrontendType(valueType)));
   }
 
   @override
   InterfaceType listType([DartType elementType]) {
-    return _map.fromFrontendType(
-        _commonElements.listType(_map.toBackendType(elementType)));
+    return _map.toBackendType(
+        _commonElements.listType(_map.toFrontendType(elementType)));
   }
 
   @override
   InterfaceType get stackTraceType =>
-      _map.fromFrontendType(_commonElements.stackTraceType);
+      _map.toBackendType(_commonElements.stackTraceType);
 
   @override
   InterfaceType get typeLiteralType =>
-      _map.fromFrontendType(_commonElements.typeLiteralType);
+      _map.toBackendType(_commonElements.typeLiteralType);
 
   @override
-  InterfaceType get typeType => _map.fromFrontendType(_commonElements.typeType);
+  InterfaceType get typeType => _map.toBackendType(_commonElements.typeType);
 
   @override
-  InterfaceType get nullType => _map.fromFrontendType(_commonElements.nullType);
+  InterfaceType get nullType => _map.toBackendType(_commonElements.nullType);
 
   @override
   InterfaceType get functionType =>
-      _map.fromFrontendType(_commonElements.functionType);
+      _map.toBackendType(_commonElements.functionType);
 
   @override
   InterfaceType get symbolType =>
-      _map.fromFrontendType(_commonElements.symbolType);
+      _map.toBackendType(_commonElements.symbolType);
 
   @override
   InterfaceType get stringType =>
-      _map.fromFrontendType(_commonElements.stringType);
+      _map.toBackendType(_commonElements.stringType);
 
   @override
   InterfaceType get resourceType =>
-      _map.fromFrontendType(_commonElements.resourceType);
+      _map.toBackendType(_commonElements.resourceType);
 
   @override
   InterfaceType get doubleType =>
-      _map.fromFrontendType(_commonElements.doubleType);
+      _map.toBackendType(_commonElements.doubleType);
 
   @override
-  InterfaceType get intType => _map.fromFrontendType(_commonElements.intType);
+  InterfaceType get intType => _map.toBackendType(_commonElements.intType);
 
   @override
-  InterfaceType get numType => _map.fromFrontendType(_commonElements.numType);
+  InterfaceType get numType => _map.toBackendType(_commonElements.numType);
 
   @override
-  InterfaceType get boolType => _map.fromFrontendType(_commonElements.boolType);
+  InterfaceType get boolType => _map.toBackendType(_commonElements.boolType);
 
   @override
   InterfaceType get objectType =>
-      _map.fromFrontendType(_commonElements.objectType);
+      _map.toBackendType(_commonElements.objectType);
 
   @override
   DynamicType get dynamicType =>
-      _map.fromFrontendType(_commonElements.dynamicType);
+      _map.toBackendType(_commonElements.dynamicType);
 
   @override
   bool isFilledListConstructor(ConstructorEntity element) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index e3ea086..505ea3b 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -5,6 +5,8 @@
 library dart2js.js_model.strategy;
 
 import '../backend_strategy.dart';
+import '../closure.dart' show ClosureConversionTask;
+import '../common/tasks.dart';
 import '../common_elements.dart';
 import '../compiler.dart';
 import '../elements/elements.dart' show TypedefElement;
@@ -18,7 +20,10 @@
 import '../js_backend/constant_system_javascript.dart';
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
+import '../kernel/element_map.dart';
+import '../kernel/element_map_impl.dart';
 import '../kernel/kernel_backend_strategy.dart';
+import '../kernel/kernel_strategy.dart';
 import '../ssa/ssa.dart';
 import '../universe/class_set.dart';
 import '../universe/world_builder.dart';
@@ -28,20 +33,23 @@
 
 class JsBackendStrategy implements BackendStrategy {
   final Compiler _compiler;
-  final JsToFrontendMap _map = new JsToFrontendMap();
+  final JsToFrontendMap _map = new JsToFrontendMapImpl();
+  ElementEnvironment _elementEnvironment;
+  CommonElements _commonElements;
 
   JsBackendStrategy(this._compiler);
 
   @override
   ClosedWorldRefiner createClosedWorldRefiner(ClosedWorld closedWorld) {
-    CommonElements commonElements =
-        new JsCommonElements(_map, closedWorld.commonElements);
+    _elementEnvironment =
+        new JsElementEnvironment(_map, closedWorld.elementEnvironment);
+    _commonElements = new JsCommonElements(_map, closedWorld.commonElements);
     BackendUsage backendUsage =
         new JsBackendUsage(_map, closedWorld.backendUsage);
     NativeData nativeData = new JsNativeData(_map, closedWorld.nativeData);
     InterceptorData interceptorData = new InterceptorDataImpl(
         nativeData,
-        commonElements,
+        _commonElements,
         // TODO(johnniwinther): Convert these.
         const {},
         new Set(),
@@ -89,9 +97,8 @@
     }, ClassHierarchyNode.ALL);
 
     return new JsClosedWorld(
-        // TODO(johnniwinther): Create a JsElementEnvironment.
-        elementEnvironment: closedWorld.elementEnvironment,
-        commonElements: commonElements,
+        elementEnvironment: _elementEnvironment,
+        commonElements: _commonElements,
         constantSystem: const JavaScriptConstantSystem(),
         backendUsage: backendUsage,
         nativeData: nativeData,
@@ -109,16 +116,21 @@
   }
 
   @override
-  void convertClosures(ClosedWorldRefiner closedWorldRefiner) {}
+  ClosureConversionTask createClosureConversionTask(Compiler compiler) =>
+      new KernelClosureConversionTask(compiler.measurer);
 
   @override
   SourceInformationStrategy get sourceInformationStrategy =>
       const JavaScriptSourceInformationStrategy();
 
   @override
-  SsaBuilderTask createSsaBuilderTask(JavaScriptBackend backend,
+  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
       SourceInformationStrategy sourceInformationStrategy) {
-    return new KernelSsaBuilderTask(backend.compiler);
+    KernelFrontEndStrategy strategy = backend.compiler.frontendStrategy;
+    KernelToElementMap elementMap = strategy.elementMap;
+    JsKernelToElementMap jsElementMap = new JsKernelToElementMap(
+        _map, _elementEnvironment, _commonElements, elementMap);
+    return new KernelSsaBuilder(task, backend.compiler, jsElementMap);
   }
 
   @override
@@ -131,7 +143,12 @@
       NativeBasicData nativeBasicData,
       ClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy) {
-    return new KernelCodegenWorldBuilder(closedWorld.elementEnvironment,
-        nativeBasicData, closedWorld, selectorConstraintsStrategy);
+    KernelFrontEndStrategy frontendStrategy = _compiler.frontendStrategy;
+    return new KernelCodegenWorldBuilder(
+        frontendStrategy.elementMap,
+        closedWorld.elementEnvironment,
+        nativeBasicData,
+        closedWorld,
+        selectorConstraintsStrategy);
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index df4209a..7407499 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.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:js_runtime/shared/embedded_names.dart';
 import 'package:kernel/ast.dart' as ir;
 
 import '../closure.dart';
@@ -16,7 +17,10 @@
 import '../elements/names.dart';
 import '../elements/operators.dart';
 import '../elements/types.dart';
+import '../js/js.dart' as js;
 import '../js_backend/backend.dart' show JavaScriptBackend;
+import '../js_backend/namer.dart';
+import '../js_emitter/code_emitter_task.dart';
 import '../native/native.dart' as native;
 import '../types/types.dart';
 import '../universe/call_structure.dart';
@@ -44,10 +48,6 @@
   /// Returns the [InterfaceType] corresponding to [type].
   InterfaceType getInterfaceType(ir.InterfaceType type);
 
-  /// 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);
-
   /// Return the [InterfaceType] corresponding to the [cls] with the given
   /// [typeArguments].
   InterfaceType createInterfaceType(
@@ -86,6 +86,9 @@
   /// Returns the [MemberEntity] corresponding to the member [node].
   MemberEntity getMember(ir.Member node);
 
+  /// Returns the kernel IR node that defines the [member].
+  ir.Node getMemberNode(covariant MemberEntity member);
+
   /// Returns the [FunctionEntity] corresponding to the procedure [node].
   FunctionEntity getMethod(ir.Procedure node);
 
@@ -147,6 +150,13 @@
   /// Compute the kind of foreign helper function called by [node], if any.
   ForeignKind getForeignKind(ir.StaticInvocation node);
 
+  /// Returns the [js.Name] for the `JsGetName` [constant] value.
+  js.Name getNameForJsGetName(ConstantValue constant, Namer namer);
+
+  /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
+  js.Template getJsBuiltinTemplate(
+      ConstantValue constant, CodeEmitterTask emitter);
+
   /// Computes the [InterfaceType] referenced by a call to the
   /// [JS_INTERCEPTOR_CONSTANT] function, if any.
   InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node);
@@ -535,6 +545,36 @@
         failedAt(cls, "No super noSuchMethod found for class $cls."));
     return function;
   }
+
+  js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
+    int index = _extractEnumIndexFromConstantValue(
+        constant, commonElements.jsGetNameEnum);
+    if (index == null) return null;
+    return namer.getNameForJsGetName(
+        CURRENT_ELEMENT_SPANNABLE, JsGetName.values[index]);
+  }
+
+  js.Template getJsBuiltinTemplate(
+      ConstantValue constant, CodeEmitterTask emitter) {
+    int index = _extractEnumIndexFromConstantValue(
+        constant, commonElements.jsBuiltinEnum);
+    if (index == null) return null;
+    return emitter.builtinTemplateFor(JsBuiltin.values[index]);
+  }
+
+  int _extractEnumIndexFromConstantValue(
+      ConstantValue constant, ClassEntity classElement) {
+    if (constant is ConstructedConstantValue) {
+      if (constant.type.element == classElement) {
+        assert(constant.fields.length == 1 || constant.fields.length == 2);
+        ConstantValue indexConstant = constant.fields.values.first;
+        if (indexConstant is IntConstantValue) {
+          return indexConstant.primitiveValue;
+        }
+      }
+    }
+    return null;
+  }
 }
 
 /// Visitor that converts string literals and concatenations of string literals
@@ -980,8 +1020,8 @@
   TypeMask typeOfSet(ir.PropertySet write, ClosedWorld closedWorld);
 
   /// Returns the inferred type of [listLiteral].
-  TypeMask typeOfListLiteral(
-      MemberEntity owner, ir.ListLiteral listLiteral, ClosedWorld closedWorld);
+  TypeMask typeOfListLiteral(covariant MemberEntity owner,
+      ir.ListLiteral listLiteral, ClosedWorld closedWorld);
 
   /// Returns the inferred type of iterator in [forInStatement].
   TypeMask typeOfIterator(ir.ForInStatement forInStatement);
@@ -1027,10 +1067,10 @@
   // TODO(johnniwinther): Make these return the [KernelToLocalsMap] to use from
   // now on.
   /// Call to notify that [member] is currently being inlined.
-  void enterInlinedMember(MemberEntity member);
+  void enterInlinedMember(covariant MemberEntity member);
 
   /// Call to notify that [member] is no longer being inlined.
-  void leaveInlinedMember(MemberEntity member);
+  void leaveInlinedMember(covariant MemberEntity member);
 
   /// Returns the [Local] for [node].
   Local getLocal(ir.VariableDeclaration node);
@@ -1042,5 +1082,11 @@
   /// Returns the [LoopClosureRepresentationInfo] for the loop [node] in
   /// [closureClassMaps].
   LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
-      ClosureClassMaps closureClassMaps, ir.TreeNode node);
+      ClosureDataLookup closureLookup, ir.TreeNode node);
+}
+
+/// Comparator for the canonical order or named arguments.
+// TODO(johnniwinther): Remove this when named parameters are sorted in dill.
+int namedOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
+  return a.name.compareTo(b.name);
 }
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 07dc4f6..9ec2d3c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -29,6 +29,7 @@
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
+import '../js_model/elements.dart';
 import '../native/native.dart' as native;
 import '../native/resolver.dart';
 import '../ordered_typeset.dart';
@@ -141,6 +142,7 @@
 
   @override
   ConstantValue getFieldConstantValue(ir.Field field) {
+    // TODO(johnniwinther): Cache the result in [_FieldData].
     return getConstantValue(field.initializer, requireConstant: field.isConst);
   }
 
@@ -494,7 +496,7 @@
     }
   }
 
-  InterfaceType getThisType(KClass cls) {
+  InterfaceType _getThisType(KClass cls) {
     _KClassEnv env = _classEnvs[cls.classIndex];
     _ensureThisAndRawType(cls, env);
     return env.thisType;
@@ -576,7 +578,7 @@
 
   DartType _substByContext(DartType type, InterfaceType context) {
     return type.subst(
-        context.typeArguments, getThisType(context.element).typeArguments);
+        context.typeArguments, _getThisType(context.element).typeArguments);
   }
 
   InterfaceType _getSuperType(KClass cls) {
@@ -673,12 +675,31 @@
   @override
   FieldEntity getField(ir.Field node) => _getField(node);
 
+  bool hasConstantFieldInitializer(KField field) {
+    _FieldData data = _memberList[field.memberIndex];
+    return getFieldConstantValue(data.node) != null;
+  }
+
+  ConstantValue getConstantFieldInitializer(KField field) {
+    _FieldData data = _memberList[field.memberIndex];
+    ConstantValue value = getFieldConstantValue(data.node);
+    assert(value != null,
+        failedAt(field, "Field $field doesn't have a constant initial value."));
+    return value;
+  }
+
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       _getTypeVariable(node);
 
   @override
   FunctionEntity getMethod(ir.Procedure node) => _getMethod(node);
 
+  void forEachParameter(KFunction function,
+      void f(DartType type, String name, ConstantValue defaultValue)) {
+    _FunctionData data = _memberList[function.memberIndex];
+    data.forEachParameter(this, f);
+  }
+
   @override
   MemberEntity getMember(ir.Member node) {
     if (node is ir.Field) {
@@ -742,8 +763,8 @@
     return member;
   }
 
-  /// Returns the kernel IR node that defines the [member].
-  ir.Member getMemberNode(KMember member) {
+  @override
+  ir.Member getMemberNode(covariant KMember member) {
     return _memberList[member.memberIndex].node;
   }
 
@@ -1066,6 +1087,31 @@
   FunctionType getFunctionType(KernelToElementMapImpl elementMap) {
     return _type ??= elementMap.getFunctionType(functionNode);
   }
+
+  void forEachParameter(KernelToElementMap elementMap,
+      void f(DartType type, String name, ConstantValue defaultValue)) {
+    void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
+      DartType type = elementMap.getDartType(node.type);
+      String name = node.name;
+      ConstantValue defaultValue;
+      if (isOptional) {
+        if (node.initializer != null) {
+          defaultValue = elementMap.getConstantValue(node.initializer);
+        } else {
+          defaultValue = new NullConstantValue();
+        }
+      }
+      f(type, name, defaultValue);
+    }
+
+    for (int i = 0; i < functionNode.positionalParameters.length; i++) {
+      handleParameter(functionNode.positionalParameters[i],
+          isOptional: i < functionNode.requiredParameterCount);
+    }
+    functionNode.namedParameters.toList()
+      ..sort(namedOrdering)
+      ..forEach(handleParameter);
+  }
 }
 
 class _ConstructorData extends _FunctionData {
@@ -1138,7 +1184,7 @@
 
   @override
   InterfaceType getThisType(ClassEntity cls) {
-    return elementMap.getThisType(cls);
+    return elementMap._getThisType(cls);
   }
 
   @override
@@ -1152,12 +1198,12 @@
   }
 
   @override
-  bool isMixinApplication(KClass cls) {
+  bool isMixinApplication(covariant KClass cls) {
     return elementMap._isMixinApplication(cls);
   }
 
   @override
-  bool isUnnamedMixinApplication(KClass cls) {
+  bool isUnnamedMixinApplication(covariant KClass cls) {
     return elementMap._isUnnamedMixinApplication(cls);
   }
 
@@ -1183,12 +1229,12 @@
   }
 
   @override
-  FunctionType getFunctionType(KFunction function) {
+  FunctionType getFunctionType(covariant KFunction function) {
     return elementMap._getFunctionType(function);
   }
 
   @override
-  FunctionType getLocalFunctionType(KLocalFunction function) {
+  FunctionType getLocalFunctionType(covariant KLocalFunction function) {
     return function.functionType;
   }
 
@@ -1285,7 +1331,7 @@
   }
 
   @override
-  void forEachClass(KLibrary library, void f(ClassEntity cls)) {
+  void forEachClass(covariant KLibrary library, void f(ClassEntity cls)) {
     elementMap._forEachClass(library, f);
   }
 
@@ -1300,13 +1346,13 @@
   }
 
   @override
-  bool isDeferredLoadLibraryGetter(KMember member) {
+  bool isDeferredLoadLibraryGetter(covariant KMember member) {
     // TODO(johnniwinther): Support these.
     return false;
   }
 
   @override
-  Iterable<ConstantValue> getMemberMetadata(KMember member) {
+  Iterable<ConstantValue> getMemberMetadata(covariant KMember member) {
     _MemberData memberData = elementMap._memberList[member.memberIndex];
     return memberData.getMetadata(elementMap);
   }
@@ -1670,13 +1716,14 @@
   CommonElements get commonElements => elementMap.commonElements;
 
   @override
-  native.NativeBehavior computeNativeFieldStoreBehavior(KField field) {
+  native.NativeBehavior computeNativeFieldStoreBehavior(
+      covariant KField field) {
     ir.Field node = elementMap._memberList[field.memberIndex].node;
     return elementMap.getNativeBehaviorForFieldStore(node);
   }
 
   @override
-  native.NativeBehavior computeNativeFieldLoadBehavior(KField field,
+  native.NativeBehavior computeNativeFieldLoadBehavior(covariant KField field,
       {bool isJsInterop}) {
     ir.Field node = elementMap._memberList[field.memberIndex].node;
     return elementMap.getNativeBehaviorForFieldLoad(node,
@@ -1684,7 +1731,8 @@
   }
 
   @override
-  native.NativeBehavior computeNativeMethodBehavior(KFunction function,
+  native.NativeBehavior computeNativeMethodBehavior(
+      covariant KFunction function,
       {bool isJsInterop}) {
     ir.Member node = elementMap._memberList[function.memberIndex].node;
     return elementMap.getNativeBehaviorForMethod(node,
@@ -1692,7 +1740,7 @@
   }
 
   @override
-  bool isNativeMethod(KFunction function) {
+  bool isNativeMethod(covariant KFunction function) {
     if (!native.maybeEnableNative(function.library.canonicalUri)) return false;
     ir.Member node = elementMap._memberList[function.memberIndex].node;
     return node.isExternal &&
@@ -1705,3 +1753,130 @@
     return false;
   }
 }
+
+class JsKernelToElementMap extends KernelToElementMapMixin {
+  final JsToFrontendMap _map;
+  final ElementEnvironment _elementEnvironment;
+  final CommonElements _commonElements;
+  final KernelToElementMapImpl _elementMap;
+
+  JsKernelToElementMap(this._map, this._elementEnvironment,
+      this._commonElements, this._elementMap);
+
+  @override
+  Spannable getSpannable(MemberEntity member, ir.Node node) {
+    return _elementMap.getSpannable(_map.toFrontendMember(member), node);
+  }
+
+  @override
+  LibraryEntity getLibrary(ir.Library node) {
+    return _map.toBackendLibrary(_elementMap.getLibrary(node));
+  }
+
+  @override
+  Local getLocalFunction(ir.TreeNode node) {
+    throw new UnsupportedError("JsKernelToElementMap.getLocalFunction");
+  }
+
+  @override
+  ClassEntity getClass(ir.Class node) {
+    return _map.toBackendClass(_elementMap.getClass(node));
+  }
+
+  @override
+  FieldEntity getField(ir.Field node) {
+    return _map.toBackendMember(_elementMap.getField(node));
+  }
+
+  @override
+  MemberEntity getSuperMember(ir.Member context, ir.Name name, ir.Member target,
+      {bool setter: false}) {
+    return _map.toBackendMember(
+        _elementMap.getSuperMember(context, name, target, setter: setter));
+  }
+
+  @override
+  FunctionEntity getMethod(ir.Procedure node) {
+    return _map.toBackendMember(_elementMap.getMethod(node));
+  }
+
+  @override
+  ir.Member getMemberNode(MemberEntity member) {
+    return _elementMap.getMemberNode(_map.toFrontendMember(member));
+  }
+
+  @override
+  MemberEntity getMember(ir.Member node) {
+    return _map.toBackendMember(_elementMap.getMember(node));
+  }
+
+  @override
+  ConstructorEntity getSuperConstructor(
+      ir.Constructor constructor, ir.Member target) {
+    return _map
+        .toBackendMember(_elementMap.getSuperConstructor(constructor, target));
+  }
+
+  @override
+  ConstructorEntity getConstructor(ir.Member node) {
+    return _map.toBackendMember(_elementMap.getConstructor(node));
+  }
+
+  @override
+  InterfaceType createInterfaceType(
+      ir.Class cls, List<ir.DartType> typeArguments) {
+    return _map
+        .toBackendType(_elementMap.createInterfaceType(cls, typeArguments));
+  }
+
+  @override
+  InterfaceType getInterfaceType(ir.InterfaceType type) {
+    return _map.toBackendType(_elementMap.getInterfaceType(type));
+  }
+
+  @override
+  List<DartType> getDartTypes(List<ir.DartType> types) {
+    return _elementMap.getDartTypes(types).map(_map.toBackendType).toList();
+  }
+
+  @override
+  FunctionType getFunctionType(ir.FunctionNode node) {
+    return _map.toBackendType(_elementMap.getFunctionType(node));
+  }
+
+  @override
+  DartType getDartType(ir.DartType type) {
+    return _map.toBackendType(_elementMap.getDartType(type));
+  }
+
+  @override
+  ElementEnvironment get elementEnvironment {
+    return _elementEnvironment;
+  }
+
+  @override
+  CommonElements get commonElements {
+    return _commonElements;
+  }
+
+  @override
+  ConstantValue computeConstantValue(ConstantExpression constant,
+      {bool requireConstant: true}) {
+    throw new UnsupportedError("JsKernelToElementMap.computeConstantValue");
+  }
+
+  @override
+  native.BehaviorBuilder get nativeBehaviorBuilder {
+    throw new UnsupportedError("JsKernelToElementMap.nativeBehaviorBuilder");
+  }
+
+  @override
+  DiagnosticReporter get reporter {
+    return _elementMap.reporter;
+  }
+
+  @override
+  ConstantValue getFieldConstantValue(ir.Field field) {
+    throw new UnsupportedError("JsKernelToElementMap.getFieldConstantValue");
+  }
+}
diff --git a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
index c5ef1b1..0dac29e 100644
--- a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
@@ -46,7 +46,8 @@
   KernelBackendStrategy(this._compiler);
 
   @override
-  ClosedWorldRefiner createClosedWorldRefiner(KernelClosedWorld closedWorld) {
+  ClosedWorldRefiner createClosedWorldRefiner(
+      covariant KernelClosedWorld closedWorld) {
     return closedWorld;
   }
 
@@ -60,10 +61,8 @@
   }
 
   @override
-  void convertClosures(ClosedWorldRefiner closedWorldRefiner) {
-    // TODO(johnniwinther,efortuna): Compute closure classes for kernel based
-    // elements.
-  }
+  ClosureConversionTask createClosureConversionTask(Compiler compiler) =>
+      new KernelClosureConversionTask(compiler.measurer);
 
   @override
   WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld) {
@@ -75,14 +74,21 @@
       NativeBasicData nativeBasicData,
       ClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy) {
-    return new KernelCodegenWorldBuilder(closedWorld.elementEnvironment,
-        nativeBasicData, closedWorld, selectorConstraintsStrategy);
+    KernelFrontEndStrategy frontendStrategy = _compiler.frontendStrategy;
+    return new KernelCodegenWorldBuilder(
+        frontendStrategy.elementMap,
+        closedWorld.elementEnvironment,
+        nativeBasicData,
+        closedWorld,
+        selectorConstraintsStrategy);
   }
 
   @override
-  SsaBuilderTask createSsaBuilderTask(JavaScriptBackend backend,
+  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
       SourceInformationStrategy sourceInformationStrategy) {
-    return new KernelSsaBuilderTask(backend.compiler);
+    KernelFrontEndStrategy strategy = backend.compiler.frontendStrategy;
+    KernelToElementMap elementMap = strategy.elementMap;
+    return new KernelSsaBuilder(task, backend.compiler, elementMap);
   }
 
   @override
@@ -119,7 +125,8 @@
   final CodegenRegistry registry;
 
   KernelCodegenWorkItem(this._backend, this._closedWorld, this.element)
-      : registry = new CodegenRegistry(element);
+      : registry =
+            new CodegenRegistry(_closedWorld.elementEnvironment, element);
 
   @override
   WorldImpact run() {
@@ -128,19 +135,16 @@
 }
 
 /// Task for building SSA from kernel IR loaded from .dill.
-class KernelSsaBuilderTask extends CompilerTask implements SsaBuilderTask {
+class KernelSsaBuilder implements SsaBuilder {
+  final CompilerTask task;
   final Compiler _compiler;
+  final KernelToElementMap _elementMap;
 
-  KernelSsaBuilderTask(this._compiler) : super(_compiler.measurer);
-
-  KernelToElementMapImpl get _elementMap {
-    KernelFrontEndStrategy frontendStrategy = _compiler.frontendStrategy;
-    return frontendStrategy.elementMap;
-  }
+  KernelSsaBuilder(this.task, this._compiler, this._elementMap);
 
   @override
   HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
-    KernelSsaBuilder builder = new KernelSsaBuilder(
+    KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
         work.element,
         work.element.enclosingClass,
         _elementMap.getMemberNode(work.element),
@@ -151,8 +155,8 @@
         closedWorld,
         _compiler.codegenWorldBuilder,
         work.registry,
+        _compiler.closureDataLookup,
         // TODO(johnniwinther): Support these:
-        const KernelClosureClassMaps(),
         const SourceInformationBuilder(),
         null, // Function node used as capture scope id.
         targetIsConstructorBody: false);
@@ -268,7 +272,8 @@
 
   @override
   JumpTarget getJumpTarget(ir.TreeNode node, {bool isContinueTarget: false}) {
-    throw new UnimplementedError('KernelToLocalsMapImpl.getJumpTarget');
+    // TODO(johnniwinther): Support jump targets.
+    return null;
   }
 
   @override
@@ -280,7 +285,7 @@
 
   @override
   LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
-      ClosureClassMaps closureClassMaps, ir.TreeNode node) {
+      ClosureDataLookup closureLookup, ir.TreeNode node) {
     return const LoopClosureRepresentationInfo();
   }
 }
@@ -309,22 +314,31 @@
   }
 }
 
-/// TODO(johnniwinther,efortuna): Implement this.
-class KernelClosureClassMaps implements ClosureClassMaps<ir.Node> {
-  const KernelClosureClassMaps();
+/// Closure conversion code using our new Entity model. Closure conversion is
+/// necessary because the semantics of closures are slightly different in Dart
+/// than JavaScript. Closure conversion is separated out into two phases:
+/// generation of a new (temporary) representation to store where variables need
+/// to be hoisted/captured up at another level to re-write the closure, and then
+/// the code generation phase where we generate elements and/or instructions to
+/// represent this new code path.
+///
+/// For a general explanation of how closure conversion works at a high level,
+/// check out:
+/// http://siek.blogspot.com/2012/07/essence-of-closure-conversion.html or
+/// http://matt.might.net/articles/closure-conversion/.
+class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
+  KernelClosureConversionTask(Measurer measurer) : super(measurer);
 
+  /// The combined steps of generating our intermediate representation of
+  /// closures that need to be rewritten and generating the element model.
+  /// Ultimately these two steps will be split apart with the second step
+  /// happening later in compilation just before codegen. These steps are
+  /// combined here currently to provide a consistent interface to the rest of
+  /// the compiler until we are ready to separate these phases.
   @override
-  ClosureClassMap getLocalFunctionMap(Local localFunction) {
-    return new ClosureClassMap(null, null, null, null);
-  }
-
-  @override
-  ClosureClassMap getMemberMap(MemberEntity member) {
-    ThisLocal thisLocal;
-    if (member.isInstanceMember) {
-      thisLocal = new ThisLocal(member);
-    }
-    return new ClosureClassMap(null, null, null, thisLocal);
+  void convertClosures(Iterable<MemberEntity> processedEntities,
+      ClosedWorldRefiner closedWorldRefiner) {
+    // TODO(efortuna): implement.
   }
 
   @override
@@ -337,6 +351,18 @@
       ir.Node loopNode) {
     return const LoopClosureRepresentationInfo();
   }
+
+  @override
+  ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) {
+    if (entity is MemberEntity) {
+      ThisLocal thisLocal;
+      if (entity.isInstanceMember) {
+        thisLocal = new ThisLocal(entity);
+      }
+      return new ClosureClassMap(null, null, null, thisLocal);
+    }
+    return const ClosureRepresentationInfo();
+  }
 }
 
 class KernelSorter implements Sorter {
diff --git a/pkg/compiler/lib/src/kernel/kernel_visitor.dart b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
index a344f42..c947b30 100644
--- a/pkg/compiler/lib/src/kernel/kernel_visitor.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
@@ -217,7 +217,7 @@
     return node;
   }
 
-  ir.Node associateNode(ir.Node node, Node ast) {
+  N associateNode<N extends ir.Node>(N node, Node ast) {
     kernel.nodeToAst[node] = ast;
     return node;
   }
@@ -406,8 +406,8 @@
 
   @override
   ir.AssertStatement visitAssert(Assert node) {
-    return new ir.AssertStatement(
-        visitForValue(node.condition), visitForValue(node.message));
+    return new ir.AssertStatement(visitForValue(node.condition),
+        message: visitForValue(node.message));
   }
 
   ir.LabeledStatement getBreakTarget(JumpTarget target) {
@@ -1275,7 +1275,7 @@
 
   @override
   ir.Expression visitClassTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, _) {
+      SendSet node, TypeConstantExpression constant, Node rhs, _) {
     return buildTypeLiteralSet(constant, rhs);
   }
 
@@ -1412,7 +1412,7 @@
 
   @override
   ir.Expression visitDynamicTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, _) {
+      SendSet node, TypeConstantExpression constant, Node rhs, _) {
     return buildTypeLiteralSet(constant, rhs);
   }
 
@@ -1493,7 +1493,8 @@
         // Mixin application implicit super call.
         arguments = <ir.Expression>[];
         named = <ir.NamedExpression>[];
-        signature.orderedForEachParameter((ParameterElement parameter) {
+        signature.orderedForEachParameter((_parameter) {
+          ParameterElement parameter = _parameter;
           ir.VariableGet argument = buildLocalGet(parameter);
           if (parameter.isNamed) {
             named.add(new ir.NamedExpression(parameter.name, argument));
@@ -2112,7 +2113,8 @@
     if (function.hasFunctionSignature) {
       FunctionSignature signature = function.functionSignature;
       requiredParameterCount = signature.requiredParameterCount;
-      signature.forEachParameter((ParameterElement parameter) {
+      signature.forEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         ir.VariableDeclaration variable = getLocal(parameter);
         if (parameter.isNamed) {
           namedParameters.add(variable);
@@ -2120,7 +2122,8 @@
           positionalParameters.add(variable);
         }
       });
-      signature.forEachParameter((ParameterElement parameter) {
+      signature.forEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         if (!parameter.isOptional) return;
         ir.Expression initializer = visitForValue(parameter.initializer);
         ir.VariableDeclaration variable = getLocal(parameter);
@@ -2320,7 +2323,7 @@
 
   @override
   ir.Expression handleStaticGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, _) {
+      SendSet node, GetterElement getter, Node rhs, _) {
     return buildStaticAccessor(getter)
         .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
   }
@@ -2356,7 +2359,7 @@
   }
 
   @override
-  ir.SuperMethodInvocation visitSuperBinary(Send node, FunctionElement function,
+  ir.SuperMethodInvocation visitSuperBinary(Send node, MethodElement function,
       BinaryOperator operator, Node argument, _) {
     transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(
@@ -2409,7 +2412,7 @@
 
   @override
   ir.SuperMethodInvocation visitSuperEquals(
-      Send node, FunctionElement function, Node argument, _) {
+      Send node, MethodElement function, Node argument, _) {
     return buildSuperEquals(function, argument);
   }
 
@@ -2516,8 +2519,7 @@
   }
 
   @override
-  ir.SuperPropertyGet visitSuperGetterGet(
-      Send node, FunctionElement getter, _) {
+  ir.SuperPropertyGet visitSuperGetterGet(Send node, MethodElement getter, _) {
     return buildSuperPropertyAccessor(getter).buildSimpleRead();
   }
 
@@ -2553,7 +2555,7 @@
 
   @override
   ir.SuperMethodInvocation visitSuperIndex(
-      Send node, FunctionElement function, Node index, _) {
+      Send node, MethodElement function, Node index, _) {
     return buildSuperIndexAccessor(index, function).buildSimpleRead();
   }
 
@@ -2614,14 +2616,14 @@
 
   @override
   ir.Expression visitSuperMethodSet(
-      Send node, MethodElement method, Node rhs, _) {
+      SendSet node, MethodElement method, Node rhs, _) {
     return buildSuperPropertyAccessor(method)
         .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
   }
 
   @override
   ir.Not visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, _) {
+      Send node, MethodElement function, Node argument, _) {
     return new ir.Not(buildSuperEquals(function, argument));
   }
 
@@ -2646,7 +2648,7 @@
 
   @override
   ir.SuperMethodInvocation visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, _) {
+      Send node, UnaryOperator operator, MethodElement function, _) {
     transformerFlags |= TransformerFlag.superCalls;
     return new ir.SuperMethodInvocation(kernel.irName(function.name, function),
         new ir.Arguments.empty(), kernel.functionToIr(function));
@@ -2824,7 +2826,7 @@
 
   @override
   ir.Expression visitTypedefTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, _) {
+      SendSet node, TypeConstantExpression constant, Node rhs, _) {
     return buildTypeLiteralSet(constant, rhs);
   }
 
@@ -2878,6 +2880,7 @@
   }
 
   @override
+  // TODO(ahe): Remove this ignore when strong-mode only.
   // ignore: INVALID_METHOD_OVERRIDE_RETURN_TYPE
   ir.Node visitVariableDefinitions(VariableDefinitions definitions) {
     // TODO(ahe): This method is copied from [SemanticDeclarationResolvedMixin]
@@ -2886,12 +2889,11 @@
     computeVariableStructures(definitions,
         (Node node, VariableStructure structure) {
       if (structure == null) {
-        return internalError(node, 'No structure for $node');
+        internalError(node, 'No structure for $node');
       } else {
         ir.VariableDeclaration variable =
             structure.dispatch(declVisitor, node, null);
         variables.add(variable);
-        return variable;
       }
     });
     if (variables.length == 1) return variables.single;
diff --git a/pkg/compiler/lib/src/kernel/task.dart b/pkg/compiler/lib/src/kernel/task.dart
index 81637a2..63532fc 100644
--- a/pkg/compiler/lib/src/kernel/task.dart
+++ b/pkg/compiler/lib/src/kernel/task.dart
@@ -29,7 +29,8 @@
   ///
   /// May enqueue more elements to the resolution queue.
   void buildKernelIr() => measure(() {
-        program = buildProgram(_compiler.mainApp);
+        program = buildProgram(
+            _compiler.frontendStrategy.elementEnvironment.mainLibrary);
       });
 
   /// Builds the kernel IR program for the main function exported from
diff --git a/pkg/compiler/lib/src/kernel/types.dart b/pkg/compiler/lib/src/kernel/types.dart
index af6884d3..a0f6268 100644
--- a/pkg/compiler/lib/src/kernel/types.dart
+++ b/pkg/compiler/lib/src/kernel/types.dart
@@ -7,8 +7,8 @@
 /// Support for subtype checks of kernel based [DartType]s.
 class _KernelDartTypes extends DartTypes {
   final KernelToElementMapImpl elementMap;
-  final SubtypeVisitor subtypeVisitor;
-  final PotentialSubtypeVisitor potentialSubtypeVisitor;
+  final SubtypeVisitor<DartType> subtypeVisitor;
+  final PotentialSubtypeVisitor<DartType> potentialSubtypeVisitor;
 
   _KernelDartTypes(this.elementMap)
       : this.subtypeVisitor = new _KernelSubtypeVisitor(elementMap),
@@ -32,7 +32,7 @@
 
   @override
   InterfaceType getThisType(ClassEntity cls) {
-    return elementMap.getThisType(cls);
+    return elementMap._getThisType(cls);
   }
 
   @override
@@ -82,7 +82,7 @@
             objectType: elementMap.commonElements.objectType);
 
   InterfaceType getThisType(ClassEntity cls) {
-    return elementMap.getThisType(cls);
+    return elementMap._getThisType(cls);
   }
 
   InterfaceType substByContext(InterfaceType type, InterfaceType context) {
@@ -98,7 +98,8 @@
   }
 }
 
-abstract class _AbstractTypeRelationMixin implements AbstractTypeRelation {
+abstract class _AbstractTypeRelationMixin
+    implements AbstractTypeRelation<DartType> {
   KernelToElementMapImpl get elementMap;
 
   @override
@@ -122,14 +123,14 @@
   }
 }
 
-class _KernelSubtypeVisitor extends SubtypeVisitor
+class _KernelSubtypeVisitor extends SubtypeVisitor<DartType>
     with _AbstractTypeRelationMixin {
   final KernelToElementMapImpl elementMap;
 
   _KernelSubtypeVisitor(this.elementMap);
 }
 
-class _KernelPotentialSubtypeVisitor extends PotentialSubtypeVisitor
+class _KernelPotentialSubtypeVisitor extends PotentialSubtypeVisitor<DartType>
     with _AbstractTypeRelationMixin {
   final KernelToElementMapImpl elementMap;
 
diff --git a/pkg/compiler/lib/src/kernel/unresolved.dart b/pkg/compiler/lib/src/kernel/unresolved.dart
index ee0d95f..0af0395 100644
--- a/pkg/compiler/lib/src/kernel/unresolved.dart
+++ b/pkg/compiler/lib/src/kernel/unresolved.dart
@@ -11,12 +11,15 @@
         Element,
         ErroneousElement,
         FunctionElement,
-        MethodElement;
+        GetterElement,
+        MethodElement,
+        SetterElement;
 import "../elements/operators.dart"
     show AssignmentOperator, BinaryOperator, IncDecOperator, UnaryOperator;
 import "../elements/resolution_types.dart"
     show ResolutionDartType, ResolutionInterfaceType;
-import "../tree/tree.dart" show Expression, NewExpression, Node, NodeList, Send;
+import "../tree/tree.dart"
+    show Expression, NewExpression, Node, NodeList, Send, SendSet;
 import "../universe/call_structure.dart" show CallStructure;
 import "../universe/selector.dart" show Selector;
 import 'accessors.dart';
@@ -184,8 +187,8 @@
         receiver, methodName, buildArguments(arguments), constructor);
   }
 
-  ir.Expression visitUnresolvedCompound(
-      Send node, Element element, AssignmentOperator operator, Node rhs, _) {
+  ir.Expression visitUnresolvedCompound(Send node, ErroneousElement element,
+      AssignmentOperator operator, Node rhs, _) {
     return buildThrowUnresolvedGetter('${node.selector}');
   }
 
@@ -202,12 +205,12 @@
   }
 
   ir.Expression visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, _) {
+      Send node, ErroneousElement element, IncDecOperator operator, _) {
     return buildThrowUnresolvedGetter('${node.selector}');
   }
 
   ir.Expression visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, _) {
+      Send node, ErroneousElement element, IncDecOperator operator, _) {
     return buildThrowUnresolvedGetter('${node.selector}');
   }
 
@@ -223,7 +226,7 @@
         possiblyErroneousFunctionToIr(constructor), buildArguments(arguments));
   }
 
-  ir.Expression visitUnresolvedSet(Send node, Element element, Node rhs, _) {
+  ir.Expression visitUnresolvedSet(SendSet node, Element element, Node rhs, _) {
     return buildThrowUnresolvedSetter('${node.selector}', visitForValue(rhs));
   }
 
@@ -258,7 +261,7 @@
 
   ir.Expression visitUnresolvedStaticSetterCompound(
       Send node,
-      MethodElement getter,
+      GetterElement getter,
       Element element,
       AssignmentOperator operator,
       Node rhs,
@@ -268,7 +271,7 @@
   }
 
   ir.Expression visitUnresolvedStaticSetterPostfix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     var accessor = new ClassStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     var result = accessor.buildPostfixIncrement(
@@ -279,7 +282,7 @@
   }
 
   ir.Expression visitUnresolvedStaticSetterPrefix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     var accessor = new ClassStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     var result = accessor.buildPrefixIncrement(
@@ -290,7 +293,7 @@
   }
 
   ir.Expression visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, _) {
+      Send node, GetterElement getter, Element element, Node rhs, _) {
     var accessor = new ClassStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     return accessor.buildNullAwareAssignment(visitForValue(rhs), null,
@@ -312,8 +315,8 @@
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
-  ir.Expression visitUnresolvedSuperCompoundIndexSet(Send node, Element element,
-      Node index, AssignmentOperator operator, Node rhs, _) {
+  ir.Expression visitUnresolvedSuperCompoundIndexSet(SendSet node,
+      Element element, Node index, AssignmentOperator operator, Node rhs, _) {
     return buildUnresolvedSuperIndexAccessor(index, element)
         .buildCompoundAssignment(
             new ir.Name(operator.selectorName), visitForValue(rhs));
@@ -323,13 +326,18 @@
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
-  ir.Expression visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, _) {
+  ir.Expression visitUnresolvedSuperGetterCompound(
+      SendSet node,
+      Element element,
+      SetterElement setter,
+      AssignmentOperator operator,
+      Node rhs,
+      _) {
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
   ir.Expression visitUnresolvedSuperGetterCompoundIndexSet(
-      Send node,
+      SendSet node,
       Element element,
       MethodElement setter,
       Node index,
@@ -340,7 +348,7 @@
   }
 
   ir.Expression visitUnresolvedSuperGetterIndexPostfix(
-      Send node,
+      SendSet node,
       Element element,
       MethodElement setter,
       Node index,
@@ -350,7 +358,7 @@
   }
 
   ir.Expression visitUnresolvedSuperGetterIndexPrefix(
-      Send node,
+      SendSet node,
       Element element,
       MethodElement setter,
       Node index,
@@ -359,13 +367,13 @@
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
-  ir.Expression visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, _) {
+  ir.Expression visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, _) {
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
-  ir.Expression visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, _) {
+  ir.Expression visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, _) {
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
@@ -390,7 +398,7 @@
   }
 
   ir.Expression visitUnresolvedSuperIndexSet(
-      Send node, Element element, Node index, Node rhs, _) {
+      SendSet node, ErroneousElement element, Node index, Node rhs, _) {
     return buildUnresolvedSuperIndexAccessor(index, element)
         .buildAssignment(visitForValue(rhs));
   }
@@ -403,12 +411,12 @@
   }
 
   ir.Expression visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, _) {
+      SendSet node, Element element, IncDecOperator operator, _) {
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
   ir.Expression visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, _) {
+      SendSet node, Element element, IncDecOperator operator, _) {
     return buildThrowUnresolvedSuperGetter('${node.selector}');
   }
 
@@ -419,7 +427,7 @@
 
   ir.Expression visitUnresolvedSuperSetterCompound(
       Send node,
-      MethodElement getter,
+      GetterElement getter,
       Element element,
       AssignmentOperator operator,
       Node rhs,
@@ -430,7 +438,7 @@
   }
 
   ir.Expression visitUnresolvedSuperSetterCompoundIndexSet(
-      Send node,
+      SendSet node,
       MethodElement getter,
       Element element,
       Node index,
@@ -443,7 +451,7 @@
   }
 
   ir.Expression visitUnresolvedSuperSetterIndexPostfix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -454,7 +462,7 @@
   }
 
   ir.Expression visitUnresolvedSuperSetterIndexPrefix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -464,20 +472,20 @@
         .buildPrefixIncrement(new ir.Name(operator.selectorName));
   }
 
-  ir.Expression visitUnresolvedSuperSetterPostfix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+  ir.Expression visitUnresolvedSuperSetterPostfix(SendSet node,
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
         .buildPostfixIncrement(new ir.Name(operator.selectorName));
   }
 
-  ir.Expression visitUnresolvedSuperSetterPrefix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+  ir.Expression visitUnresolvedSuperSetterPrefix(SendSet node,
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
         .buildPrefixIncrement(new ir.Name(operator.selectorName));
   }
 
   ir.Expression visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, _) {
+      Send node, GetterElement getter, Element element, Node rhs, _) {
     return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
         .buildNullAwareAssignment(visitForValue(rhs), null);
   }
@@ -523,7 +531,7 @@
 
   ir.Expression visitUnresolvedTopLevelSetterCompound(
       Send node,
-      MethodElement getter,
+      GetterElement getter,
       Element element,
       AssignmentOperator operator,
       Node rhs,
@@ -538,7 +546,7 @@
   }
 
   ir.Expression visitUnresolvedTopLevelSetterPostfix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     var accessor = new TopLevelStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     var result = accessor.buildPostfixIncrement(
@@ -549,7 +557,7 @@
   }
 
   ir.Expression visitUnresolvedTopLevelSetterPrefix(Send node,
-      MethodElement getter, Element element, IncDecOperator operator, _) {
+      GetterElement getter, Element element, IncDecOperator operator, _) {
     var accessor = new TopLevelStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     var result = accessor.buildPrefixIncrement(
@@ -560,20 +568,20 @@
   }
 
   ir.Expression visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, _) {
+      Send node, GetterElement getter, Element element, Node rhs, _) {
     var accessor = new TopLevelStaticAccessor(
         this, getter.name, possiblyErroneousFunctionToIr(getter), null);
     return accessor.buildNullAwareAssignment(visitForValue(rhs), null,
         voidContext: isVoidContext);
   }
 
-  ir.Expression visitUnresolvedSuperGetterIndexSetIfNull(Send node,
+  ir.Expression visitUnresolvedSuperGetterIndexSetIfNull(SendSet node,
       Element element, MethodElement setter, Node index, Node rhs, _) {
     return buildUnresolvedSuperIndexAccessor(index, element)
         .buildNullAwareAssignment(visitForValue(rhs), null);
   }
 
-  ir.Expression visitUnresolvedSuperSetterIndexSetIfNull(Send node,
+  ir.Expression visitUnresolvedSuperSetterIndexSetIfNull(SendSet node,
       MethodElement getter, Element element, Node index, Node rhs, _) {
     return buildUnresolvedSuperIndexAccessor(index, element)
         .buildNullAwareAssignment(visitForValue(rhs), null);
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 785f4cb..3c950cc 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -523,14 +523,14 @@
       return new NativeBehavior();
     }
 
-    var specArgument = argNodes.head;
+    dynamic specArgument = argNodes.head;
     if (specArgument is! StringNode || specArgument.isInterpolation) {
       reporter.reportErrorMessage(
           specArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
       return new NativeBehavior();
     }
 
-    var codeArgument = argNodes.tail.head;
+    dynamic codeArgument = argNodes.tail.head;
     if (codeArgument is! StringNode || codeArgument.isInterpolation) {
       reporter.reportErrorMessage(
           codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index 5f94465..ff4bc4b 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -80,14 +80,14 @@
   NativeBasicData get nativeBasicData;
   NativeDataBuilder get nativeDataBuilder;
 
-  bool isJsInteropMember(MemberEntity element);
-  bool isNativeMethod(FunctionEntity element);
+  bool isJsInteropMember(covariant MemberEntity element);
+  bool isNativeMethod(covariant FunctionEntity element);
 
-  NativeBehavior computeNativeMethodBehavior(FunctionEntity function,
+  NativeBehavior computeNativeMethodBehavior(covariant FunctionEntity function,
       {bool isJsInterop});
-  NativeBehavior computeNativeFieldLoadBehavior(FieldEntity field,
+  NativeBehavior computeNativeFieldLoadBehavior(covariant FieldEntity field,
       {bool isJsInterop});
-  NativeBehavior computeNativeFieldStoreBehavior(FieldEntity field);
+  NativeBehavior computeNativeFieldStoreBehavior(covariant FieldEntity field);
 
   @override
   void resolveNativeMember(MemberEntity element, [NativeRegistry registry]) {
@@ -128,7 +128,7 @@
 
   /// Process the potentially native [field]. Adds information from metadata
   /// attributes. Returns `true` of [method] is native.
-  bool _processFieldAnnotations(FieldEntity element) {
+  bool _processFieldAnnotations(covariant FieldEntity element) {
     if (element.isInstanceMember &&
         nativeBasicData.isNativeClass(element.enclosingClass)) {
       // Exclude non-instance (static) fields - they are not really native and
@@ -143,7 +143,7 @@
 
   /// Process the potentially native [method]. Adds information from metadata
   /// attributes. Returns `true` of [method] is native.
-  bool _processMethodAnnotations(FunctionEntity method) {
+  bool _processMethodAnnotations(covariant FunctionEntity method) {
     if (isNativeMethod(method)) {
       if (method.isStatic) {
         _setNativeNameForStaticMethod(method);
@@ -435,7 +435,8 @@
 
   /// Adds [cls] to [nativeClasses] and performs further processing of [cls],
   /// if necessary.
-  void _processNativeClass(ClassEntity cls, Set<ClassEntity> nativeClasses) {
+  void _processNativeClass(
+      covariant ClassEntity cls, Set<ClassEntity> nativeClasses) {
     nativeClasses.add(cls);
     // Js Interop interfaces do not have tags.
     if (_nativeBasicData.isJsInteropClass(cls)) return;
@@ -456,7 +457,7 @@
 
   /// Returns the name of the super class of [cls] or `null` of [cls] has
   /// no explicit superclass.
-  String _findExtendsNameOfClass(ClassEntity cls) {
+  String _findExtendsNameOfClass(covariant ClassEntity cls) {
     return _elementEnvironment
         .getSuperClass(cls, skipUnnamedMixinApplications: true)
         ?.name;
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 200b98b..ad45484 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -8,14 +8,14 @@
 import '../elements/elements.dart';
 import '../js/js.dart' as js;
 import '../js_emitter/js_emitter.dart' show NativeEmitter;
-import '../ssa/builder.dart' show SsaBuilder;
+import '../ssa/builder.dart' show SsaAstGraphBuilder;
 import '../ssa/nodes.dart' show HInstruction, HForeignCode, HReturn;
 import '../tree/tree.dart';
 import '../universe/side_effects.dart' show SideEffects;
 
 final RegExp nativeRedirectionRegExp = new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');
 
-void handleSsaNative(SsaBuilder builder, Expression nativeBody) {
+void handleSsaNative(SsaAstGraphBuilder builder, Expression nativeBody) {
   MethodElement element = builder.target;
   NativeEmitter nativeEmitter = builder.nativeEmitter;
 
@@ -67,7 +67,8 @@
       receiver = '#.';
       inputs.add(builder.localsHandler.readThis());
     }
-    parameters.forEachParameter((ParameterElement parameter) {
+    parameters.forEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       ResolutionDartType type = parameter.type.unaliased;
       HInstruction input = builder.localsHandler.readLocal(parameter);
       if (type is ResolutionFunctionType) {
diff --git a/pkg/compiler/lib/src/ordered_typeset.dart b/pkg/compiler/lib/src/ordered_typeset.dart
index bbc71c9..b01dbf3 100644
--- a/pkg/compiler/lib/src/ordered_typeset.dart
+++ b/pkg/compiler/lib/src/ordered_typeset.dart
@@ -171,10 +171,11 @@
   OrderedTypeSetBuilderBase(this.cls, {this.reporter, InterfaceType objectType})
       : this._objectType = objectType;
 
-  InterfaceType getThisType(ClassEntity cls);
-  InterfaceType substByContext(InterfaceType type, InterfaceType context);
-  int getHierarchyDepth(ClassEntity cls);
-  OrderedTypeSet getOrderedTypeSet(ClassEntity cls);
+  InterfaceType getThisType(covariant ClassEntity cls);
+  InterfaceType substByContext(
+      covariant InterfaceType type, covariant InterfaceType context);
+  int getHierarchyDepth(covariant ClassEntity cls);
+  OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
 
   OrderedTypeSet createOrderedTypeSet(
       InterfaceType supertype, Link<DartType> interfaces) {
diff --git a/pkg/compiler/lib/src/parser/partial_elements.dart b/pkg/compiler/lib/src/parser/partial_elements.dart
index 899f686..f0cc995 100644
--- a/pkg/compiler/lib/src/parser/partial_elements.dart
+++ b/pkg/compiler/lib/src/parser/partial_elements.dart
@@ -139,6 +139,7 @@
   PartialFunctionElement copyWithEnclosing(Element enclosing);
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class PartialMethodElement extends MethodElementX
     with PartialElement, PartialFunctionMixin
     implements PartialFunctionElement {
@@ -161,6 +162,7 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class PartialGetterElement extends GetterElementX
     with PartialElement, PartialFunctionMixin
     implements GetterElement, PartialFunctionElement {
@@ -186,6 +188,7 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class PartialSetterElement extends SetterElementX
     with PartialElement, PartialFunctionMixin
     implements SetterElement, PartialFunctionElement {
diff --git a/pkg/compiler/lib/src/platform_configuration.dart b/pkg/compiler/lib/src/platform_configuration.dart
index 471f7ca..0f61ca4 100644
--- a/pkg/compiler/lib/src/platform_configuration.dart
+++ b/pkg/compiler/lib/src/platform_configuration.dart
@@ -135,7 +135,7 @@
 Future<Map<String, Uri>> load(Uri location, api.CompilerInput provider) {
   return provider
       .readFromUri(location, inputKind: api.InputKind.binary)
-      .then((api.Input<List<int>> input) {
+      .then((api.Input input) {
     return libraryMappings(
         parseIni(input.data,
             allowedSections: allowedSections, sourceUri: location),
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index 9381d28..c3063f3 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -105,7 +105,8 @@
     ClassElement superclass = supertype.element;
 
     // Inherit class and interface members from superclass.
-    void inheritClassMember(DeclaredMember member) {
+    void inheritClassMember(Member _member) {
+      DeclaredMember member = _member;
       if (shouldSkipMember(member)) return;
       if (!member.isStatic) {
         DeclaredMember inherited = member.inheritFrom(supertype);
@@ -136,7 +137,8 @@
       if (mixinApplication.mixin != null) {
         // Only mix in class members when the mixin type is not malformed.
 
-        void inheritMixinMember(DeclaredMember member) {
+        void inheritMixinMember(Member _member) {
+          DeclaredMember member = _member;
           if (shouldSkipMember(member)) return;
           Name name = member.name;
           if (!member.isAbstract && !member.isStatic) {
@@ -165,7 +167,8 @@
       LibraryElement library = cls.library;
       ResolutionInterfaceType thisType = cls.thisType;
 
-      void createMember(MemberElement element) {
+      void createMember(Element _element) {
+        MemberElement element = _element;
         if (element.isConstructor) return;
         String elementName = element.name;
         if (shouldSkipName(elementName)) return;
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 64b65d1..99e4431 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -313,7 +313,8 @@
     Link<Node> parameterNodes = (functionNode.parameters == null)
         ? const Link<Node>()
         : functionNode.parameters.nodes;
-    functionParameters.forEachParameter((ParameterElementX element) {
+    functionParameters.forEachParameter((FormalElement _element) {
+      ParameterElementX element = _element;
       List<Element> optionals = functionParameters.optionalParameters;
       if (!optionals.isEmpty && element == optionals.first) {
         NodeList nodes = parameterNodes.head;
@@ -414,7 +415,7 @@
           }
           // Check that there are no field initializing parameters.
           FunctionSignature signature = constructor.functionSignature;
-          signature.forEachParameter((ParameterElement parameter) {
+          signature.forEachParameter((FormalElement parameter) {
             if (parameter.isInitializingFormal) {
               Node node = parameter.node;
               reporter.reportErrorMessage(
diff --git a/pkg/compiler/lib/src/resolution/enum_creator.dart b/pkg/compiler/lib/src/resolution/enum_creator.dart
index aab9140..72781d4 100644
--- a/pkg/compiler/lib/src/resolution/enum_creator.dart
+++ b/pkg/compiler/lib/src/resolution/enum_creator.dart
@@ -257,7 +257,7 @@
 
     EnumFormalElementX nameFormal;
 
-    List<Element> parameters = <Element>[indexFormal];
+    List<FormalElement> parameters = <FormalElement>[indexFormal];
     List<ResolutionDartType> parameterTypes = <ResolutionDartType>[intType];
     if (!matchKernelRepresentationForTesting) {
       nameFormal = new EnumFormalElementX(constructor, nameDefinition,
diff --git a/pkg/compiler/lib/src/resolution/member_impl.dart b/pkg/compiler/lib/src/resolution/member_impl.dart
index d8c3c4e..ac37087 100644
--- a/pkg/compiler/lib/src/resolution/member_impl.dart
+++ b/pkg/compiler/lib/src/resolution/member_impl.dart
@@ -6,7 +6,7 @@
 
 class DeclaredMember implements Member {
   final Name name;
-  final Element element;
+  final MemberElement element;
   final ResolutionInterfaceType declarer;
   final ResolutionDartType type;
   final ResolutionFunctionType functionType;
@@ -116,7 +116,7 @@
     assert(!declaration.isStatic);
   }
 
-  Element get element => declaration.element;
+  MemberElement get element => declaration.element;
 
   Name get name => declaration.name;
 
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 600aed4..d85656a 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -426,7 +426,8 @@
     scope = new BlockScope(scope);
     Link<Node> parameterNodes =
         (node.parameters == null) ? const Link<Node>() : node.parameters.nodes;
-    functionSignature.forEachParameter((ParameterElementX element) {
+    functionSignature.forEachParameter((_element) {
+      ParameterElementX element = _element;
       // TODO(karlklose): should be a list of [FormalElement]s, but the actual
       // implementation uses [Element].
       List<Element> optionals = functionSignature.optionalParameters;
@@ -458,13 +459,15 @@
       parameterNodes = parameterNodes.tail;
     });
     addDeferredAction(enclosingElement, () {
-      functionSignature.forEachOptionalParameter((ParameterElementX parameter) {
+      functionSignature.forEachOptionalParameter((_parameter) {
+        ParameterElementX parameter = _parameter;
         parameter.constant =
             resolver.constantCompiler.compileConstant(parameter);
       });
     });
     registry.registerCheckedModeCheck(functionSignature.returnType);
-    functionSignature.forEachParameter((ParameterElement element) {
+    functionSignature.forEachParameter((_element) {
+      ParameterElement element = _element;
       registry.registerCheckedModeCheck(element.type);
     });
   }
@@ -3730,7 +3733,8 @@
       List<String> names = <String>[];
       List<ConstantExpression> arguments = <ConstantExpression>[];
       int index = 0;
-      constructorSignature.forEachParameter((ParameterElement parameter) {
+      constructorSignature.forEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         if (parameter.isNamed) {
           String name = parameter.name;
           names.add(name);
diff --git a/pkg/compiler/lib/src/resolution/no_such_method_resolver.dart b/pkg/compiler/lib/src/resolution/no_such_method_resolver.dart
index 49f3353..5e4955f 100644
--- a/pkg/compiler/lib/src/resolution/no_such_method_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/no_such_method_resolver.dart
@@ -51,9 +51,11 @@
           arg is Send &&
           arg.argumentsNode == null &&
           arg.receiver == null &&
-          arg.selector is Identifier &&
-          arg.selector.source == param) {
-        return true;
+          arg.selector is Identifier) {
+        Identifier selector = arg.selector;
+        if (selector.source == param) {
+          return true;
+        }
       }
     }
     return false;
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index bcae57b..3267764 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -774,7 +774,8 @@
 
     // Check that the mixed in class doesn't have any constructors and
     // make sure we aren't mixing in methods that use 'super'.
-    mixin.forEachLocalMember((AstElement member) {
+    mixin.forEachLocalMember((_member) {
+      AstElement member = _member;
       if (member.isGenerativeConstructor && !member.isSynthesized) {
         reporter.reportErrorMessage(
             member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR);
diff --git a/pkg/compiler/lib/src/resolution/resolution_common.dart b/pkg/compiler/lib/src/resolution/resolution_common.dart
index ffca163..4428cd3 100644
--- a/pkg/compiler/lib/src/resolution/resolution_common.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_common.dart
@@ -26,7 +26,7 @@
         node, 'internal error: Unhandled node: ${node.getObjectDescription()}');
   }
 
-  R visitEmptyStatement(Node node) => null;
+  R visitEmptyStatement(EmptyStatement node) => null;
 
   /** Convenience method for visiting nodes that may be null. */
   R visit(Node node) => (node == null) ? null : node.accept(this);
diff --git a/pkg/compiler/lib/src/resolution/resolution_strategy.dart b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
index aac70a2..2b47335 100644
--- a/pkg/compiler/lib/src/resolution/resolution_strategy.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
@@ -47,7 +47,7 @@
 /// model using the resolver.
 class ResolutionFrontEndStrategy implements FrontendStrategy {
   final Compiler _compiler;
-  final ElementEnvironment elementEnvironment;
+  final _CompilerElementEnvironment _elementEnvironment;
   final CommonElements commonElements;
 
   AnnotationProcessor _annotationProcessor;
@@ -61,7 +61,9 @@
   }
 
   ResolutionFrontEndStrategy.internal(
-      this._compiler, this.elementEnvironment, this.commonElements);
+      this._compiler, this._elementEnvironment, this.commonElements);
+
+  ElementEnvironment get elementEnvironment => _elementEnvironment;
 
   DartTypes get dartTypes => _compiler.types;
 
@@ -140,7 +142,8 @@
   }
 
   FunctionEntity computeMain(
-      LibraryElement mainApp, WorldImpactBuilder impactBuilder) {
+      covariant LibraryElement mainApp, WorldImpactBuilder impactBuilder) {
+    _elementEnvironment._mainLibrary = mainApp;
     if (mainApp == null) return null;
     MethodElement mainFunction;
     Element main = mainApp.findExported(Identifiers.main);
@@ -211,6 +214,7 @@
       mainFunction.computeType(_compiler.resolution);
       mainMethod = mainFunction;
     }
+    _elementEnvironment._mainFunction = mainMethod;
     return mainMethod;
   }
 
@@ -370,6 +374,9 @@
 class _CompilerElementEnvironment implements ElementEnvironment {
   final Compiler _compiler;
 
+  LibraryEntity _mainLibrary;
+  FunctionEntity _mainFunction;
+
   _CompilerElementEnvironment(this._compiler);
 
   LibraryProvider get _libraryProvider => _compiler.libraryLoader;
@@ -378,25 +385,26 @@
   ResolutionDynamicType get dynamicType => const ResolutionDynamicType();
 
   @override
-  LibraryEntity get mainLibrary => _compiler.mainApp;
+  LibraryEntity get mainLibrary => _mainLibrary;
 
   @override
-  FunctionEntity get mainFunction => _compiler.mainFunction;
+  FunctionEntity get mainFunction => _mainFunction;
 
   @override
   Iterable<LibraryEntity> get libraries => _compiler.libraryLoader.libraries;
 
   @override
-  String getLibraryName(LibraryElement library) => library.libraryName;
+  String getLibraryName(covariant LibraryElement library) =>
+      library.libraryName;
 
   @override
-  ResolutionInterfaceType getThisType(ClassElement cls) {
+  ResolutionInterfaceType getThisType(covariant ClassElement cls) {
     cls.ensureResolved(_resolution);
     return cls.thisType;
   }
 
   @override
-  ResolutionInterfaceType getRawType(ClassElement cls) {
+  ResolutionInterfaceType getRawType(covariant ClassElement cls) {
     cls.ensureResolved(_resolution);
     return cls.rawType;
   }
@@ -407,17 +415,17 @@
   }
 
   @override
-  bool isMixinApplication(ClassElement cls) {
+  bool isMixinApplication(covariant ClassElement cls) {
     return cls.isMixinApplication;
   }
 
   @override
-  bool isUnnamedMixinApplication(ClassElement cls) {
+  bool isUnnamedMixinApplication(covariant ClassElement cls) {
     return cls.isUnnamedMixinApplication;
   }
 
   @override
-  ClassEntity getEffectiveMixinClass(ClassElement cls) {
+  ClassEntity getEffectiveMixinClass(covariant ClassElement cls) {
     if (!cls.isMixinApplication) return null;
     do {
       MixinApplicationElement mixinApplication = cls;
@@ -427,19 +435,20 @@
   }
 
   @override
-  ResolutionDartType getTypeVariableBound(TypeVariableElement typeVariable) {
+  ResolutionDartType getTypeVariableBound(
+      covariant TypeVariableElement typeVariable) {
     return typeVariable.bound;
   }
 
   @override
-  ResolutionInterfaceType createInterfaceType(
-      ClassElement cls, List<ResolutionDartType> typeArguments) {
+  ResolutionInterfaceType createInterfaceType(covariant ClassElement cls,
+      covariant List<ResolutionDartType> typeArguments) {
     cls.ensureResolved(_resolution);
     return cls.thisType.createInstantiation(typeArguments);
   }
 
   @override
-  MemberElement lookupClassMember(ClassElement cls, String name,
+  MemberElement lookupClassMember(covariant ClassElement cls, String name,
       {bool setter: false, bool required: false}) {
     cls.ensureResolved(_resolution);
     Element member = cls.implementation.lookupLocalMember(name);
@@ -467,7 +476,7 @@
   }
 
   @override
-  ConstructorElement lookupConstructor(ClassElement cls, String name,
+  ConstructorElement lookupConstructor(covariant ClassElement cls, String name,
       {bool required: false}) {
     cls.ensureResolved(_resolution);
     ConstructorElement constructor = cls.implementation.lookupConstructor(name);
@@ -482,10 +491,11 @@
   }
 
   @override
-  void forEachClassMember(
-      ClassElement cls, void f(ClassElement declarer, MemberElement member)) {
+  void forEachClassMember(covariant ClassElement cls,
+      void f(ClassElement declarer, MemberElement member)) {
     cls.ensureResolved(_resolution);
-    cls.forEachMember((ClassElement declarer, MemberElement member) {
+    cls.forEachMember((ClassElement declarer, _member) {
+      MemberElement member = _member;
       if (member.isSynthesized) return;
       if (member.isMalformed) return;
       if (member.isConstructor) return;
@@ -495,7 +505,7 @@
 
   @override
   void forEachConstructor(
-      ClassElement cls, void f(ConstructorEntity constructor)) {
+      covariant ClassElement cls, void f(ConstructorEntity constructor)) {
     cls.ensureResolved(_resolution);
     for (ConstructorElement constructor in cls.implementation.constructors) {
       _resolution.ensureResolved(constructor.declaration);
@@ -505,7 +515,7 @@
   }
 
   @override
-  ClassEntity getSuperClass(ClassElement cls,
+  ClassEntity getSuperClass(covariant ClassElement cls,
       {bool skipUnnamedMixinApplications: false}) {
     cls.ensureResolved(_resolution);
     ClassElement superclass = cls.superclass;
@@ -519,13 +529,12 @@
 
   @override
   void forEachSupertype(
-      ClassElement cls, void f(ResolutionInterfaceType supertype)) {
-    cls.allSupertypes
-        .forEach((ResolutionInterfaceType supertype) => f(supertype));
+      covariant ClassElement cls, void f(ResolutionInterfaceType supertype)) {
+    cls.allSupertypes.forEach((InterfaceType supertype) => f(supertype));
   }
 
   @override
-  void forEachMixin(ClassElement cls, void f(ClassElement mixin)) {
+  void forEachMixin(covariant ClassElement cls, void f(ClassElement mixin)) {
     for (; cls != null; cls = cls.superclass) {
       if (cls.isMixinApplication) {
         MixinApplicationElement mixinApplication = cls;
@@ -535,7 +544,8 @@
   }
 
   @override
-  MemberElement lookupLibraryMember(LibraryElement library, String name,
+  MemberElement lookupLibraryMember(
+      covariant LibraryElement library, String name,
       {bool setter: false, bool required: false}) {
     Element member = library.implementation.findLocal(name);
     if (member != null && member.isAbstractField) {
@@ -563,7 +573,7 @@
 
   @override
   void forEachLibraryMember(
-      LibraryElement library, void f(MemberEntity member)) {
+      covariant LibraryElement library, void f(MemberEntity member)) {
     library.implementation.forEachLocalMember((Element element) {
       if (!element.isClass && !element.isTypedef) {
         MemberElement member = element;
@@ -573,7 +583,7 @@
   }
 
   @override
-  ClassElement lookupClass(LibraryElement library, String name,
+  ClassElement lookupClass(covariant LibraryElement library, String name,
       {bool required: false}) {
     ClassElement cls = library.implementation.findLocal(name);
     if (cls == null && required) {
@@ -586,10 +596,11 @@
   }
 
   @override
-  void forEachClass(LibraryElement library, void f(ClassElement cls)) {
-    library.implementation.forEachLocalMember((member) {
+  void forEachClass(covariant LibraryElement library, void f(ClassEntity cls)) {
+    library.implementation.forEachLocalMember((dynamic member) {
       if (member.isClass) {
-        f(member);
+        ClassElement cls = member;
+        f(cls);
       }
     });
   }
@@ -613,12 +624,12 @@
   }
 
   @override
-  bool isDeferredLoadLibraryGetter(MemberElement member) {
+  bool isDeferredLoadLibraryGetter(covariant MemberElement member) {
     return member.isDeferredLoaderGetter;
   }
 
   @override
-  ResolutionFunctionType getFunctionType(MethodElement method) {
+  ResolutionFunctionType getFunctionType(covariant MethodElement method) {
     if (method is ConstructorBodyElement) {
       return method.constructor.type;
     }
@@ -627,18 +638,19 @@
   }
 
   @override
-  ResolutionFunctionType getLocalFunctionType(LocalFunctionElement function) {
+  ResolutionFunctionType getLocalFunctionType(
+      covariant LocalFunctionElement function) {
     return function.type;
   }
 
   @override
-  ResolutionDartType getUnaliasedType(ResolutionDartType type) {
+  ResolutionDartType getUnaliasedType(covariant ResolutionDartType type) {
     type.computeUnaliased(_resolution);
     return type.unaliased;
   }
 
   @override
-  Iterable<ConstantValue> getMemberMetadata(MemberElement element) {
+  Iterable<ConstantValue> getMemberMetadata(covariant MemberElement element) {
     List<ConstantValue> values = <ConstantValue>[];
     _compiler.reporter.withCurrentElement(element, () {
       for (MetadataAnnotation metadata in element.implementation.metadata) {
@@ -669,8 +681,8 @@
 
   /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
   /// native name from the annotation.
-  void extractNativeAnnotations(
-      LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) {
+  void extractNativeAnnotations(covariant LibraryElement library,
+      NativeBasicDataBuilder nativeBasicDataBuilder) {
     library.forEachLocalMember((Element element) {
       if (element.isClass) {
         EagerAnnotationHandler.checkAnnotation(_compiler, element,
@@ -679,8 +691,8 @@
     });
   }
 
-  void extractJsInteropAnnotations(
-      LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) {
+  void extractJsInteropAnnotations(covariant LibraryElement library,
+      NativeBasicDataBuilder nativeBasicDataBuilder) {
     bool checkJsInteropAnnotation(Element element) {
       return EagerAnnotationHandler.checkAnnotation(
           _compiler, element, const JsInteropAnnotationHandler());
@@ -801,8 +813,8 @@
           });
         }
 
-        classElement
-            .forEachMember((ClassElement classElement, MemberElement member) {
+        classElement.forEachMember((ClassElement classElement, _member) {
+          MemberElement member = _member;
           String memberName = processJsInteropAnnotation(member);
           if (memberName != null) {
             nativeDataBuilder.setJsInteropMemberName(member, memberName);
@@ -823,8 +835,8 @@
             }
 
             if (fn.isFactoryConstructor && isAnonymous) {
-              fn.functionSignature
-                  .orderedForEachParameter((ParameterElement parameter) {
+              fn.functionSignature.orderedForEachParameter((_parameter) {
+                ParameterElement parameter = _parameter;
                 if (!parameter.isNamed) {
                   _compiler.reporter.reportErrorMessage(
                       parameter,
@@ -842,7 +854,7 @@
     }
 
     _compiler.libraryLoader.libraries
-        .forEach(processJsInteropAnnotationsInLibrary);
+        .forEach((LibraryEntity l) => processJsInteropAnnotationsInLibrary(l));
   }
 }
 
diff --git a/pkg/compiler/lib/src/resolution/scope.dart b/pkg/compiler/lib/src/resolution/scope.dart
index 380b764..a047968 100644
--- a/pkg/compiler/lib/src/resolution/scope.dart
+++ b/pkg/compiler/lib/src/resolution/scope.dart
@@ -110,8 +110,8 @@
   final Map<String, Element> elements;
 
   MutableScope(Scope parent)
-      : super(parent),
-        this.elements = new Map<String, Element>() {
+      : this.elements = new Map<String, Element>(),
+        super(parent) {
     assert(parent != null);
   }
 
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 3c837fe..f917349 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -521,7 +521,7 @@
   ///        m() { super.foo = rhs; }
   ///     }
   ///
-  R visitSuperMethodSet(Send node, MethodElement method, Node rhs, A arg);
+  R visitSuperMethodSet(SendSet node, MethodElement method, Node rhs, A arg);
 
   /// Getter call to the super [getter].
   ///
@@ -534,7 +534,7 @@
   ///        m() => super.foo;
   ///     }
   ///
-  R visitSuperGetterGet(Send node, FunctionElement getter, A arg);
+  R visitSuperGetterGet(Send node, GetterElement getter, A arg);
 
   /// Getter call the super [setter].
   ///
@@ -547,7 +547,7 @@
   ///        m() => super.foo;
   ///     }
   ///
-  R visitSuperSetterGet(Send node, FunctionElement setter, A arg);
+  R visitSuperSetterGet(Send node, SetterElement setter, A arg);
 
   /// Setter call to the super [setter].
   ///
@@ -560,7 +560,7 @@
   ///        m() { super.foo = rhs; }
   ///     }
   ///
-  R visitSuperSetterSet(SendSet node, FunctionElement setter, Node rhs, A arg);
+  R visitSuperSetterSet(SendSet node, SetterElement setter, Node rhs, A arg);
 
   /// Assignment of [rhs] to the super [getter].
   ///
@@ -573,7 +573,7 @@
   ///        m() { super.foo = rhs; }
   ///     }
   ///
-  R visitSuperGetterSet(SendSet node, FunctionElement getter, Node rhs, A arg);
+  R visitSuperGetterSet(SendSet node, GetterElement getter, Node rhs, A arg);
 
   /// Invocation of the super [getter] with [arguments].
   ///
@@ -586,8 +586,8 @@
   ///        m() { super.foo(null, 42; }
   ///     }
   ///
-  R visitSuperGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg);
+  R visitSuperGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg);
 
   /// Invocation of the super [setter] with [arguments].
   ///
@@ -600,8 +600,8 @@
   ///        m() { super.foo(null, 42; }
   ///     }
   ///
-  R visitSuperSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg);
+  R visitSuperSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg);
 
   /// Invocation of a [expression] with [arguments].
   ///
@@ -701,7 +701,8 @@
   ///     }
   ///     m() { C.foo = rhs; }
   ///
-  R visitStaticFunctionSet(Send node, MethodElement function, Node rhs, A arg);
+  R visitStaticFunctionSet(
+      SendSet node, MethodElement function, Node rhs, A arg);
 
   /// Getter call to the static [getter].
   ///
@@ -712,7 +713,7 @@
   ///     }
   ///     m() => C.foo;
   ///
-  R visitStaticGetterGet(Send node, FunctionElement getter, A arg);
+  R visitStaticGetterGet(Send node, GetterElement getter, A arg);
 
   /// Getter call the static [setter].
   ///
@@ -723,7 +724,7 @@
   ///     }
   ///     m() => C.foo;
   ///
-  R visitStaticSetterGet(Send node, FunctionElement setter, A arg);
+  R visitStaticSetterGet(Send node, SetterElement setter, A arg);
 
   /// Setter call to the static [setter].
   ///
@@ -734,7 +735,7 @@
   ///     }
   ///     m() { C.foo = rhs; }
   ///
-  R visitStaticSetterSet(SendSet node, FunctionElement setter, Node rhs, A arg);
+  R visitStaticSetterSet(SendSet node, SetterElement setter, Node rhs, A arg);
 
   /// Assignment of [rhs] to the static [getter].
   ///
@@ -745,7 +746,7 @@
   ///     }
   ///     m() { C.foo = rhs; }
   ///
-  R visitStaticGetterSet(SendSet node, FunctionElement getter, Node rhs, A arg);
+  R visitStaticGetterSet(SendSet node, GetterElement getter, Node rhs, A arg);
 
   /// Invocation of the static [getter] with [arguments].
   ///
@@ -756,8 +757,8 @@
   ///     }
   ///     m() { C.foo(null, 42; }
   ///
-  R visitStaticGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg);
+  R visitStaticGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg);
 
   /// Invocation of the static [setter] with [arguments].
   ///
@@ -768,8 +769,8 @@
   ///     }
   ///     m() { C.foo(null, 42; }
   ///
-  R visitStaticSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg);
+  R visitStaticSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg);
 
   /// Read of the top level [field].
   ///
@@ -848,7 +849,7 @@
   ///     m() { foo = rhs; }
   ///
   R visitTopLevelFunctionSet(
-      Send node, MethodElement function, Node rhs, A arg);
+      SendSet node, MethodElement function, Node rhs, A arg);
 
   /// Getter call to the top level [getter].
   ///
@@ -857,7 +858,7 @@
   ///     get foo => null;
   ///     m() => foo;
   ///
-  R visitTopLevelGetterGet(Send node, FunctionElement getter, A arg);
+  R visitTopLevelGetterGet(Send node, GetterElement getter, A arg);
 
   /// Getter call the top level [setter].
   ///
@@ -866,7 +867,7 @@
   ///     set foo(_) {}
   ///     m() => foo;
   ///
-  R visitTopLevelSetterGet(Send node, FunctionElement setter, A arg);
+  R visitTopLevelSetterGet(Send node, SetterElement setter, A arg);
 
   /// Setter call to the top level [setter].
   ///
@@ -875,8 +876,7 @@
   ///     set foo(_) {}
   ///     m() { foo = rhs; }
   ///
-  R visitTopLevelSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg);
+  R visitTopLevelSetterSet(SendSet node, SetterElement setter, Node rhs, A arg);
 
   /// Assignment of [rhs] to the top level [getter].
   ///
@@ -885,8 +885,7 @@
   ///     get foo => null;
   ///     m() { foo = rhs; }
   ///
-  R visitTopLevelGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg);
+  R visitTopLevelGetterSet(SendSet node, GetterElement getter, Node rhs, A arg);
 
   /// Invocation of the top level [getter] with [arguments].
   ///
@@ -895,7 +894,7 @@
   ///     get foo => null;
   ///     m() { foo(null, 42); }
   ///
-  R visitTopLevelGetterInvoke(Send node, FunctionElement getter,
+  R visitTopLevelGetterInvoke(Send node, GetterElement getter,
       NodeList arguments, CallStructure callStructure, A arg);
 
   /// Invocation of the top level [setter] with [arguments].
@@ -905,7 +904,7 @@
   ///     set foo(_) {};
   ///     m() { foo(null, 42); }
   ///
-  R visitTopLevelSetterInvoke(Send node, FunctionElement setter,
+  R visitTopLevelSetterInvoke(Send node, SetterElement setter,
       NodeList arguments, CallStructure callStructure, A arg);
 
   /// Read of the type literal for class [element].
@@ -935,7 +934,7 @@
   ///     m() { C = rhs; }
   ///
   R visitClassTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg);
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg);
 
   /// Read of the type literal for typedef [element].
   ///
@@ -964,7 +963,7 @@
   ///     m() { F = rhs; }
   ///
   R visitTypedefTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg);
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg);
 
   /// Read of the type literal for type variable [element].
   ///
@@ -1024,7 +1023,7 @@
   ///     m() { dynamic = rhs; }
   ///
   R visitDynamicTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg);
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg);
 
   /// Binary expression `left operator right` where [operator] is a user
   /// definable operator. Binary expressions using operator `==` are handled
@@ -1052,8 +1051,8 @@
   ///       m(a) => super + a;
   ///     }
   ///
-  R visitSuperBinary(Send node, FunctionElement function,
-      BinaryOperator operator, Node argument, A arg);
+  R visitSuperBinary(Send node, MethodElement function, BinaryOperator operator,
+      Node argument, A arg);
 
   /// Binary operation on the unresolved super [element].
   ///
@@ -1108,7 +1107,7 @@
   ///       m(a) => super[a];
   ///     }
   ///
-  R visitSuperIndex(Send node, FunctionElement function, Node index, A arg);
+  R visitSuperIndex(Send node, MethodElement function, Node index, A arg);
 
   /// Index expression `super[index]` where 'operator []' is unresolved.
   ///
@@ -1180,7 +1179,7 @@
   ///       m(a) => --super[a];
   ///     }
   ///
-  R visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPrefix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg);
 
   /// Postfix operation on an index expression `super[index] operator` where
@@ -1196,7 +1195,7 @@
   ///       m(a) => super[a]++;
   ///     }
   ///
-  R visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPostfix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg);
 
   /// Prefix operation on an index expression `operator super[index]` where
@@ -1213,7 +1212,7 @@
   ///     }
   ///
   R visitUnresolvedSuperSetterIndexPrefix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -1234,7 +1233,7 @@
   ///     }
   ///
   R visitUnresolvedSuperSetterIndexPostfix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -1294,7 +1293,7 @@
   ///     }
   ///
   R visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, A arg);
+      Send node, MethodElement function, Node argument, A arg);
 
   /// Binary expression `left == right`.
   ///
@@ -1316,7 +1315,7 @@
   ///       m(a) => super == a;
   ///     }
   ///
-  R visitSuperEquals(Send node, FunctionElement function, Node argument, A arg);
+  R visitSuperEquals(Send node, MethodElement function, Node argument, A arg);
 
   /// Unary expression `operator expression` where [operator] is a user
   /// definable operator.
@@ -1341,7 +1340,7 @@
   ///     }
   ///
   R visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, A arg);
+      Send node, UnaryOperator operator, MethodElement function, A arg);
 
   /// Unary operation on the unresolved super [element].
   ///
@@ -1399,7 +1398,7 @@
   ///     }
   ///
   R visitUnresolvedSuperIndexSet(
-      Send node, Element element, Node index, Node rhs, A arg);
+      SendSet node, ErroneousElement element, Node index, Node rhs, A arg);
 
   /// If-null, ??, expression with operands [left] and [right].
   ///
@@ -1588,8 +1587,8 @@
   ///       m(rhs) => o += rhs;
   ///     }
   ///
-  R visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+  R visitStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// static [method], that is, closurizing [method], and writing to a static
@@ -1604,7 +1603,7 @@
   ///     }
   ///
   R visitStaticMethodSetterCompound(Send node, MethodElement method,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] on a top level
   /// [field].
@@ -1637,8 +1636,8 @@
   ///     set o(_) {}
   ///     m(rhs) => o += rhs;
   ///
-  R visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+  R visitTopLevelGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// top level [method], that is, closurizing [method], and writing to a top
@@ -1651,7 +1650,7 @@
   ///     m(rhs) => o += rhs;
   ///
   R visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// top level [method], that is, closurizing [method], and writing to an
@@ -1662,7 +1661,7 @@
   ///     o() {}
   ///     m(rhs) => o += rhs;
   ///
-  R visitTopLevelMethodCompound(Send node, FunctionElement method,
+  R visitTopLevelMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] on a super
@@ -1838,8 +1837,8 @@
   ///       m(rhs) => o ??= rhs;
   ///     }
   ///
-  R visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg);
+  R visitStaticGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the static property defined by
   /// [method] and [setter]. That is, [rhs] is only evaluated and assigned to
@@ -1855,7 +1854,7 @@
   ///     }
   ///
   R visitStaticMethodSetterSetIfNull(
-      Send node, MethodElement method, MethodElement setter, Node rhs, A arg);
+      Send node, MethodElement method, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the static [method]. That is,
   /// [rhs] is only evaluated and assigned, if the value of the [method] is
@@ -1902,8 +1901,8 @@
   ///     set o(_) {}
   ///     m(rhs) => o ??= rhs;
   ///
-  R visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg);
+  R visitTopLevelGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level property defined
   /// by [method] and [setter]. That is, [rhs] is only evaluated and assigned to
@@ -1916,8 +1915,8 @@
   ///     set o(_) {}
   ///     m(rhs) => o ??= rhs;
   ///
-  R visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg);
+  R visitTopLevelMethodSetterSetIfNull(
+      Send node, FunctionElement method, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level [method]. That is,
   /// [rhs] is only evaluated and assigned, if the value of the [method] is
@@ -1995,8 +1994,8 @@
   ///       m(rhs) => super.o ??= rhs;
   ///     }
   ///
-  R visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg);
+  R visitSuperGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the super property defined
   /// by [method] and [setter]. That is, [rhs] is only evaluated and assigned to
@@ -2013,8 +2012,8 @@
   ///       m(rhs) => super.o ??= rhs;
   ///     }
   ///
-  R visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg);
+  R visitSuperMethodSetterSetIfNull(
+      Send node, FunctionElement method, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the super [method].
   /// That is, [rhs] is only evaluated and assigned, if the value of
@@ -2048,7 +2047,7 @@
   ///     }
   ///
   R visitUnresolvedSuperGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, A arg);
+      Send node, Element element, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the super property defined
   /// by [getter] with no corresponding setter. That is, [rhs] is only evaluated
@@ -2065,7 +2064,7 @@
   ///     }
   ///
   R visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg);
+      Send node, GetterElement getter, Element element, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level property defined
   /// by [field] and [setter]. That is, [rhs] is only evaluated and assigned to
@@ -2084,7 +2083,7 @@
   ///     }
   ///
   R visitSuperFieldSetterSetIfNull(
-      Send node, FieldElement field, FunctionElement setter, Node rhs, A arg);
+      Send node, FieldElement field, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level property defined
   /// by [getter] and [field]. That is, [rhs] is only evaluated and assigned to
@@ -2103,7 +2102,7 @@
   ///     }
   ///
   R visitSuperGetterFieldSetIfNull(
-      Send node, FunctionElement getter, FieldElement field, Node rhs, A arg);
+      Send node, GetterElement getter, FieldElement field, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to an unresolved super property.
   /// That is, [rhs] is only evaluated and assigned, if the value of the
@@ -2134,7 +2133,7 @@
   ///     m1() => C.foo ??= 42;
   ///
   R visitUnresolvedStaticGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, A arg);
+      Send node, Element element, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level property defined
   /// by [setter] with no corresponding getter. That is, [rhs] is only evaluated
@@ -2147,7 +2146,7 @@
   ///     m1() => foo ??= 42;
   ///
   R visitUnresolvedTopLevelGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, A arg);
+      Send node, Element element, SetterElement setter, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the static property defined
   /// by [getter] with no corresponding setter. That is, [rhs] is only evaluated
@@ -2162,7 +2161,7 @@
   ///     m1() => C.foo ??= 42;
   ///
   R visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg);
+      Send node, GetterElement getter, Element element, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to the top level property defined
   /// by [getter] with no corresponding setter. That is, [rhs] is only evaluated
@@ -2175,7 +2174,7 @@
   ///     m1() => foo ??= 42;
   ///
   R visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg);
+      Send node, GetterElement getter, Element element, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to an unresolved property.
   /// That is, [rhs] is only evaluated and assigned, if the value of the
@@ -2278,7 +2277,7 @@
   ///     }
   ///
   R visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, A arg);
+      SendSet node, Element element, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] on an unresolved super property.
   ///
@@ -2291,7 +2290,7 @@
   ///     }
   ///
   R visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, A arg);
+      SendSet node, Element element, IncDecOperator operator, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] on an unresolved
   /// super property.
@@ -2353,8 +2352,8 @@
   ///       m(rhs) => super.o += rhs;
   ///     }
   ///
-  R visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+  R visitSuperGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// super [method], that is, closurizing [method], and writing to a super
@@ -2371,7 +2370,7 @@
   ///     }
   ///
   R visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading the
   /// closurized super [method] and trying to invoke the non-existing setter.
@@ -2385,7 +2384,7 @@
   ///       m(rhs) => super.o += rhs;
   ///     }
   ///
-  R visitSuperMethodCompound(Send node, FunctionElement method,
+  R visitSuperMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from the
@@ -2400,8 +2399,8 @@
   ///       m(rhs) => super.o += rhs;
   ///     }
   ///
-  R visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg);
+  R visitUnresolvedSuperGetterCompound(SendSet node, Element element,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// super [getter] and writing to the non-existing super setter.
@@ -2415,7 +2414,7 @@
   ///       m(rhs) => super.o += rhs;
   ///     }
   ///
-  R visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
@@ -2434,7 +2433,7 @@
   ///     }
   ///
   R visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// super [getter] and writing to a super [field].
@@ -2451,7 +2450,7 @@
   ///       m(rhs) => super.o += rhs;
   ///     }
   ///
-  R visitSuperGetterFieldCompound(Send node, FunctionElement getter,
+  R visitSuperGetterFieldCompound(Send node, GetterElement getter,
       FieldElement field, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment expression of [rhs] with [operator] on a type literal
@@ -2543,7 +2542,7 @@
   ///     }
   ///
   R visitUnresolvedSuperGetterCompoundIndexSet(
-      Send node,
+      SendSet node,
       Element element,
       MethodElement setter,
       Node index,
@@ -2565,7 +2564,7 @@
   ///     }
   ///
   R visitUnresolvedSuperSetterCompoundIndexSet(
-      Send node,
+      SendSet node,
       MethodElement getter,
       Element element,
       Node index,
@@ -2584,8 +2583,8 @@
   ///       m() => super[1] += 42;
   ///     }
   ///
-  R visitUnresolvedSuperCompoundIndexSet(Send node, Element element, Node index,
-      AssignmentOperator operator, Node rhs, A arg);
+  R visitUnresolvedSuperCompoundIndexSet(SendSet node, Element element,
+      Node index, AssignmentOperator operator, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to [index] on the index operators
   /// of [receiver].
@@ -2625,7 +2624,7 @@
   ///       m() => super[1] ??= 42;
   ///     }
   ///
-  R visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexSetIfNull(SendSet node, Element element,
       MethodElement setter, Node index, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to [index] on a super class where
@@ -2640,7 +2639,7 @@
   ///       m() => super[1] ??= 42;
   ///     }
   ///
-  R visitUnresolvedSuperSetterIndexSetIfNull(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexSetIfNull(SendSet node, MethodElement getter,
       Element element, Node index, Node rhs, A arg);
 
   /// If-null assignment expression of [rhs] to [index] on a super class where
@@ -2787,8 +2786,8 @@
   ///       m() => ++o;
   ///     }
   ///
-  R visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitStaticGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a static [method], that is,
   /// closurizing [method], and writing to a static [setter].
@@ -2801,8 +2800,8 @@
   ///       m() => ++o;
   ///     }
   ///
-  R visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitStaticMethodSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] on a top level [field].
   ///
@@ -2833,8 +2832,8 @@
   ///     set o(_) {}
   ///     m() => ++o;
   ///
-  R visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitTopLevelGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a top level [method], that
   /// is, closurizing [method], and writing to a top level [setter].
@@ -2846,7 +2845,7 @@
   ///     m() => ++o;
   ///
   R visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] on a super [field].
   ///
@@ -2860,7 +2859,7 @@
   ///     }
   ///
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg);
+      SendSet node, FieldElement field, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from the super field [readField]
   /// and writing to the different super field [writtenField].
@@ -2877,7 +2876,7 @@
   ///       m() => ++super.field;
   ///     }
   ///
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [field] and writing
@@ -2895,8 +2894,8 @@
   ///       m() => ++super.field;
   ///     }
   ///
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to a super [setter].
@@ -2911,8 +2910,8 @@
   ///       m() => ++super.field;
   ///     }
   ///
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to a super [field].
@@ -2929,7 +2928,7 @@
   ///       m() => ++super.field;
   ///     }
   ///
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [method], that is,
@@ -2945,8 +2944,8 @@
   ///       m() => ++super.o;
   ///     }
   ///
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [method], that is,
   /// closurizing [method], and writing to an unresolved super setter.
@@ -2962,7 +2961,7 @@
   ///     }
   ///
   R visitSuperMethodPrefix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg);
+      Send node, MethodElement method, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from an unresolved super getter
   /// and writing to a super [setter].
@@ -2977,8 +2976,8 @@
   ///     }
   ///
   ///
-  R visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+  R visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to an unresolved super setter.
@@ -2993,7 +2992,7 @@
   ///     }
   ///
   ///
-  R visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPrefix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] on a type literal for a class [element].
@@ -3168,8 +3167,8 @@
   ///       m() => o++;
   ///     }
   ///
-  R visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitStaticGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a static [method], that
   /// is, closurizing [method], and writing to a static [setter].
@@ -3182,8 +3181,8 @@
   ///       m() => o++;
   ///     }
   ///
-  R visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitStaticMethodSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] on a top level [field].
   ///
@@ -3214,8 +3213,8 @@
   ///     set o(_) {}
   ///     m() => o++;
   ///
-  R visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitTopLevelGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a top level [method], that
   /// is, closurizing [method], and writing to a top level [setter].
@@ -3227,7 +3226,7 @@
   ///     m() => o++;
   ///
   R visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] on a super [field].
   ///
@@ -3241,7 +3240,7 @@
   ///     }
   ///
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg);
+      SendSet node, FieldElement field, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from the super field
   /// [readField] and writing to the different super field [writtenField].
@@ -3258,7 +3257,7 @@
   ///       m() => super.field++;
   ///     }
   ///
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a super [field] and
@@ -3276,8 +3275,8 @@
   ///       m() => super.field++;
   ///     }
   ///
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a super [getter] and
   /// writing to a super [setter].
@@ -3292,8 +3291,8 @@
   ///       m() => super.field++;
   ///     }
   ///
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a super [getter] and
   /// writing to a super [field].
@@ -3310,7 +3309,7 @@
   ///       m() => super.field++;
   ///     }
   ///
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a super [method], that is,
@@ -3326,8 +3325,8 @@
   ///       m() => super.o++;
   ///     }
   ///
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg);
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] reading from a super [method], that is,
   /// closurizing [method], and writing to an unresolved super.
@@ -3343,7 +3342,7 @@
   ///     }
   ///
   R visitSuperMethodPostfix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg);
+      Send node, MethodElement method, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from an unresolved super getter
   /// and writing to a super [setter].
@@ -3358,8 +3357,8 @@
   ///     }
   ///
   ///
-  R visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+  R visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to an unresolved super setter.
@@ -3374,7 +3373,7 @@
   ///     }
   ///
   ///
-  R visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPostfix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Postfix expression with [operator] on a type literal for a class
@@ -3488,7 +3487,7 @@
   ///     m11() => unresolved?.Foo?.bar = 42;
   ///
   // TODO(johnniwinther): Split the cases in which a prefix is resolved.
-  R visitUnresolvedSet(Send node, Element element, Node rhs, A arg);
+  R visitUnresolvedSet(SendSet node, Element element, Node rhs, A arg);
 
   ///  Assignment of [rhs] to the unresolved super [element].
   ///
@@ -3545,7 +3544,7 @@
   ///     m1() => C.foo += 42;
   ///
   R visitUnresolvedStaticGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment of [rhs] with [operator] reading from the
   /// non-existing top level getter and writing to the top level [setter].
@@ -3556,7 +3555,7 @@
   ///     m1() => foo += 42;
   ///
   R visitUnresolvedTopLevelGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment of [rhs] with [operator] reading from the static
   /// [getter] and writing to the non-existing static setter.
@@ -3568,7 +3567,7 @@
   ///     }
   ///     m1() => C.foo += 42;
   ///
-  R visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment of [rhs] with [operator] reading from the top level
@@ -3579,7 +3578,7 @@
   ///     get foo => 42;
   ///     m1() => foo += 42;
   ///
-  R visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg);
 
   /// Compound assignment of [rhs] with [operator] reading the closurized static
@@ -3613,8 +3612,8 @@
   ///     m11() => unresolved?.Foo?.bar += 42;
   ///
   // TODO(johnniwinther): Split the cases in which a prefix is resolved.
-  R visitUnresolvedCompound(
-      Send node, Element element, AssignmentOperator operator, Node rhs, A arg);
+  R visitUnresolvedCompound(Send node, ErroneousElement element,
+      AssignmentOperator operator, Node rhs, A arg);
 
   /// Prefix operation of [operator] reading from the non-existing static getter
   /// and writing to the static [setter].
@@ -3627,7 +3626,7 @@
   ///     m1() => ++C.foo;
   ///
   R visitUnresolvedStaticGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix operation of [operator] reading from the non-existing top level
   /// getter and writing to the top level [setter].
@@ -3638,7 +3637,7 @@
   ///     m1() => ++foo;
   ///
   R visitUnresolvedTopLevelGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Prefix operation of [operator] reading from the static [getter] and
   /// writing to the non-existing static setter.
@@ -3650,7 +3649,7 @@
   ///     }
   ///     m1() => ++C.foo;
   ///
-  R visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading from the top level [getter] and
@@ -3661,7 +3660,7 @@
   ///     get foo => 42;
   ///     m1() => ++foo;
   ///
-  R visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Prefix operation of [operator] reading the closurized static [method] and
@@ -3709,7 +3708,7 @@
   ///
   // TODO(johnniwinther): Split the cases in which a prefix is resolved.
   R visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, A arg);
+      Send node, ErroneousElement element, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading from the non-existing static
   /// getter and writing to the static [setter].
@@ -3722,7 +3721,7 @@
   ///     m1() => C.foo++;
   ///
   R visitUnresolvedStaticGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading from the non-existing top level
   /// getter and writing to the top level [setter].
@@ -3733,7 +3732,7 @@
   ///     m1() => foo++;
   ///
   R visitUnresolvedTopLevelGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg);
+      SetterElement setter, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading from the static [getter] and
   /// writing to the non-existing static setter.
@@ -3745,7 +3744,7 @@
   ///     }
   ///     m1() => C.foo++;
   ///
-  R visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading from the top level [getter] and
@@ -3756,7 +3755,7 @@
   ///     get foo => 42;
   ///     m1() => foo++;
   ///
-  R visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg);
 
   /// Postfix operation of [operator] reading the closurized static [method] and
@@ -3804,7 +3803,7 @@
   ///
   // TODO(johnniwinther): Split the cases in which a prefix is resolved.
   R visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, A arg);
+      Send node, ErroneousElement element, IncDecOperator operator, A arg);
 
   /// Invocation of an undefined unary [operator] on [expression].
   R errorUndefinedUnaryExpression(
@@ -3966,8 +3965,13 @@
   ///
   // TODO(johnniwinther): Change [type] to [MalformedType] when is it not
   // `dynamic`.
-  R visitUnresolvedClassConstructorInvoke(NewExpression node, Element element,
-      ResolutionDartType type, NodeList arguments, Selector selector, A arg);
+  R visitUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      ErroneousElement element,
+      ResolutionDartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
 
   /// Constant invocation of a non-constant constructor.
   ///
@@ -4242,7 +4246,7 @@
   ///     get m => 42;
   ///
   R visitTopLevelGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg);
+      FunctionExpression node, GetterElement getter, Node body, A arg);
 
   /// A declaration of a top level [setter].
   ///
@@ -4251,7 +4255,7 @@
   ///     set m(a) {}
   ///
   R visitTopLevelSetterDeclaration(FunctionExpression node,
-      MethodElement setter, NodeList parameters, Node body, A arg);
+      SetterElement setter, NodeList parameters, Node body, A arg);
 
   /// A declaration of a top level [function].
   ///
@@ -4271,7 +4275,7 @@
   ///     }
   ///
   R visitStaticGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg);
+      FunctionExpression node, GetterElement getter, Node body, A arg);
 
   /// A declaration of a static [setter].
   ///
@@ -4281,7 +4285,7 @@
   ///       static set m(a) {}
   ///     }
   ///
-  R visitStaticSetterDeclaration(FunctionExpression node, MethodElement setter,
+  R visitStaticSetterDeclaration(FunctionExpression node, SetterElement setter,
       NodeList parameters, Node body, A arg);
 
   /// A declaration of a static [function].
@@ -4304,7 +4308,7 @@
   ///     }
   ///
   R visitAbstractGetterDeclaration(
-      FunctionExpression node, MethodElement getter, A arg);
+      FunctionExpression node, GetterElement getter, A arg);
 
   /// A declaration of an abstract instance [setter].
   ///
@@ -4315,7 +4319,7 @@
   ///     }
   ///
   R visitAbstractSetterDeclaration(FunctionExpression node,
-      MethodElement setter, NodeList parameters, A arg);
+      SetterElement setter, NodeList parameters, A arg);
 
   /// A declaration of an abstract instance [method].
   ///
@@ -4337,7 +4341,7 @@
   ///     }
   ///
   R visitInstanceGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg);
+      FunctionExpression node, GetterElement getter, Node body, A arg);
 
   /// A declaration of an instance [setter].
   ///
@@ -4348,7 +4352,7 @@
   ///     }
   ///
   R visitInstanceSetterDeclaration(FunctionExpression node,
-      MethodElement setter, NodeList parameters, Node body, A arg);
+      SetterElement setter, NodeList parameters, Node body, A arg);
 
   /// A declaration of an instance [method].
   ///
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
index d46a6ef..a10f4e7 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
@@ -153,7 +153,7 @@
 /// methods.
 abstract class PrefixBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
-  R bulkHandlePrefix(Send node, A arg) {
+  R bulkHandlePrefix(SendSet node, A arg) {
     return bulkHandleNode(node, "Prefix expression `#` unhandled.", arg);
   }
 
@@ -193,52 +193,52 @@
   }
 
   @override
-  R visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
   R visitSuperIndexPrefix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -246,13 +246,13 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPrefix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexPrefix(SendSet node, MethodElement getter,
       Element element, Node index, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
@@ -264,8 +264,8 @@
   }
 
   @override
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
@@ -282,14 +282,14 @@
   }
 
   @override
-  R visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
   R visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
@@ -336,13 +336,13 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
@@ -361,7 +361,7 @@
 
   @override
   R visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
@@ -391,7 +391,7 @@
 
   @override
   R visitSuperMethodPrefix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
@@ -403,18 +403,18 @@
 
   @override
   R visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPrefix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePrefix(node, arg);
   }
@@ -427,7 +427,7 @@
 /// methods.
 abstract class PostfixBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
-  R bulkHandlePostfix(Send node, A arg) {
+  R bulkHandlePostfix(SendSet node, A arg) {
     return bulkHandleNode(node, "Postfix expression `#` unhandled.", arg);
   }
 
@@ -467,52 +467,52 @@
   }
 
   @override
-  R visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
   R visitSuperIndexPostfix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -520,13 +520,13 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPostfix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexPostfix(SendSet node, MethodElement getter,
       Element element, Node index, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
@@ -538,8 +538,8 @@
   }
 
   @override
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
@@ -556,14 +556,14 @@
   }
 
   @override
-  R visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
   R visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
@@ -610,13 +610,13 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
@@ -634,7 +634,7 @@
 
   @override
   R visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
@@ -664,7 +664,7 @@
 
   @override
   R visitSuperMethodPostfix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
@@ -682,18 +682,18 @@
 
   @override
   R visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPostfix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return bulkHandlePostfix(node, arg);
   }
@@ -706,7 +706,7 @@
 /// methods.
 abstract class CompoundBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
-  R bulkHandleCompound(Send node, A arg) {
+  R bulkHandleCompound(SendSet node, A arg) {
     return bulkHandleNode(node, "Compound assignment `#` unhandled.", arg);
   }
 
@@ -741,14 +741,14 @@
   }
 
   @override
-  R visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
   R visitStaticMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
@@ -760,25 +760,25 @@
 
   @override
   R visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldCompound(Send node, FunctionElement getter,
+  R visitSuperGetterFieldCompound(Send node, GetterElement getter,
       FieldElement field, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitSuperGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
   R visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
@@ -795,14 +795,14 @@
   }
 
   @override
-  R visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitTopLevelGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
   R visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
@@ -879,13 +879,13 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
-  R visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
@@ -903,7 +903,7 @@
   }
 
   @override
-  R visitUnresolvedCompound(Send node, Element element,
+  R visitUnresolvedCompound(Send node, ErroneousElement element,
       AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
@@ -915,7 +915,7 @@
   }
 
   @override
-  R visitSuperMethodCompound(Send node, FunctionElement method,
+  R visitSuperMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
@@ -927,13 +927,13 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitUnresolvedSuperGetterCompound(SendSet node, Element element,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleCompound(node, arg);
   }
@@ -946,7 +946,7 @@
 /// methods.
 abstract class SetIfNullBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
-  R bulkHandleSetIfNull(Send node, A arg) {
+  R bulkHandleSetIfNull(SendSet node, A arg) {
     return bulkHandleNode(node, "If null assignment `#` unhandled.", arg);
   }
 
@@ -1028,8 +1028,8 @@
   }
 
   @override
-  R visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitStaticGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1058,19 +1058,19 @@
 
   @override
   R visitSuperFieldSetterSetIfNull(
-      Send node, FieldElement field, FunctionElement setter, Node rhs, A arg) {
+      Send node, FieldElement field, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
   @override
   R visitSuperGetterFieldSetIfNull(
-      Send node, FunctionElement getter, FieldElement field, Node rhs, A arg) {
+      Send node, GetterElement getter, FieldElement field, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitSuperGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1082,7 +1082,7 @@
 
   @override
   R visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1098,8 +1098,8 @@
   }
 
   @override
-  R visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitTopLevelGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1111,7 +1111,7 @@
 
   @override
   R visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1140,7 +1140,7 @@
 
   @override
   R visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1157,7 +1157,7 @@
 
   @override
   R visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1169,7 +1169,7 @@
 
   @override
   R visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
@@ -1186,13 +1186,13 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexSetIfNull(SendSet node, Element element,
       MethodElement setter, Node index, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexSetIfNull(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexSetIfNull(SendSet node, MethodElement getter,
       Element element, Node index, Node rhs, A arg) {
     return bulkHandleSetIfNull(node, arg);
   }
@@ -1292,8 +1292,8 @@
   }
 
   @override
-  R visitStaticGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitStaticGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
 
@@ -1304,8 +1304,8 @@
   }
 
   @override
-  R visitSuperGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitSuperGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
 
@@ -1352,7 +1352,7 @@
   }
 
   @override
-  R visitTopLevelGetterInvoke(Send node, FunctionElement getter,
+  R visitTopLevelGetterInvoke(Send node, GetterElement getter,
       NodeList arguments, CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
@@ -1388,19 +1388,19 @@
   }
 
   @override
-  R visitStaticSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitStaticSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
 
   @override
-  R visitSuperSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitSuperSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
 
   @override
-  R visitTopLevelSetterInvoke(Send node, FunctionElement setter,
+  R visitTopLevelSetterInvoke(Send node, SetterElement setter,
       NodeList arguments, CallStructure callStructure, A arg) {
     return bulkHandleInvoke(node, arg);
   }
@@ -1464,7 +1464,7 @@
   }
 
   @override
-  R visitStaticGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitStaticGetterGet(Send node, GetterElement getter, A arg) {
     return bulkHandleGet(node, arg);
   }
 
@@ -1474,7 +1474,7 @@
   }
 
   @override
-  R visitSuperGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitSuperGetterGet(Send node, GetterElement getter, A arg) {
     return bulkHandleGet(node, arg);
   }
 
@@ -1504,7 +1504,7 @@
   }
 
   @override
-  R visitTopLevelGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitTopLevelGetterGet(Send node, GetterElement getter, A arg) {
     return bulkHandleGet(node, arg);
   }
 
@@ -1535,17 +1535,17 @@
   }
 
   @override
-  R visitStaticSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitStaticSetterGet(Send node, SetterElement setter, A arg) {
     return bulkHandleGet(node, arg);
   }
 
   @override
-  R visitSuperSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitSuperSetterGet(Send node, SetterElement setter, A arg) {
     return bulkHandleGet(node, arg);
   }
 
   @override
-  R visitTopLevelSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitTopLevelSetterGet(Send node, SetterElement setter, A arg) {
     return bulkHandleGet(node, arg);
   }
 }
@@ -1557,7 +1557,7 @@
 /// methods.
 abstract class SetBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
-  R bulkHandleSet(Send node, A arg) {
+  R bulkHandleSet(SendSet node, A arg) {
     return bulkHandleNode(node, "Assignment `#` unhandled.", arg);
   }
 
@@ -1591,8 +1591,7 @@
   }
 
   @override
-  R visitStaticSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitStaticSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
@@ -1602,7 +1601,7 @@
   }
 
   @override
-  R visitSuperSetterSet(SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitSuperSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
@@ -1618,19 +1617,19 @@
 
   @override
   R visitTopLevelSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+      SendSet node, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
   R visitClassTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
   R visitDynamicTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
@@ -1670,35 +1669,35 @@
   }
 
   @override
-  R visitStaticFunctionSet(Send node, MethodElement function, Node rhs, A arg) {
+  R visitStaticFunctionSet(
+      SendSet node, MethodElement function, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
-  R visitStaticGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+  R visitStaticGetterSet(SendSet node, GetterElement getter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
-  R visitSuperGetterSet(SendSet node, FunctionElement getter, Node rhs, A arg) {
+  R visitSuperGetterSet(SendSet node, GetterElement getter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
-  R visitSuperMethodSet(Send node, MethodElement method, Node rhs, A arg) {
+  R visitSuperMethodSet(SendSet node, MethodElement method, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
   R visitTopLevelFunctionSet(
-      Send node, MethodElement function, Node rhs, A arg) {
+      SendSet node, MethodElement function, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
   R visitTopLevelGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+      SendSet node, GetterElement getter, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
@@ -1710,12 +1709,12 @@
 
   @override
   R visitTypedefTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
   @override
-  R visitUnresolvedSet(Send node, Element element, Node rhs, A arg) {
+  R visitUnresolvedSet(SendSet node, Element element, Node rhs, A arg) {
     return bulkHandleSet(node, arg);
   }
 
@@ -1750,8 +1749,8 @@
   @override
   R visitSuperCompoundIndexSet(
       SendSet node,
-      FunctionElement getter,
-      FunctionElement setter,
+      MethodElement getter,
+      MethodElement setter,
       Node index,
       AssignmentOperator operator,
       Node rhs,
@@ -1797,7 +1796,7 @@
 
   @override
   R visitUnresolvedSuperIndexSet(
-      SendSet node, Element element, Node index, Node rhs, A arg) {
+      SendSet node, ErroneousElement element, Node index, Node rhs, A arg) {
     return bulkHandleIndexSet(node, arg);
   }
 }
@@ -1835,30 +1834,29 @@
   }
 
   @override
-  R visitSuperBinary(Send node, FunctionElement function,
-      BinaryOperator operator, Node argument, A arg) {
+  R visitSuperBinary(Send node, MethodElement function, BinaryOperator operator,
+      Node argument, A arg) {
     return bulkHandleBinary(node, arg);
   }
 
   @override
-  R visitSuperEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+  R visitSuperEquals(Send node, MethodElement function, Node argument, A arg) {
     return bulkHandleBinary(node, arg);
   }
 
   @override
   R visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+      Send node, MethodElement function, Node argument, A arg) {
     return bulkHandleBinary(node, arg);
   }
 
   @override
-  R visitSuperIndex(Send node, FunctionElement function, Node index, A arg) {
+  R visitSuperIndex(Send node, MethodElement function, Node index, A arg) {
     return bulkHandleBinary(node, arg);
   }
 
   @override
-  R visitUnresolvedSuperBinary(Send node, FunctionElement function,
+  R visitUnresolvedSuperBinary(Send node, Element function,
       BinaryOperator operator, Node argument, A arg) {
     return bulkHandleBinary(node, arg);
   }
@@ -1870,8 +1868,7 @@
   }
 
   @override
-  R visitUnresolvedSuperIndex(
-      Send node, FunctionElement function, Node index, A arg) {
+  R visitUnresolvedSuperIndex(Send node, Element function, Node index, A arg) {
     return bulkHandleBinary(node, arg);
   }
 }
@@ -1894,7 +1891,7 @@
 
   @override
   R visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, A arg) {
+      Send node, UnaryOperator operator, MethodElement function, A arg) {
     return bulkHandleUnary(node, arg);
   }
 
@@ -1905,7 +1902,7 @@
 
   @override
   R visitUnresolvedSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, A arg) {
+      Send node, UnaryOperator operator, Element function, A arg) {
     return bulkHandleUnary(node, arg);
   }
 }
@@ -1965,16 +1962,16 @@
   }
 
   @override
-  R visitSuperBinary(Send node, FunctionElement function,
-      BinaryOperator operator, Node argument, A arg) {
+  R visitSuperBinary(Send node, MethodElement function, BinaryOperator operator,
+      Node argument, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
   R visitSuperCompoundIndexSet(
       SendSet node,
-      FunctionElement getter,
-      FunctionElement setter,
+      MethodElement getter,
+      MethodElement setter,
       Node index,
       AssignmentOperator operator,
       Node rhs,
@@ -1983,8 +1980,7 @@
   }
 
   @override
-  R visitSuperEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+  R visitSuperEquals(Send node, MethodElement function, Node argument, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
@@ -1995,13 +1991,13 @@
   }
 
   @override
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
@@ -2019,13 +2015,13 @@
 
   @override
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
@@ -2036,66 +2032,66 @@
 
   @override
   R visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldCompound(Send node, FunctionElement getter,
+  R visitSuperGetterFieldCompound(Send node, GetterElement getter,
       FieldElement field, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitSuperGetterGet(Send node, GetterElement getter, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitSuperGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitSuperGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
@@ -2124,36 +2120,36 @@
 
   @override
   R visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
   R visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+      Send node, MethodElement function, Node argument, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
-  R visitSuperSetterSet(SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitSuperSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
   @override
   R visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, A arg) {
+      Send node, UnaryOperator operator, MethodElement function, A arg) {
     return bulkHandleSuper(node, arg);
   }
 
@@ -2290,8 +2286,13 @@
   }
 
   @override
-  R visitUnresolvedClassConstructorInvoke(NewExpression node, Element element,
-      ResolutionDartType type, NodeList arguments, Selector selector, A arg) {
+  R visitUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      ErroneousElement element,
+      ResolutionDartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
     return bulkHandleNew(node, arg);
   }
 
@@ -2529,7 +2530,7 @@
 
   @override
   R visitAbstractGetterDeclaration(
-      FunctionExpression node, MethodElement getter, A arg) {
+      FunctionExpression node, GetterElement getter, A arg) {
     return bulkHandleFunctionDeclaration(node, arg);
   }
 
@@ -2553,7 +2554,7 @@
 
   @override
   R visitInstanceGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     return bulkHandleFunctionDeclaration(node, arg);
   }
 
@@ -2583,7 +2584,7 @@
 
   @override
   R visitStaticGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     return bulkHandleFunctionDeclaration(node, arg);
   }
 
@@ -2601,7 +2602,7 @@
 
   @override
   R visitTopLevelGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     return bulkHandleFunctionDeclaration(node, arg);
   }
 
@@ -2813,14 +2814,14 @@
 
   @override
   R visitClassTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
   R visitDynamicTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -2914,75 +2915,75 @@
   }
 
   @override
-  R visitStaticFunctionSet(Send node, MethodElement function, Node rhs, A arg) {
+  R visitStaticFunctionSet(
+      SendSet node, MethodElement function, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitStaticGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+  R visitStaticGetterSet(SendSet node, GetterElement getter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitStaticSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitStaticSetterGet(Send node, SetterElement setter, A arg) {
     return null;
   }
 
   @override
-  R visitStaticSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitStaticSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
   }
 
   @override
-  R visitSuperGetterSet(SendSet node, FunctionElement getter, Node rhs, A arg) {
+  R visitSuperGetterSet(SendSet node, GetterElement getter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperMethodSet(Send node, MethodElement method, Node rhs, A arg) {
+  R visitSuperMethodSet(SendSet node, MethodElement method, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitSuperSetterGet(Send node, SetterElement setter, A arg) {
     return null;
   }
 
   @override
-  R visitSuperSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitSuperSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
   }
 
   @override
   R visitTopLevelFunctionSet(
-      Send node, MethodElement function, Node rhs, A arg) {
+      SendSet node, MethodElement function, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
   R visitTopLevelGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+      SendSet node, GetterElement getter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitTopLevelSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitTopLevelSetterGet(Send node, SetterElement setter, A arg) {
     return null;
   }
 
   @override
-  R visitTopLevelSetterInvoke(Send node, FunctionElement setter,
+  R visitTopLevelSetterInvoke(Send node, SetterElement setter,
       NodeList arguments, CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
@@ -2997,7 +2998,7 @@
 
   @override
   R visitTypedefTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, A arg) {
+      SendSet node, TypeConstantExpression constant, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -3444,65 +3445,64 @@
   }
 
   @override
-  R visitStaticGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitStaticGetterGet(Send node, GetterElement getter, A arg) {
     return null;
   }
 
   @override
-  R visitStaticGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitStaticGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
   }
 
   @override
-  R visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitStaticMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitStaticSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitStaticSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperBinary(Send node, FunctionElement function,
-      BinaryOperator operator, Node argument, A arg) {
+  R visitSuperBinary(Send node, MethodElement function, BinaryOperator operator,
+      Node argument, A arg) {
     apply(argument, arg);
     return null;
   }
@@ -3510,8 +3510,8 @@
   @override
   R visitSuperCompoundIndexSet(
       SendSet node,
-      FunctionElement getter,
-      FunctionElement setter,
+      MethodElement getter,
+      MethodElement setter,
       Node index,
       AssignmentOperator operator,
       Node rhs,
@@ -3521,8 +3521,7 @@
   }
 
   @override
-  R visitSuperEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+  R visitSuperEquals(Send node, MethodElement function, Node argument, A arg) {
     apply(argument, arg);
     return null;
   }
@@ -3535,13 +3534,13 @@
   }
 
   @override
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return null;
   }
@@ -3560,13 +3559,13 @@
 
   @override
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return null;
   }
 
@@ -3578,75 +3577,75 @@
 
   @override
   R visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperGetterFieldCompound(Send node, FunctionElement getter,
+  R visitSuperGetterFieldCompound(Send node, GetterElement getter,
       FieldElement field, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitSuperGetterGet(Send node, GetterElement getter, A arg) {
     return null;
   }
 
   @override
-  R visitSuperGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitSuperGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
   }
 
   @override
-  R visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitSuperGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperIndex(Send node, FunctionElement function, Node index, A arg) {
+  R visitSuperIndex(Send node, MethodElement function, Node index, A arg) {
     apply(index, arg);
     return null;
   }
@@ -3680,39 +3679,39 @@
 
   @override
   R visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, A arg) {
+      Send node, MethodElement function, Node argument, A arg) {
     apply(argument, arg);
     return null;
   }
 
   @override
-  R visitSuperSetterSet(SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitSuperSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
   R visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, A arg) {
+      Send node, UnaryOperator operator, MethodElement function, A arg) {
     return null;
   }
 
@@ -3822,58 +3821,58 @@
   }
 
   @override
-  R visitTopLevelGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitTopLevelGetterGet(Send node, GetterElement getter, A arg) {
     return null;
   }
 
   @override
-  R visitTopLevelGetterInvoke(Send node, FunctionElement getter,
+  R visitTopLevelGetterInvoke(Send node, GetterElement getter,
       NodeList arguments, CallStructure callStructure, A arg) {
     apply(arguments, arg);
     return null;
   }
 
   @override
-  R visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitTopLevelGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
   R visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitTopLevelSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+      SendSet node, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -3948,7 +3947,7 @@
   }
 
   @override
-  R visitUnresolvedCompound(Send node, Element element,
+  R visitUnresolvedCompound(Send node, ErroneousElement element,
       AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
@@ -3968,18 +3967,18 @@
 
   @override
   R visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedSet(Send node, Element element, Node rhs, A arg) {
+  R visitUnresolvedSet(SendSet node, Element element, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4001,7 +4000,7 @@
 
   @override
   R visitUnresolvedSuperIndexSet(
-      Send node, Element element, Node index, Node rhs, A arg) {
+      SendSet node, ErroneousElement element, Node index, Node rhs, A arg) {
     apply(index, arg);
     apply(rhs, arg);
     return null;
@@ -4057,14 +4056,14 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPostfix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     apply(index, arg);
     return null;
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexPostfix(SendSet node, MethodElement getter,
       Element element, Node index, IncDecOperator operator, A arg) {
     apply(index, arg);
     return null;
@@ -4078,14 +4077,14 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPrefix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     apply(index, arg);
     return null;
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexPrefix(SendSet node, MethodElement getter,
       Element element, Node index, IncDecOperator operator, A arg) {
     apply(index, arg);
     return null;
@@ -4117,8 +4116,8 @@
   @override
   R visitSuperIndexPostfix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -4129,8 +4128,8 @@
   @override
   R visitSuperIndexPrefix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -4237,8 +4236,8 @@
   }
 
   @override
-  R visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitStaticGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4272,21 +4271,21 @@
 
   @override
   R visitSuperFieldSetterSetIfNull(
-      Send node, FieldElement field, FunctionElement setter, Node rhs, A arg) {
+      Send node, FieldElement field, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
   R visitSuperGetterFieldSetIfNull(
-      Send node, FunctionElement getter, FieldElement field, Node rhs, A arg) {
+      Send node, GetterElement getter, FieldElement field, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitSuperGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4300,7 +4299,7 @@
 
   @override
   R visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4319,8 +4318,8 @@
   }
 
   @override
-  R visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitTopLevelGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4334,7 +4333,7 @@
 
   @override
   R visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4368,7 +4367,7 @@
 
   @override
   R visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4388,7 +4387,7 @@
 
   @override
   R visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4402,7 +4401,7 @@
 
   @override
   R visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
@@ -4446,7 +4445,7 @@
   @override
   R visitUnresolvedClassConstructorInvoke(
       NewExpression node,
-      Element constructor,
+      ErroneousElement constructor,
       ResolutionDartType type,
       NodeList arguments,
       Selector selector,
@@ -4563,14 +4562,14 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
@@ -4596,13 +4595,13 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
@@ -4632,13 +4631,13 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
@@ -4718,7 +4717,7 @@
   }
 
   @override
-  R visitSuperMethodCompound(Send node, FunctionElement method,
+  R visitSuperMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
@@ -4726,13 +4725,13 @@
 
   @override
   R visitSuperMethodPostfix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitSuperMethodPrefix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return null;
   }
 
@@ -4749,7 +4748,7 @@
   }
 
   @override
-  R visitTopLevelMethodCompound(Send node, FunctionElement method,
+  R visitTopLevelMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
@@ -4764,50 +4763,50 @@
 
   @override
   R visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
   R visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitUnresolvedSuperGetterCompound(SendSet node, Element element,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     apply(rhs, arg);
     return null;
   }
 
   @override
-  R visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPostfix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
 
   @override
-  R visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPrefix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return null;
   }
@@ -4830,7 +4829,7 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexSetIfNull(SendSet node, Element element,
       MethodElement setter, Node index, Node rhs, A arg) {
     apply(index, arg);
     apply(rhs, arg);
@@ -4838,7 +4837,7 @@
   }
 
   @override
-  R visitUnresolvedSuperSetterIndexSetIfNull(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterIndexSetIfNull(SendSet node, MethodElement getter,
       Element element, Node index, Node rhs, A arg) {
     apply(index, arg);
     apply(rhs, arg);
@@ -5141,7 +5140,7 @@
 
   @override
   R visitAbstractGetterDeclaration(
-      FunctionExpression node, MethodElement getter, A arg) {
+      FunctionExpression node, GetterElement getter, A arg) {
     return null;
   }
 
@@ -5154,7 +5153,7 @@
 
   @override
   R visitInstanceGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     apply(body, arg);
     return null;
   }
@@ -5169,7 +5168,7 @@
 
   @override
   R visitStaticGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     apply(body, arg);
     return null;
   }
@@ -5184,7 +5183,7 @@
 
   @override
   R visitTopLevelGetterDeclaration(
-      FunctionExpression node, MethodElement getter, Node body, A arg) {
+      FunctionExpression node, GetterElement getter, Node body, A arg) {
     apply(body, arg);
     return null;
   }
@@ -5263,19 +5262,18 @@
   R handleStaticFunctionIncompatibleInvoke(Send node, MethodElement function,
       NodeList arguments, CallStructure callStructure, A arg);
 
-  R handleStaticGetterGet(Send node, FunctionElement getter, A arg);
+  R handleStaticGetterGet(Send node, GetterElement getter, A arg);
 
-  R handleStaticGetterSet(Send node, FunctionElement getter, Node rhs, A arg);
+  R handleStaticGetterSet(SendSet node, GetterElement getter, Node rhs, A arg);
 
-  R handleStaticGetterInvoke(Send node, FunctionElement getter,
+  R handleStaticGetterInvoke(Send node, GetterElement getter,
       NodeList arguments, CallStructure callStructure, A arg);
 
-  R handleStaticSetterGet(SendSet node, FunctionElement setter, A arg);
+  R handleStaticSetterGet(SendSet node, SetterElement setter, A arg);
 
-  R handleStaticSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg);
+  R handleStaticSetterSet(SendSet node, SetterElement setter, Node rhs, A arg);
 
-  R handleStaticSetterInvoke(Send node, FunctionElement setter,
+  R handleStaticSetterInvoke(Send node, SetterElement setter,
       NodeList arguments, CallStructure callStructure, A arg);
 
   R handleFinalStaticFieldSet(
@@ -5320,20 +5318,19 @@
   }
 
   @override
-  R visitStaticGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitStaticGetterGet(Send node, GetterElement getter, A arg) {
     return handleStaticGetterGet(node, getter, arg);
   }
 
   @override
-  R visitStaticGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, A arg) {
+  R visitStaticGetterInvoke(Send node, GetterElement getter, NodeList arguments,
+      CallStructure callStructure, A arg) {
     return handleStaticGetterInvoke(
         node, getter, arguments, callStructure, arg);
   }
 
   @override
-  R visitStaticSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+  R visitStaticSetterSet(SendSet node, SetterElement setter, Node rhs, A arg) {
     return handleStaticSetterSet(node, setter, rhs, arg);
   }
 
@@ -5373,18 +5370,18 @@
   }
 
   @override
-  R visitTopLevelGetterGet(Send node, FunctionElement getter, A arg) {
+  R visitTopLevelGetterGet(Send node, GetterElement getter, A arg) {
     return handleStaticGetterGet(node, getter, arg);
   }
 
   @override
   R visitTopLevelGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+      SendSet node, GetterElement getter, Node rhs, A arg) {
     return handleStaticGetterSet(node, getter, rhs, arg);
   }
 
   @override
-  R visitTopLevelGetterInvoke(Send node, FunctionElement getter,
+  R visitTopLevelGetterInvoke(Send node, GetterElement getter,
       NodeList arguments, CallStructure callStructure, A arg) {
     return handleStaticGetterInvoke(
         node, getter, arguments, callStructure, arg);
@@ -5392,37 +5389,36 @@
 
   @override
   R visitTopLevelSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, A arg) {
+      SendSet node, SetterElement setter, Node rhs, A arg) {
     return handleStaticSetterSet(node, setter, rhs, arg);
   }
 
   @override
-  R visitStaticSetterInvoke(Send node, FunctionElement setter,
+  R visitStaticSetterInvoke(Send node, SetterElement setter, NodeList arguments,
+      CallStructure callStructure, A arg) {
+    return handleStaticSetterInvoke(
+        node, setter, arguments, callStructure, arg);
+  }
+
+  @override
+  R visitTopLevelSetterInvoke(Send node, SetterElement setter,
       NodeList arguments, CallStructure callStructure, A arg) {
     return handleStaticSetterInvoke(
         node, setter, arguments, callStructure, arg);
   }
 
   @override
-  R visitTopLevelSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, A arg) {
-    return handleStaticSetterInvoke(
-        node, setter, arguments, callStructure, arg);
-  }
-
-  @override
-  R visitStaticSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitStaticSetterGet(Send node, SetterElement setter, A arg) {
     return handleStaticSetterGet(node, setter, arg);
   }
 
   @override
-  R visitStaticGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, A arg) {
+  R visitStaticGetterSet(SendSet node, GetterElement getter, Node rhs, A arg) {
     return handleStaticGetterSet(node, getter, rhs, arg);
   }
 
   @override
-  R visitTopLevelSetterGet(Send node, FunctionElement setter, A arg) {
+  R visitTopLevelSetterGet(Send node, SetterElement setter, A arg) {
     return handleStaticSetterGet(node, setter, arg);
   }
 
@@ -5439,13 +5435,14 @@
   }
 
   @override
-  R visitStaticFunctionSet(Send node, MethodElement function, Node rhs, A arg) {
+  R visitStaticFunctionSet(
+      SendSet node, MethodElement function, Node rhs, A arg) {
     return handleStaticFunctionSet(node, function, rhs, arg);
   }
 
   @override
   R visitTopLevelFunctionSet(
-      Send node, MethodElement function, Node rhs, A arg) {
+      SendSet node, MethodElement function, Node rhs, A arg) {
     return handleStaticFunctionSet(node, function, rhs, arg);
   }
 }
@@ -5464,18 +5461,18 @@
       Send node, FieldElement field, IncDecOperator operator, A arg,
       {bool isPrefix});
 
-  R handleStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+  R handleStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
-  R handleStaticGetterSetterPostfixPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg,
+  R handleStaticGetterSetterPostfixPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
   R handleStaticMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
-  R handleStaticMethodSetterPostfixPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg,
+  R handleStaticMethodSetterPostfixPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
   R handleFinalStaticFieldCompound(Send node, FieldElement field,
@@ -5493,16 +5490,16 @@
       {bool isPrefix});
 
   R handleUnresolvedStaticGetterCompound(Send node, Element element,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg);
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg);
 
   R handleUnresolvedStaticGetterPostfixPrefix(Send node, Element element,
-      FunctionElement setter, IncDecOperator operator, A arg,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
-  R handleUnresolvedStaticSetterCompound(Send node, FunctionElement getter,
+  R handleUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg);
 
-  R handleUnresolvedStaticSetterPostfixPrefix(Send node, FunctionElement getter,
+  R handleUnresolvedStaticSetterPostfixPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg,
       {bool isPrefix});
 
@@ -5527,23 +5524,23 @@
   }
 
   @override
-  R visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticGetterSetterCompound(
         node, getter, setter, operator, rhs, arg);
   }
 
   @override
-  R visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: true);
@@ -5551,22 +5548,22 @@
 
   @override
   R visitStaticMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticMethodSetterCompound(
         node, method, setter, operator, rhs, arg);
   }
 
   @override
-  R visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticMethodSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticMethodSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: true);
@@ -5593,23 +5590,23 @@
   }
 
   @override
-  R visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitTopLevelGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticGetterSetterCompound(
         node, getter, setter, operator, rhs, arg);
   }
 
   @override
-  R visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: true);
@@ -5617,14 +5614,14 @@
 
   @override
   R visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticMethodSetterCompound(
         node, method, setter, operator, rhs, arg);
   }
 
   @override
   R visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticMethodSetterPostfixPrefix(
         node, method, setter, operator, arg,
         isPrefix: false);
@@ -5632,7 +5629,7 @@
 
   @override
   R visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticMethodSetterPostfixPrefix(
         node, method, setter, operator, arg,
         isPrefix: true);
@@ -5680,14 +5677,14 @@
 
   @override
   R visitUnresolvedStaticGetterCompound(Send node, Element element,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleUnresolvedStaticGetterCompound(
         node, element, setter, operator, rhs, arg);
   }
 
   @override
   R visitUnresolvedStaticGetterPostfix(Send node, Element element,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleUnresolvedStaticGetterPostfixPrefix(
         node, element, setter, operator, arg,
         isPrefix: false);
@@ -5695,21 +5692,21 @@
 
   @override
   R visitUnresolvedStaticGetterPrefix(Send node, Element element,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleUnresolvedStaticGetterPostfixPrefix(
         node, element, setter, operator, arg,
         isPrefix: true);
   }
 
   @override
-  R visitUnresolvedStaticSetterCompound(Send node, FunctionElement getter,
+  R visitUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return handleUnresolvedStaticSetterCompound(
         node, getter, element, operator, rhs, arg);
   }
 
   @override
-  R visitUnresolvedStaticSetterPostfix(Send node, FunctionElement getter,
+  R visitUnresolvedStaticSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleUnresolvedStaticSetterPostfixPrefix(
         node, getter, element, operator, arg,
@@ -5717,7 +5714,7 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPrefix(Send node, FunctionElement getter,
+  R visitUnresolvedStaticSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleUnresolvedStaticSetterPostfixPrefix(
         node, getter, element, operator, arg,
@@ -6309,15 +6306,15 @@
   }
 
   @override
-  R visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitStaticGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
   R visitStaticMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, method, CompoundGetter.METHOD, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
@@ -6337,15 +6334,15 @@
   }
 
   @override
-  R visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitTopLevelGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
   R visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, method, CompoundGetter.METHOD, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
@@ -6365,28 +6362,28 @@
   }
 
   @override
-  R visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitSuperGetterSetterCompound(Send node, GetterElement getter,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
   R visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, method, CompoundGetter.METHOD, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
   R visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, A arg) {
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, field, CompoundGetter.FIELD, setter,
         CompoundSetter.SETTER, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
-  R visitSuperGetterFieldCompound(Send node, FunctionElement getter,
+  R visitSuperGetterFieldCompound(Send node, GetterElement getter,
       FieldElement field, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, getter, CompoundGetter.GETTER, field,
         CompoundSetter.FIELD, new AssignmentCompound(operator, rhs), arg);
@@ -6476,8 +6473,8 @@
   }
 
   @override
-  R visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6488,8 +6485,8 @@
         arg);
   }
 
-  R visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6514,8 +6511,8 @@
   }
 
   @override
-  R visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6528,7 +6525,7 @@
 
   @override
   R visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         method,
@@ -6541,7 +6538,7 @@
 
   @override
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         field,
@@ -6553,7 +6550,7 @@
   }
 
   @override
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -6566,8 +6563,8 @@
   }
 
   @override
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         field,
@@ -6579,8 +6576,8 @@
   }
 
   @override
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         getter,
@@ -6592,7 +6589,7 @@
   }
 
   @override
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -6605,8 +6602,8 @@
   }
 
   @override
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         method,
@@ -6703,8 +6700,8 @@
   }
 
   @override
-  R visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6715,8 +6712,8 @@
         arg);
   }
 
-  R visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitStaticMethodSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6741,8 +6738,8 @@
   }
 
   @override
-  R visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitTopLevelGetterSetterPostfix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         getter,
@@ -6755,7 +6752,7 @@
 
   @override
   R visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         method,
@@ -6768,7 +6765,7 @@
 
   @override
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         field,
@@ -6780,7 +6777,7 @@
   }
 
   @override
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -6793,8 +6790,8 @@
   }
 
   @override
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         field,
@@ -6805,8 +6802,8 @@
         arg);
   }
 
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         getter,
@@ -6818,7 +6815,7 @@
   }
 
   @override
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -6831,8 +6828,8 @@
   }
 
   @override
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         method,
@@ -6898,7 +6895,7 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
@@ -6911,7 +6908,7 @@
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPostfix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
@@ -6951,7 +6948,7 @@
 
   @override
   R visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         element,
@@ -6989,7 +6986,7 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
@@ -7002,7 +6999,7 @@
   }
 
   @override
-  R visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
@@ -7042,7 +7039,7 @@
 
   @override
   R visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      Send node, ErroneousElement element, IncDecOperator operator, A arg) {
     return handleStaticCompounds(
         node,
         element,
@@ -7080,14 +7077,14 @@
   }
 
   @override
-  R visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedStaticSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
-  R visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedTopLevelSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, new AssignmentCompound(operator, rhs), arg);
@@ -7108,7 +7105,7 @@
   }
 
   @override
-  R visitUnresolvedCompound(Send node, Element element,
+  R visitUnresolvedCompound(Send node, ErroneousElement element,
       AssignmentOperator operator, Node rhs, A arg) {
     return handleStaticCompounds(
         node,
@@ -7218,7 +7215,7 @@
   }
 
   @override
-  R visitSuperMethodCompound(Send node, FunctionElement method,
+  R visitSuperMethodCompound(Send node, MethodElement method,
       AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, method, CompoundGetter.METHOD, method,
         CompoundSetter.INVALID, new AssignmentCompound(operator, rhs), arg);
@@ -7226,7 +7223,7 @@
 
   @override
   R visitSuperMethodPostfix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         method,
@@ -7239,7 +7236,7 @@
 
   @override
   R visitSuperMethodPrefix(
-      Send node, FunctionElement method, IncDecOperator operator, A arg) {
+      Send node, MethodElement method, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         method,
@@ -7291,7 +7288,7 @@
 
   @override
   R visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         element,
@@ -7304,7 +7301,7 @@
 
   @override
   R visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         element,
@@ -7316,8 +7313,8 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, A arg) {
+  R visitUnresolvedSuperGetterCompound(SendSet node, Element element,
+      SetterElement setter, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(
         node,
         element,
@@ -7329,8 +7326,8 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         element,
@@ -7342,8 +7339,8 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
         element,
@@ -7355,14 +7352,14 @@
   }
 
   @override
-  R visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterCompound(Send node, GetterElement getter,
       Element element, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperCompounds(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, new AssignmentCompound(operator, rhs), arg);
   }
 
   @override
-  R visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPostfix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -7375,7 +7372,7 @@
   }
 
   @override
-  R visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPrefix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleSuperCompounds(
         node,
@@ -7512,8 +7509,8 @@
   }
 
   @override
-  R visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitStaticGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return handleStaticSetIfNulls(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
@@ -7547,21 +7544,21 @@
 
   @override
   R visitSuperFieldSetterSetIfNull(
-      Send node, FieldElement field, FunctionElement setter, Node rhs, A arg) {
+      Send node, FieldElement field, SetterElement setter, Node rhs, A arg) {
     return handleSuperSetIfNulls(node, field, CompoundGetter.FIELD, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
 
   @override
   R visitSuperGetterFieldSetIfNull(
-      Send node, FunctionElement getter, FieldElement field, Node rhs, A arg) {
+      Send node, GetterElement getter, FieldElement field, Node rhs, A arg) {
     return handleSuperSetIfNulls(node, getter, CompoundGetter.GETTER, field,
         CompoundSetter.FIELD, rhs, arg);
   }
 
   @override
-  R visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitSuperGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return handleSuperSetIfNulls(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
@@ -7575,7 +7572,7 @@
 
   @override
   R visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     return handleSuperSetIfNulls(node, method, CompoundGetter.METHOD, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
@@ -7593,8 +7590,8 @@
   }
 
   @override
-  R visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, A arg) {
+  R visitTopLevelGetterSetterSetIfNull(
+      Send node, GetterElement getter, SetterElement setter, Node rhs, A arg) {
     return handleStaticSetIfNulls(node, getter, CompoundGetter.GETTER, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
@@ -7608,7 +7605,7 @@
 
   @override
   R visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, A arg) {
+      SetterElement setter, Node rhs, A arg) {
     return handleStaticSetIfNulls(node, method, CompoundGetter.METHOD, setter,
         CompoundSetter.SETTER, rhs, arg);
   }
@@ -7634,7 +7631,7 @@
 
   @override
   R visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return handleStaticSetIfNulls(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, rhs, arg);
   }
@@ -7654,7 +7651,7 @@
 
   @override
   R visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return handleSuperSetIfNulls(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, rhs, arg);
   }
@@ -7668,7 +7665,7 @@
 
   @override
   R visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, A arg) {
+      Send node, GetterElement getter, Element element, Node rhs, A arg) {
     return handleStaticSetIfNulls(node, getter, CompoundGetter.GETTER, element,
         CompoundSetter.INVALID, rhs, arg);
   }
@@ -7692,8 +7689,8 @@
   @override
   R visitSuperCompoundIndexSet(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       AssignmentOperator operator,
       Node rhs,
@@ -7706,8 +7703,8 @@
   @override
   R visitSuperIndexPostfix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -7719,8 +7716,8 @@
   @override
   R visitSuperIndexPrefix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -7731,7 +7728,7 @@
 
   @override
   R visitUnresolvedSuperGetterCompoundIndexSet(
-      Send node,
+      SendSet node,
       Element indexFunction,
       FunctionElement indexSetFunction,
       Node index,
@@ -7745,8 +7742,8 @@
 
   @override
   R visitUnresolvedSuperSetterCompoundIndexSet(
-      Send node,
-      FunctionElement indexFunction,
+      SendSet node,
+      MethodElement indexFunction,
       Element indexSetFunction,
       Node index,
       AssignmentOperator operator,
@@ -7758,8 +7755,8 @@
   }
 
   @override
-  R visitUnresolvedSuperCompoundIndexSet(Send node, Element element, Node index,
-      AssignmentOperator operator, Node rhs, A arg) {
+  R visitUnresolvedSuperCompoundIndexSet(SendSet node, Element element,
+      Node index, AssignmentOperator operator, Node rhs, A arg) {
     return handleSuperIndexCompounds(node, element, element, index,
         new AssignmentCompound(operator, rhs), arg,
         isGetterValid: false, isSetterValid: false);
@@ -7767,7 +7764,7 @@
 
   @override
   R visitUnresolvedSuperGetterIndexPostfix(
-      Send node,
+      SendSet node,
       Element element,
       FunctionElement indexSetFunction,
       Node index,
@@ -7780,7 +7777,7 @@
 
   @override
   R visitUnresolvedSuperGetterIndexPrefix(
-      Send node,
+      SendSet node,
       Element element,
       FunctionElement indexSetFunction,
       Node index,
@@ -7793,7 +7790,7 @@
 
   @override
   R visitUnresolvedSuperSetterIndexPostfix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -7806,7 +7803,7 @@
 
   @override
   R visitUnresolvedSuperSetterIndexPrefix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -7872,8 +7869,13 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element indexFunction,
-      FunctionElement indexSetFunction, Node index, Node rhs, A arg) {
+  R visitUnresolvedSuperGetterIndexSetIfNull(
+      SendSet node,
+      Element indexFunction,
+      FunctionElement indexSetFunction,
+      Node index,
+      Node rhs,
+      A arg) {
     return handleSuperIndexSetIfNull(
         node, indexFunction, indexSetFunction, index, rhs, arg,
         isGetterValid: false, isSetterValid: true);
@@ -7881,8 +7883,8 @@
 
   @override
   R visitUnresolvedSuperSetterIndexSetIfNull(
-      Send node,
-      FunctionElement indexFunction,
+      SendSet node,
+      MethodElement indexFunction,
       Element indexSetFunction,
       Node index,
       Node rhs,
@@ -7912,19 +7914,19 @@
       {bool isPrefix});
 
   R handleSuperFieldSetterPostfixPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
-  R handleSuperGetterFieldPostfixPrefix(Send node, FunctionElement getter,
+  R handleSuperGetterFieldPostfixPrefix(Send node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg,
       {bool isPrefix});
 
-  R handleSuperGetterSetterPostfixPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg,
+  R handleSuperGetterSetterPostfixPrefix(Send node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
   R handleSuperMethodSetterPostfixPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg,
+      SetterElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
   R handleSuperIndexPostfixPrefix(
@@ -7969,12 +7971,12 @@
       MethodElement setter, IncDecOperator operator, A arg,
       {bool isPrefix});
 
-  R handleUnresolvedSuperSetterPostfixPrefix(Send node, MethodElement getter,
+  R handleUnresolvedSuperSetterPostfixPrefix(Send node, GetterElement getter,
       Element element, IncDecOperator operator, A arg,
       {bool isPrefix});
 
   @override
-  R visitSuperFieldFieldPostfix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPostfix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return handleSuperFieldFieldPostfixPrefix(
         node, readField, writtenField, operator, arg,
@@ -7982,7 +7984,7 @@
   }
 
   @override
-  R visitSuperFieldFieldPrefix(Send node, FieldElement readField,
+  R visitSuperFieldFieldPrefix(SendSet node, FieldElement readField,
       FieldElement writtenField, IncDecOperator operator, A arg) {
     return handleSuperFieldFieldPostfixPrefix(
         node, readField, writtenField, operator, arg,
@@ -7991,36 +7993,36 @@
 
   @override
   R visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperFieldFieldPostfixPrefix(node, field, field, operator, arg,
         isPrefix: false);
   }
 
   @override
   R visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, A arg) {
+      SendSet node, FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperFieldFieldPostfixPrefix(node, field, field, operator, arg,
         isPrefix: true);
   }
 
   @override
-  R visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPostfix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperFieldSetterPostfixPrefix(
         node, field, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperFieldSetterPrefix(SendSet node, FieldElement field,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperFieldSetterPostfixPrefix(
         node, field, setter, operator, arg,
         isPrefix: true);
   }
 
   @override
-  R visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPostfix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperGetterFieldPostfixPrefix(
         node, getter, field, operator, arg,
@@ -8028,7 +8030,7 @@
   }
 
   @override
-  R visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
+  R visitSuperGetterFieldPrefix(SendSet node, GetterElement getter,
       FieldElement field, IncDecOperator operator, A arg) {
     return handleSuperGetterFieldPostfixPrefix(
         node, getter, field, operator, arg,
@@ -8036,32 +8038,32 @@
   }
 
   @override
-  R visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPostfix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperGetterSetterPrefix(SendSet node, GetterElement getter,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperGetterSetterPostfixPrefix(
         node, getter, setter, operator, arg,
         isPrefix: true);
   }
 
   @override
-  R visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPostfix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperMethodSetterPostfixPrefix(
         node, method, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, A arg) {
+  R visitSuperMethodSetterPrefix(SendSet node, FunctionElement method,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleSuperMethodSetterPostfixPrefix(
         node, method, setter, operator, arg,
         isPrefix: true);
@@ -8070,8 +8072,8 @@
   @override
   R visitSuperIndexPostfix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -8083,8 +8085,8 @@
   @override
   R visitSuperIndexPrefix(
       Send node,
-      FunctionElement indexFunction,
-      FunctionElement indexSetFunction,
+      MethodElement indexFunction,
+      MethodElement indexSetFunction,
       Node index,
       IncDecOperator operator,
       A arg) {
@@ -8094,7 +8096,7 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPostfix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperGetterIndexPostfixPrefix(
         node, element, setter, index, operator, arg,
@@ -8102,7 +8104,7 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
+  R visitUnresolvedSuperGetterIndexPrefix(SendSet node, Element element,
       MethodElement setter, Node index, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperGetterIndexPostfixPrefix(
         node, element, setter, index, operator, arg,
@@ -8111,7 +8113,7 @@
 
   @override
   R visitUnresolvedSuperSetterIndexPostfix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -8124,7 +8126,7 @@
 
   @override
   R visitUnresolvedSuperSetterIndexPrefix(
-      Send node,
+      SendSet node,
       MethodElement indexFunction,
       Element element,
       Node index,
@@ -8181,7 +8183,7 @@
 
   @override
   R visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, A arg) {
+      SendSet node, Element element, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperPostfixPrefix(node, element, operator, arg,
         isPrefix: false);
   }
@@ -8194,23 +8196,23 @@
   }
 
   @override
-  R visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPostfix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperGetterPostfixPrefix(
         node, element, setter, operator, arg,
         isPrefix: false);
   }
 
   @override
-  R visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, A arg) {
+  R visitUnresolvedSuperGetterPrefix(SendSet node, Element element,
+      SetterElement setter, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperGetterPostfixPrefix(
         node, element, setter, operator, arg,
         isPrefix: true);
   }
 
   @override
-  R visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPostfix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperSetterPostfixPrefix(
         node, getter, element, operator, arg,
@@ -8218,7 +8220,7 @@
   }
 
   @override
-  R visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
+  R visitUnresolvedSuperSetterPrefix(SendSet node, GetterElement getter,
       Element element, IncDecOperator operator, A arg) {
     return handleUnresolvedSuperSetterPostfixPrefix(
         node, getter, element, operator, arg,
@@ -8298,8 +8300,13 @@
   }
 
   @override
-  R visitUnresolvedClassConstructorInvoke(NewExpression node, Element element,
-      ResolutionDartType type, NodeList arguments, Selector selector, A arg) {
+  R visitUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      ErroneousElement element,
+      ResolutionDartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
     return handleConstructorInvoke(
         node, element, type, arguments, selector.callStructure, arg);
   }
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index fa8eb68..6ab2d06 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -20,7 +20,7 @@
 /// node.
 abstract class SemanticSendStructure<R, A> {
   /// Calls the matching visit method on [visitor] with [node] and [arg].
-  R dispatch(SemanticSendVisitor<R, A> visitor, Node node, A arg);
+  R dispatch(SemanticSendVisitor<R, A> visitor, covariant Node node, A arg);
 }
 
 enum SendStructureKind {
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 33dbfd8..ddc3528 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -35,7 +35,7 @@
   final Scope scope;
   final MessageKind defaultValuesError;
   final bool createRealParameters;
-  List<Element> optionalParameters = const <Element>[];
+  List<FormalElement> optionalParameters = const <FormalElement>[];
   int optionalParameterCount = 0;
   bool isOptionalParameter = false;
   bool optionalParametersAreNamed = false;
@@ -65,7 +65,7 @@
     }
     optionalParametersAreNamed = (identical(value, '{'));
     isOptionalParameter = true;
-    LinkBuilder<Element> elements = analyzeNodes(node.nodes);
+    LinkBuilder<FormalElement> elements = analyzeNodes(node.nodes);
     optionalParameterCount = elements.length;
     optionalParameters = elements.toList();
   }
@@ -252,7 +252,7 @@
   }
 
   /// A [SendSet] node is an optional parameter with a default value.
-  Element visitSendSet(SendSet node) {
+  FormalElementX visitSendSet(SendSet node) {
     FormalElementX element;
     if (node.receiver != null) {
       element = createFieldParameter(node, node.arguments.first);
@@ -267,7 +267,7 @@
     return element;
   }
 
-  Element visitFunctionExpression(FunctionExpression node) {
+  FormalElementX visitFunctionExpression(FunctionExpression node) {
     // This is a function typed parameter.
     Modifiers modifiers = currentDefinitions.modifiers;
     if (modifiers.isFinal) {
@@ -282,8 +282,8 @@
     return createParameter(node.name, null);
   }
 
-  LinkBuilder<Element> analyzeNodes(Link<Node> link) {
-    LinkBuilder<Element> elements = new LinkBuilder<Element>();
+  LinkBuilder<FormalElement> analyzeNodes(Link<Node> link) {
+    LinkBuilder<FormalElement> elements = new LinkBuilder<FormalElement>();
     for (; !link.isEmpty; link = link.tail) {
       Element element = link.head.accept(this);
       if (element != null) {
@@ -356,7 +356,7 @@
         resolution, element, scope, registry,
         defaultValuesError: defaultValuesError,
         createRealParameters: createRealParameters);
-    List<Element> parameters = const <Element>[];
+    List<FormalElement> parameters = const <FormalElement>[];
     int requiredParameterCount = 0;
     if (formalParameters == null) {
       if (!element.isGetter) {
@@ -380,7 +380,7 @@
               formalParameters, MessageKind.EXTRA_FORMALS);
         }
       }
-      LinkBuilder<Element> parametersBuilder =
+      LinkBuilder<FormalElement> parametersBuilder =
           visitor.analyzeNodes(formalParameters.nodes);
       requiredParameterCount = parametersBuilder.length;
       parameters = parametersBuilder.toList();
@@ -438,7 +438,7 @@
         const <ResolutionDartType>[];
     List<String> namedParameters = const <String>[];
     List<ResolutionDartType> namedParameterTypes = const <ResolutionDartType>[];
-    List<Element> orderedOptionalParameters =
+    List<FormalElement> orderedOptionalParameters =
         visitor.optionalParameters.toList();
     if (visitor.optionalParametersAreNamed) {
       // TODO(karlklose); replace when [visitor.optionalParameters] is a [List].
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index c4c6b5f..c68b64d 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -352,8 +352,9 @@
   }
 
   @override
-  Element getFunctionDefinition(FunctionExpression node) {
-    return this[node];
+  FunctionElement getFunctionDefinition(FunctionExpression node) {
+    Element e = this[node];
+    return e is FunctionElement ? e : null;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart
index 0c9ae42..3d45c9d 100644
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart
@@ -18,6 +18,7 @@
         TypedefElement,
         TypeVariableElement;
 import '../elements/modelx.dart' show ErroneousElementX;
+import '../elements/types.dart' show DartType, TypeVariableType;
 import '../resolution/resolution.dart';
 import '../tree/tree.dart';
 import '../universe/feature.dart' show Feature;
@@ -191,7 +192,8 @@
     assert(visibleTypeParameterNames != null);
 
     if (node.typeParameters != null) {
-      List<String> newTypeNames = node.typeParameters.map((TypeVariable node) {
+      List<String> newTypeNames = node.typeParameters.map((_node) {
+        TypeVariable node = _node;
         return node.name.asIdentifier().source;
       }).toList();
       visibleTypeParameterNames = visibleTypeParameterNames.toList()
@@ -409,8 +411,11 @@
 
   /// Checks the type arguments of [type] against the type variable bounds.
   void checkTypeVariableBounds(NominalTypeAnnotation node, GenericType type) {
-    void checkTypeVariableBound(_, ResolutionDartType typeArgument,
-        ResolutionTypeVariableType typeVariable, ResolutionDartType bound) {
+    void checkTypeVariableBound(_, DartType _typeArgument,
+        TypeVariableType _typeVariable, DartType _bound) {
+      ResolutionDartType typeArgument = _typeArgument;
+      ResolutionTypeVariableType typeVariable = _typeVariable;
+      ResolutionDartType bound = _bound;
       if (!types.isSubtype(typeArgument, bound)) {
         reporter.reportWarningMessage(
             node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, {
diff --git a/pkg/compiler/lib/src/serialization/constant_serialization.dart b/pkg/compiler/lib/src/serialization/constant_serialization.dart
index e598672..3239fe7 100644
--- a/pkg/compiler/lib/src/serialization/constant_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/constant_serialization.dart
@@ -8,6 +8,7 @@
 import '../constants/expressions.dart';
 import '../elements/elements.dart'
     show ConstructorElement, FieldElement, LocalVariableElement, MethodElement;
+import '../elements/entities.dart' show FieldEntity;
 import '../elements/operators.dart';
 import '../elements/resolution_types.dart';
 import '../universe/call_structure.dart' show CallStructure;
@@ -325,7 +326,8 @@
       defaults.setConstant('$key', e);
     });
     ListEncoder fields = encoder.createList(Key.FIELDS);
-    constructor.fieldMap.forEach((FieldElement f, ConstantExpression e) {
+    constructor.fieldMap.forEach((FieldEntity _f, ConstantExpression e) {
+      FieldElement f = _f;
       ObjectEncoder fieldSerializer = fields.createObject();
       fieldSerializer.setElement(Key.FIELD, f);
       fieldSerializer.setConstant(Key.CONSTANT, e);
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 0e5c562..5fa61a0 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -102,8 +102,8 @@
 
   /// Serializes [element] into the [encoder] using the [kind] computed
   /// by [getSerializedKind].
-  void serialize(
-      Element element, ObjectEncoder encoder, SerializedElementKind kind);
+  void serialize(covariant Element element, ObjectEncoder encoder,
+      SerializedElementKind kind);
 }
 
 class SerializerUtil {
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 09fc4a0..b161a2c 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -54,9 +54,9 @@
 bool areSetsEquivalent(Iterable set1, Iterable set2,
     [bool elementEquivalence(a, b) = equality]) {
   Set remaining = set2.toSet();
-  for (var element1 in set1) {
+  for (dynamic element1 in set1) {
     bool found = false;
-    for (var element2 in set2) {
+    for (dynamic element2 in set2) {
       if (elementEquivalence(element1, element2)) {
         found = true;
         remaining.remove(element2);
@@ -76,9 +76,9 @@
     [bool keyEquivalence(a, b) = equality,
     bool valueEquivalence(a, b) = equality]) {
   Set remaining = map2.keys.toSet();
-  for (var key1 in map1.keys) {
+  for (dynamic key1 in map1.keys) {
     bool found = false;
-    for (var key2 in map2.keys) {
+    for (dynamic key2 in map2.keys) {
       if (keyEquivalence(key1, key2)) {
         found = true;
         remaining.remove(key2);
@@ -103,6 +103,10 @@
       .visit(a, b);
 }
 
+bool areEntitiesEquivalent(Entity a, Entity b, {TestStrategy strategy}) {
+  return areElementsEquivalent(a, b, strategy: strategy);
+}
+
 /// Returns `true` if types [a] and [b] are equivalent.
 bool areTypesEquivalent(DartType a, DartType b, {TestStrategy strategy}) {
   if (identical(a, b)) return true;
@@ -265,8 +269,8 @@
   if (a == null || b == null) return false;
   if (a.kind != b.kind) return false;
 
-  var ad = a;
-  var bd = b;
+  dynamic ad = a;
+  dynamic bd = b;
   switch (a.kind) {
     case SendStructureKind.IF_NULL:
     case SendStructureKind.LOGICAL_AND:
@@ -322,8 +326,8 @@
   if (a == null || b == null) return false;
   if (a.kind != b.kind) return false;
 
-  var ad = a;
-  var bd = b;
+  dynamic ad = a;
+  dynamic bd = b;
   switch (a.kind) {
     case NewStructureKind.NEW_INVOKE:
       return ad.semantics.kind == bd.semantics.kind &&
@@ -356,7 +360,7 @@
   final Equivalence<ConstantValue> constantValueEquivalence;
 
   const TestStrategy(
-      {this.elementEquivalence: areElementsEquivalent,
+      {this.elementEquivalence: areEntitiesEquivalent,
       this.typeEquivalence: areTypesEquivalent,
       this.constantEquivalence: areConstantsEquivalent,
       this.constantValueEquivalence: areConstantValuesEquivalent});
@@ -364,7 +368,8 @@
   /// An equivalence [TestStrategy] that doesn't throw on inequivalence.
   TestStrategy get testOnly => this;
 
-  bool test(var object1, var object2, String property, var value1, var value2,
+  bool test(dynamic object1, dynamic object2, String property, dynamic value1,
+      dynamic value2,
       [bool equivalence(a, b) = equality]) {
     return equivalence(value1, value2);
   }
@@ -375,13 +380,14 @@
     return areListsEquivalent(list1, list2, elementEquivalence);
   }
 
-  bool testSets(
-      var object1, var object2, String property, Iterable set1, Iterable set2,
+  bool testSets(dynamic object1, dynamic object2, String property,
+      Iterable set1, Iterable set2,
       [bool elementEquivalence(a, b) = equality]) {
     return areSetsEquivalent(set1, set2, elementEquivalence);
   }
 
-  bool testMaps(var object1, var object2, String property, Map map1, Map map2,
+  bool testMaps(
+      dynamic object1, dynamic object2, String property, Map map1, Map map2,
       [bool keyEquivalence(a, b) = equality,
       bool valueEquivalence(a, b) = equality]) {
     return areMapsEquivalent(map1, map2, keyEquivalence, valueEquivalence);
@@ -463,21 +469,23 @@
   }
 
   @override
-  bool visitLibraryElement(LibraryElement element1, LibraryElement element2) {
+  bool visitLibraryElement(
+      LibraryElement element1, covariant LibraryElement element2) {
     return strategy.test(element1, element2, 'canonicalUri',
         element1.canonicalUri, element2.canonicalUri);
   }
 
   @override
-  bool visitCompilationUnitElement(
-      CompilationUnitElement element1, CompilationUnitElement element2) {
+  bool visitCompilationUnitElement(CompilationUnitElement element1,
+      covariant CompilationUnitElement element2) {
     return strategy.test(element1, element2, 'script.resourceUri',
             element1.script.resourceUri, element2.script.resourceUri) &&
         visit(element1.library, element2.library);
   }
 
   @override
-  bool visitClassElement(ClassElement element1, ClassElement element2) {
+  bool visitClassElement(
+      ClassElement element1, covariant ClassElement element2) {
     if (!strategy.test(
         element1,
         element2,
@@ -505,7 +513,7 @@
     }
   }
 
-  bool checkMembers(Element element1, Element element2) {
+  bool checkMembers(Element element1, covariant Element element2) {
     if (!strategy.test(
         element1, element2, 'name', element1.name, element2.name)) {
       return false;
@@ -518,13 +526,14 @@
   }
 
   @override
-  bool visitFieldElement(FieldElement element1, FieldElement element2) {
+  bool visitFieldElement(
+      FieldElement element1, covariant FieldElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
   bool visitBoxFieldElement(
-      BoxFieldElement element1, BoxFieldElement element2) {
+      BoxFieldElement element1, covariant BoxFieldElement element2) {
     return element1.box.name == element2.box.name &&
         visit(element1.box.executableContext, element2.box.executableContext) &&
         visit(element1.variableElement, element2.variableElement);
@@ -532,28 +541,31 @@
 
   @override
   bool visitConstructorElement(
-      ConstructorElement element1, ConstructorElement element2) {
+      ConstructorElement element1, covariant ConstructorElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
-  bool visitMethodElement(MethodElement element1, MethodElement element2) {
+  bool visitMethodElement(
+      covariant MethodElement element1, covariant MethodElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
-  bool visitGetterElement(GetterElement element1, GetterElement element2) {
+  bool visitGetterElement(
+      GetterElement element1, covariant GetterElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
-  bool visitSetterElement(SetterElement element1, SetterElement element2) {
+  bool visitSetterElement(
+      SetterElement element1, covariant SetterElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
   bool visitLocalFunctionElement(
-      LocalFunctionElement element1, LocalFunctionElement element2) {
+      LocalFunctionElement element1, covariant LocalFunctionElement element2) {
     // TODO(johnniwinther): Define an equivalence on locals.
     MemberElement member1 = element1.memberContext;
     MemberElement member2 = element2.memberContext;
@@ -564,7 +576,7 @@
 
   @override
   bool visitLocalVariableElement(
-      LocalVariableElement element1, LocalVariableElement element2) {
+      LocalVariableElement element1, covariant LocalVariableElement element2) {
     // TODO(johnniwinther): Define an equivalence on locals.
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
@@ -572,20 +584,21 @@
   }
 
   bool visitAbstractFieldElement(
-      AbstractFieldElement element1, AbstractFieldElement element2) {
+      AbstractFieldElement element1, covariant AbstractFieldElement element2) {
     return checkMembers(element1, element2);
   }
 
   @override
   bool visitTypeVariableElement(
-      TypeVariableElement element1, TypeVariableElement element2) {
+      TypeVariableElement element1, covariant TypeVariableElement element2) {
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
         visit(element1.typeDeclaration, element2.typeDeclaration);
   }
 
   @override
-  bool visitTypedefElement(TypedefElement element1, TypedefElement element2) {
+  bool visitTypedefElement(
+      TypedefElement element1, covariant TypedefElement element2) {
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
         visit(element1.library, element2.library);
@@ -593,26 +606,29 @@
 
   @override
   bool visitParameterElement(
-      ParameterElement element1, ParameterElement element2) {
+      ParameterElement element1, covariant ParameterElement element2) {
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
         visit(element1.functionDeclaration, element2.functionDeclaration);
   }
 
   @override
-  bool visitImportElement(ImportElement element1, ImportElement element2) {
+  bool visitImportElement(
+      ImportElement element1, covariant ImportElement element2) {
     return visit(element1.importedLibrary, element2.importedLibrary) &&
         visit(element1.library, element2.library);
   }
 
   @override
-  bool visitExportElement(ExportElement element1, ExportElement element2) {
+  bool visitExportElement(
+      ExportElement element1, covariant ExportElement element2) {
     return visit(element1.exportedLibrary, element2.exportedLibrary) &&
         visit(element1.library, element2.library);
   }
 
   @override
-  bool visitPrefixElement(PrefixElement element1, PrefixElement element2) {
+  bool visitPrefixElement(
+      PrefixElement element1, covariant PrefixElement element2) {
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
         visit(element1.library, element2.library);
@@ -620,14 +636,14 @@
 
   @override
   bool visitErroneousElement(
-      ErroneousElement element1, ErroneousElement element2) {
+      ErroneousElement element1, covariant ErroneousElement element2) {
     return strategy.test(element1, element2, 'messageKind',
         element1.messageKind, element2.messageKind);
   }
 
   @override
   bool visitWarnOnUseElement(
-      WarnOnUseElement element1, WarnOnUseElement element2) {
+      WarnOnUseElement element1, covariant WarnOnUseElement element2) {
     return strategy.testElements(element1, element2, 'wrappedElement',
         element1.wrappedElement, element2.wrappedElement);
   }
@@ -640,19 +656,20 @@
 
   const TypeEquivalence([this.strategy = const TestStrategy()]);
 
-  bool visit(ResolutionDartType type1, ResolutionDartType type2) {
+  bool visit(
+      covariant ResolutionDartType type1, covariant ResolutionDartType type2) {
     return strategy.test(type1, type2, 'kind', type1.kind, type2.kind) &&
         type1.accept(this, type2);
   }
 
   @override
-  bool visitDynamicType(
-          ResolutionDynamicType type, ResolutionDynamicType other) =>
+  bool visitDynamicType(covariant ResolutionDynamicType type,
+          covariant ResolutionDynamicType other) =>
       true;
 
   @override
-  bool visitFunctionType(
-      ResolutionFunctionType type, ResolutionFunctionType other) {
+  bool visitFunctionType(covariant ResolutionFunctionType type,
+      covariant ResolutionFunctionType other) {
     return strategy.testTypeLists(type, other, 'parameterTypes',
             type.parameterTypes, other.parameterTypes) &&
         strategy.testTypeLists(type, other, 'optionalParameterTypes',
@@ -671,11 +688,12 @@
   }
 
   @override
-  bool visitMalformedType(MalformedType type, MalformedType other) => true;
+  bool visitMalformedType(MalformedType type, covariant MalformedType other) =>
+      true;
 
   @override
-  bool visitTypeVariableType(
-      ResolutionTypeVariableType type, ResolutionTypeVariableType other) {
+  bool visitTypeVariableType(covariant ResolutionTypeVariableType type,
+      covariant ResolutionTypeVariableType other) {
     return strategy.testElements(
             type, other, 'element', type.element, other.element) &&
         strategy.test(type, other, 'is MethodTypeVariableType',
@@ -683,18 +701,19 @@
   }
 
   @override
-  bool visitVoidType(ResolutionVoidType type, ResolutionVoidType argument) =>
+  bool visitVoidType(covariant ResolutionVoidType type,
+          covariant ResolutionVoidType argument) =>
       true;
 
   @override
-  bool visitInterfaceType(
-      ResolutionInterfaceType type, ResolutionInterfaceType other) {
+  bool visitInterfaceType(covariant ResolutionInterfaceType type,
+      covariant ResolutionInterfaceType other) {
     return visitGenericType(type, other);
   }
 
   @override
   bool visitTypedefType(
-      ResolutionTypedefType type, ResolutionTypedefType other) {
+      ResolutionTypedefType type, covariant ResolutionTypedefType other) {
     return visitGenericType(type, other);
   }
 }
@@ -707,7 +726,7 @@
   const ConstantEquivalence([this.strategy = const TestStrategy()]);
 
   @override
-  bool visit(ConstantExpression exp1, ConstantExpression exp2) {
+  bool visit(ConstantExpression exp1, covariant ConstantExpression exp2) {
     if (identical(exp1, exp2)) return true;
     return strategy.test(exp1, exp2, 'kind', exp1.kind, exp2.kind) &&
         exp1.accept(this, exp2);
@@ -715,7 +734,7 @@
 
   @override
   bool visitBinary(
-      BinaryConstantExpression exp1, BinaryConstantExpression exp2) {
+      BinaryConstantExpression exp1, covariant BinaryConstantExpression exp2) {
     return strategy.test(
             exp1, exp2, 'operator', exp1.operator, exp2.operator) &&
         strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) &&
@@ -723,15 +742,15 @@
   }
 
   @override
-  bool visitConcatenate(
-      ConcatenateConstantExpression exp1, ConcatenateConstantExpression exp2) {
+  bool visitConcatenate(ConcatenateConstantExpression exp1,
+      covariant ConcatenateConstantExpression exp2) {
     return strategy.testConstantLists(
         exp1, exp2, 'expressions', exp1.expressions, exp2.expressions);
   }
 
   @override
-  bool visitConditional(
-      ConditionalConstantExpression exp1, ConditionalConstantExpression exp2) {
+  bool visitConditional(ConditionalConstantExpression exp1,
+      covariant ConditionalConstantExpression exp2) {
     return strategy.testConstants(
             exp1, exp2, 'condition', exp1.condition, exp2.condition) &&
         strategy.testConstants(
@@ -741,8 +760,8 @@
   }
 
   @override
-  bool visitConstructed(
-      ConstructedConstantExpression exp1, ConstructedConstantExpression exp2) {
+  bool visitConstructed(ConstructedConstantExpression exp1,
+      covariant ConstructedConstantExpression exp2) {
     return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) &&
         strategy.testElements(exp1, exp2, 'target', exp1.target, exp2.target) &&
         strategy.testConstantLists(
@@ -752,28 +771,30 @@
   }
 
   @override
-  bool visitFunction(
-      FunctionConstantExpression exp1, FunctionConstantExpression exp2) {
+  bool visitFunction(FunctionConstantExpression exp1,
+      covariant FunctionConstantExpression exp2) {
     return strategy.testElements(
         exp1, exp2, 'element', exp1.element, exp2.element);
   }
 
   @override
-  bool visitIdentical(
-      IdenticalConstantExpression exp1, IdenticalConstantExpression exp2) {
+  bool visitIdentical(IdenticalConstantExpression exp1,
+      covariant IdenticalConstantExpression exp2) {
     return strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) &&
         strategy.testConstants(exp1, exp2, 'right', exp1.right, exp2.right);
   }
 
   @override
-  bool visitList(ListConstantExpression exp1, ListConstantExpression exp2) {
+  bool visitList(
+      ListConstantExpression exp1, covariant ListConstantExpression exp2) {
     return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) &&
         strategy.testConstantLists(
             exp1, exp2, 'values', exp1.values, exp2.values);
   }
 
   @override
-  bool visitMap(MapConstantExpression exp1, MapConstantExpression exp2) {
+  bool visitMap(
+      MapConstantExpression exp1, covariant MapConstantExpression exp2) {
     return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) &&
         strategy.testConstantLists(exp1, exp2, 'keys', exp1.keys, exp2.keys) &&
         strategy.testConstantLists(
@@ -781,31 +802,34 @@
   }
 
   @override
-  bool visitNamed(NamedArgumentReference exp1, NamedArgumentReference exp2) {
+  bool visitNamed(
+      NamedArgumentReference exp1, covariant NamedArgumentReference exp2) {
     return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name);
   }
 
   @override
-  bool visitPositional(
-      PositionalArgumentReference exp1, PositionalArgumentReference exp2) {
+  bool visitPositional(PositionalArgumentReference exp1,
+      covariant PositionalArgumentReference exp2) {
     return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index);
   }
 
   @override
   bool visitSymbol(
-      SymbolConstantExpression exp1, SymbolConstantExpression exp2) {
+      SymbolConstantExpression exp1, covariant SymbolConstantExpression exp2) {
     // TODO(johnniwinther): Handle private names. Currently not even supported
     // in resolution.
     return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name);
   }
 
   @override
-  bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) {
+  bool visitType(
+      TypeConstantExpression exp1, covariant TypeConstantExpression exp2) {
     return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type);
   }
 
   @override
-  bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) {
+  bool visitUnary(
+      UnaryConstantExpression exp1, covariant UnaryConstantExpression exp2) {
     return strategy.test(
             exp1, exp2, 'operator', exp1.operator, exp2.operator) &&
         strategy.testConstants(
@@ -813,52 +837,56 @@
   }
 
   @override
-  bool visitField(FieldConstantExpression exp1, FieldConstantExpression exp2) {
+  bool visitField(
+      FieldConstantExpression exp1, covariant FieldConstantExpression exp2) {
     return strategy.testElements(
         exp1, exp2, 'element', exp1.element, exp2.element);
   }
 
   @override
   bool visitLocalVariable(LocalVariableConstantExpression exp1,
-      LocalVariableConstantExpression exp2) {
+      covariant LocalVariableConstantExpression exp2) {
     return strategy.testElements(
         exp1, exp2, 'element', exp1.element, exp2.element);
   }
 
   @override
-  bool visitBool(BoolConstantExpression exp1, BoolConstantExpression exp2) {
+  bool visitBool(
+      BoolConstantExpression exp1, covariant BoolConstantExpression exp2) {
     return strategy.test(
         exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue);
   }
 
   @override
   bool visitDouble(
-      DoubleConstantExpression exp1, DoubleConstantExpression exp2) {
+      DoubleConstantExpression exp1, covariant DoubleConstantExpression exp2) {
     return strategy.test(
         exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue);
   }
 
   @override
-  bool visitInt(IntConstantExpression exp1, IntConstantExpression exp2) {
+  bool visitInt(
+      IntConstantExpression exp1, covariant IntConstantExpression exp2) {
     return strategy.test(
         exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue);
   }
 
   @override
-  bool visitNull(NullConstantExpression exp1, NullConstantExpression exp2) {
+  bool visitNull(
+      NullConstantExpression exp1, covariant NullConstantExpression exp2) {
     return true;
   }
 
   @override
   bool visitString(
-      StringConstantExpression exp1, StringConstantExpression exp2) {
+      StringConstantExpression exp1, covariant StringConstantExpression exp2) {
     return strategy.test(
         exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue);
   }
 
   @override
   bool visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp1,
-      BoolFromEnvironmentConstantExpression exp2) {
+      covariant BoolFromEnvironmentConstantExpression exp2) {
     return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) &&
         strategy.testConstants(
             exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue);
@@ -866,7 +894,7 @@
 
   @override
   bool visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp1,
-      IntFromEnvironmentConstantExpression exp2) {
+      covariant IntFromEnvironmentConstantExpression exp2) {
     return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) &&
         strategy.testConstants(
             exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue);
@@ -874,7 +902,7 @@
 
   @override
   bool visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp1,
-      StringFromEnvironmentConstantExpression exp2) {
+      covariant StringFromEnvironmentConstantExpression exp2) {
     return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) &&
         strategy.testConstants(
             exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue);
@@ -882,14 +910,14 @@
 
   @override
   bool visitStringLength(StringLengthConstantExpression exp1,
-      StringLengthConstantExpression exp2) {
+      covariant StringLengthConstantExpression exp2) {
     return strategy.testConstants(
         exp1, exp2, 'expression', exp1.expression, exp2.expression);
   }
 
   @override
-  bool visitDeferred(
-      DeferredConstantExpression exp1, DeferredConstantExpression exp2) {
+  bool visitDeferred(DeferredConstantExpression exp1,
+      covariant DeferredConstantExpression exp2) {
     return strategy.testElements(
             exp1, exp2, 'prefix', exp1.prefix, exp2.prefix) &&
         strategy.testConstants(
@@ -904,15 +932,15 @@
 
   const ConstantValueEquivalence([this.strategy = const TestStrategy()]);
 
-  bool visit(ConstantValue value1, ConstantValue value2) {
+  bool visit(ConstantValue value1, covariant ConstantValue value2) {
     if (identical(value1, value2)) return true;
     return strategy.test(value1, value2, 'kind', value1.kind, value2.kind) &&
         value1.accept(this, value2);
   }
 
   @override
-  bool visitConstructed(
-      ConstructedConstantValue value1, ConstructedConstantValue value2) {
+  bool visitConstructed(ConstructedConstantValue value1,
+      covariant ConstructedConstantValue value2) {
     return strategy.testTypes(
             value1, value2, 'type', value1.type, value2.type) &&
         strategy.testMaps(
@@ -928,13 +956,13 @@
 
   @override
   bool visitFunction(
-      FunctionConstantValue value1, FunctionConstantValue value2) {
+      FunctionConstantValue value1, covariant FunctionConstantValue value2) {
     return strategy.testElements(
         value1, value2, 'element', value1.element, value2.element);
   }
 
   @override
-  bool visitList(ListConstantValue value1, ListConstantValue value2) {
+  bool visitList(ListConstantValue value1, covariant ListConstantValue value2) {
     return strategy.testTypes(
             value1, value2, 'type', value1.type, value2.type) &&
         strategy.testConstantValueLists(
@@ -942,7 +970,7 @@
   }
 
   @override
-  bool visitMap(MapConstantValue value1, MapConstantValue value2) {
+  bool visitMap(MapConstantValue value1, covariant MapConstantValue value2) {
     return strategy.testTypes(
             value1, value2, 'type', value1.type, value2.type) &&
         strategy.testConstantValueLists(
@@ -952,42 +980,44 @@
   }
 
   @override
-  bool visitType(TypeConstantValue value1, TypeConstantValue value2) {
+  bool visitType(TypeConstantValue value1, covariant TypeConstantValue value2) {
     return strategy.testTypes(value1, value2, 'type', value1.type, value2.type);
   }
 
   @override
-  bool visitBool(BoolConstantValue value1, BoolConstantValue value2) {
+  bool visitBool(BoolConstantValue value1, covariant BoolConstantValue value2) {
     return strategy.test(value1, value2, 'primitiveValue',
         value1.primitiveValue, value2.primitiveValue);
   }
 
   @override
-  bool visitDouble(DoubleConstantValue value1, DoubleConstantValue value2) {
+  bool visitDouble(
+      DoubleConstantValue value1, covariant DoubleConstantValue value2) {
     return strategy.test(value1, value2, 'primitiveValue',
         value1.primitiveValue, value2.primitiveValue);
   }
 
   @override
-  bool visitInt(IntConstantValue value1, IntConstantValue value2) {
+  bool visitInt(IntConstantValue value1, covariant IntConstantValue value2) {
     return strategy.test(value1, value2, 'primitiveValue',
         value1.primitiveValue, value2.primitiveValue);
   }
 
   @override
-  bool visitNull(NullConstantValue value1, NullConstantValue value2) {
+  bool visitNull(NullConstantValue value1, covariant NullConstantValue value2) {
     return true;
   }
 
   @override
-  bool visitString(StringConstantValue value1, StringConstantValue value2) {
+  bool visitString(
+      StringConstantValue value1, covariant StringConstantValue value2) {
     return strategy.test(value1, value2, 'primitiveValue',
         value1.primitiveValue, value2.primitiveValue);
   }
 
   @override
   bool visitDeferred(
-      DeferredConstantValue value1, DeferredConstantValue value2) {
+      DeferredConstantValue value1, covariant DeferredConstantValue value2) {
     return strategy.testElements(
             value1, value2, 'prefix', value1.prefix, value2.prefix) &&
         strategy.testConstantValues(
@@ -995,13 +1025,14 @@
   }
 
   @override
-  bool visitNonConstant(NonConstantValue value1, NonConstantValue value2) {
+  bool visitNonConstant(
+      NonConstantValue value1, covariant NonConstantValue value2) {
     return true;
   }
 
   @override
   bool visitSynthetic(
-      SyntheticConstantValue value1, SyntheticConstantValue value2) {
+      SyntheticConstantValue value1, covariant SyntheticConstantValue value2) {
     return strategy.test(
             value1, value2, 'payload', value1.payload, value2.payload) &&
         strategy.test(
@@ -1009,8 +1040,8 @@
   }
 
   @override
-  bool visitInterceptor(
-      InterceptorConstantValue value1, InterceptorConstantValue value2) {
+  bool visitInterceptor(InterceptorConstantValue value1,
+      covariant InterceptorConstantValue value2) {
     return strategy.testElements(value1, value2, 'cls', value1.cls, value2.cls);
   }
 }
@@ -1103,8 +1134,8 @@
     FunctionElement element1 = resolvedAst1.element;
     FunctionElement element2 = resolvedAst2.element;
     for (int index = 0; index < element1.parameters.length; index++) {
-      var parameter1 = element1.parameters[index];
-      var parameter2 = element2.parameters[index];
+      dynamic parameter1 = element1.parameters[index];
+      dynamic parameter2 = element2.parameters[index];
       result = result &&
           strategy.testNodes(parameter1, parameter2, 'node',
               parameter1.implementation.node, parameter2.implementation.node) &&
@@ -1405,8 +1436,8 @@
 
   const NodeEquivalenceVisitor([this.strategy = const TestStrategy()]);
 
-  bool testNodes(
-      var object1, var object2, String property, Node node1, Node node2) {
+  bool testNodes(dynamic object1, dynamic object2, String property, Node node1,
+      Node node2) {
     return strategy.test(object1, object2, property, node1, node2,
         (Node n1, Node n2) {
       if (n1 == n2) return true;
@@ -1415,7 +1446,7 @@
     });
   }
 
-  bool testNodeLists(var object1, var object2, String property,
+  bool testNodeLists(dynamic object1, dynamic object2, String property,
       Link<Node> list1, Link<Node> list2) {
     return strategy.test(object1, object2, property, list1, list2,
         (Link<Node> l1, Link<Node> l2) {
@@ -1432,8 +1463,8 @@
     });
   }
 
-  bool testTokens(
-      var object1, var object2, String property, Token token1, Token token2) {
+  bool testTokens(dynamic object1, dynamic object2, String property,
+      Token token1, Token token2) {
     return strategy.test(object1, object2, property, token1, token2,
         (Token t1, Token t2) {
       if (t1 == t2) return true;
@@ -1446,7 +1477,7 @@
   }
 
   @override
-  bool visitAssert(Assert node1, Assert node2) {
+  bool visitAssert(Assert node1, covariant Assert node2) {
     return testTokens(node1, node2, 'assertToken', node1.assertToken,
             node2.assertToken) &&
         testNodes(
@@ -1455,21 +1486,21 @@
   }
 
   @override
-  bool visitAsyncForIn(AsyncForIn node1, AsyncForIn node2) {
+  bool visitAsyncForIn(AsyncForIn node1, covariant AsyncForIn node2) {
     return visitForIn(node1, node2) &&
         testTokens(
             node1, node2, 'awaitToken', node1.awaitToken, node2.awaitToken);
   }
 
   @override
-  bool visitAsyncModifier(AsyncModifier node1, AsyncModifier node2) {
+  bool visitAsyncModifier(AsyncModifier node1, covariant AsyncModifier node2) {
     return testTokens(
             node1, node2, 'asyncToken', node1.asyncToken, node2.asyncToken) &&
         testTokens(node1, node2, 'starToken', node1.starToken, node2.starToken);
   }
 
   @override
-  bool visitAwait(Await node1, Await node2) {
+  bool visitAwait(Await node1, covariant Await node2) {
     return testTokens(
             node1, node2, 'awaitToken', node1.awaitToken, node2.awaitToken) &&
         testNodes(
@@ -1477,26 +1508,28 @@
   }
 
   @override
-  bool visitBlock(Block node1, Block node2) {
+  bool visitBlock(Block node1, covariant Block node2) {
     return testNodes(
         node1, node2, 'statements', node1.statements, node2.statements);
   }
 
   @override
-  bool visitBreakStatement(BreakStatement node1, BreakStatement node2) {
+  bool visitBreakStatement(
+      BreakStatement node1, covariant BreakStatement node2) {
     return testTokens(node1, node2, 'keywordToken', node1.keywordToken,
             node2.keywordToken) &&
         testNodes(node1, node2, 'target', node1.target, node2.target);
   }
 
   @override
-  bool visitCascade(Cascade node1, Cascade node2) {
+  bool visitCascade(Cascade node1, covariant Cascade node2) {
     return testNodes(
         node1, node2, 'expression', node1.expression, node2.expression);
   }
 
   @override
-  bool visitCascadeReceiver(CascadeReceiver node1, CascadeReceiver node2) {
+  bool visitCascadeReceiver(
+      CascadeReceiver node1, covariant CascadeReceiver node2) {
     return testTokens(node1, node2, 'cascadeOperator', node1.cascadeOperator,
             node2.cascadeOperator) &&
         testNodes(
@@ -1504,7 +1537,7 @@
   }
 
   @override
-  bool visitCaseMatch(CaseMatch node1, CaseMatch node2) {
+  bool visitCaseMatch(CaseMatch node1, covariant CaseMatch node2) {
     return testTokens(node1, node2, 'caseKeyword', node1.caseKeyword,
             node2.caseKeyword) &&
         testNodes(
@@ -1512,7 +1545,7 @@
   }
 
   @override
-  bool visitCatchBlock(CatchBlock node1, CatchBlock node2) {
+  bool visitCatchBlock(CatchBlock node1, covariant CatchBlock node2) {
     return testTokens(node1, node2, 'catchKeyword', node1.catchKeyword,
             node2.catchKeyword) &&
         testTokens(
@@ -1523,7 +1556,7 @@
   }
 
   @override
-  bool visitClassNode(ClassNode node1, ClassNode node2) {
+  bool visitClassNode(ClassNode node1, covariant ClassNode node2) {
     return testTokens(
             node1, node2, 'beginToken', node1.beginToken, node2.beginToken) &&
         testTokens(node1, node2, 'extendsKeyword', node1.extendsKeyword,
@@ -1542,7 +1575,7 @@
   }
 
   @override
-  bool visitCombinator(Combinator node1, Combinator node2) {
+  bool visitCombinator(Combinator node1, covariant Combinator node2) {
     return testTokens(node1, node2, 'keywordToken', node1.keywordToken,
             node2.keywordToken) &&
         testNodes(
@@ -1550,7 +1583,7 @@
   }
 
   @override
-  bool visitConditional(Conditional node1, Conditional node2) {
+  bool visitConditional(Conditional node1, covariant Conditional node2) {
     return testTokens(node1, node2, 'questionToken', node1.questionToken,
             node2.questionToken) &&
         testTokens(
@@ -1564,7 +1597,8 @@
   }
 
   @override
-  bool visitConditionalUri(ConditionalUri node1, ConditionalUri node2) {
+  bool visitConditionalUri(
+      ConditionalUri node1, covariant ConditionalUri node2) {
     return testTokens(node1, node2, 'ifToken', node1.ifToken, node2.ifToken) &&
         testNodes(node1, node2, 'key', node1.key, node2.key) &&
         testNodes(node1, node2, 'value', node1.value, node2.value) &&
@@ -1573,14 +1607,14 @@
 
   @override
   bool visitContinueStatement(
-      ContinueStatement node1, ContinueStatement node2) {
+      ContinueStatement node1, covariant ContinueStatement node2) {
     return testTokens(node1, node2, 'keywordToken', node1.keywordToken,
             node2.keywordToken) &&
         testNodes(node1, node2, 'target', node1.target, node2.target);
   }
 
   @override
-  bool visitDoWhile(DoWhile node1, DoWhile node2) {
+  bool visitDoWhile(DoWhile node1, covariant DoWhile node2) {
     return testTokens(
             node1, node2, 'doKeyword', node1.doKeyword, node2.doKeyword) &&
         testTokens(node1, node2, 'whileKeyword', node1.whileKeyword,
@@ -1592,20 +1626,21 @@
   }
 
   @override
-  bool visitDottedName(DottedName node1, DottedName node2) {
+  bool visitDottedName(DottedName node1, covariant DottedName node2) {
     return testTokens(node1, node2, 'token', node1.token, node2.token) &&
         testNodes(
             node1, node2, 'identifiers', node1.identifiers, node2.identifiers);
   }
 
   @override
-  bool visitEmptyStatement(EmptyStatement node1, EmptyStatement node2) {
+  bool visitEmptyStatement(
+      EmptyStatement node1, covariant EmptyStatement node2) {
     return testTokens(node1, node2, 'semicolonToken', node1.semicolonToken,
         node2.semicolonToken);
   }
 
   @override
-  bool visitEnum(Enum node1, Enum node2) {
+  bool visitEnum(Enum node1, covariant Enum node2) {
     return testTokens(
             node1, node2, 'enumToken', node1.enumToken, node2.enumToken) &&
         testNodes(node1, node2, 'name', node1.name, node2.name) &&
@@ -1613,7 +1648,7 @@
   }
 
   @override
-  bool visitExport(Export node1, Export node2) {
+  bool visitExport(Export node1, covariant Export node2) {
     return visitLibraryDependency(node1, node2) &&
         testTokens(node1, node2, 'exportKeyword', node1.exportKeyword,
             node2.exportKeyword);
@@ -1621,7 +1656,7 @@
 
   @override
   bool visitExpressionStatement(
-      ExpressionStatement node1, ExpressionStatement node2) {
+      ExpressionStatement node1, covariant ExpressionStatement node2) {
     return testTokens(
             node1, node2, 'endToken', node1.endToken, node2.endToken) &&
         testNodes(
@@ -1629,7 +1664,7 @@
   }
 
   @override
-  bool visitFor(For node1, For node2) {
+  bool visitFor(For node1, covariant For node2) {
     return testTokens(
             node1, node2, 'forToken', node1.forToken, node2.forToken) &&
         testNodes(node1, node2, 'initializer', node1.initializer,
@@ -1641,7 +1676,7 @@
   }
 
   @override
-  bool visitForIn(ForIn node1, ForIn node2) {
+  bool visitForIn(ForIn node1, covariant ForIn node2) {
     return testNodes(
             node1, node2, 'condition', node1.condition, node2.condition) &&
         testNodes(
@@ -1653,13 +1688,13 @@
 
   @override
   bool visitFunctionDeclaration(
-      FunctionDeclaration node1, FunctionDeclaration node2) {
+      FunctionDeclaration node1, covariant FunctionDeclaration node2) {
     return testNodes(node1, node2, 'function', node1.function, node2.function);
   }
 
   @override
   bool visitFunctionExpression(
-      FunctionExpression node1, FunctionExpression node2) {
+      FunctionExpression node1, covariant FunctionExpression node2) {
     return testTokens(
             node1, node2, 'getOrSet', node1.getOrSet, node2.getOrSet) &&
         testNodes(node1, node2, 'name', node1.name, node2.name) &&
@@ -1677,7 +1712,7 @@
   }
 
   @override
-  bool visitGotoStatement(GotoStatement node1, GotoStatement node2) {
+  bool visitGotoStatement(GotoStatement node1, covariant GotoStatement node2) {
     return testTokens(node1, node2, 'keywordToken', node1.keywordToken,
             node2.keywordToken) &&
         testTokens(node1, node2, 'semicolonToken', node1.semicolonToken,
@@ -1686,12 +1721,12 @@
   }
 
   @override
-  bool visitIdentifier(Identifier node1, Identifier node2) {
+  bool visitIdentifier(Identifier node1, covariant Identifier node2) {
     return testTokens(node1, node2, 'token', node1.token, node2.token);
   }
 
   @override
-  bool visitIf(If node1, If node2) {
+  bool visitIf(If node1, covariant If node2) {
     return testTokens(node1, node2, 'ifToken', node1.ifToken, node2.ifToken) &&
         testTokens(
             node1, node2, 'elseToken', node1.elseToken, node2.elseToken) &&
@@ -1702,7 +1737,7 @@
   }
 
   @override
-  bool visitImport(Import node1, Import node2) {
+  bool visitImport(Import node1, covariant Import node2) {
     return visitLibraryDependency(node1, node2) &&
         testTokens(node1, node2, 'importKeyword', node1.importKeyword,
             node2.importKeyword) &&
@@ -1712,7 +1747,7 @@
   }
 
   @override
-  bool visitLabel(Label node1, Label node2) {
+  bool visitLabel(Label node1, covariant Label node2) {
     return testTokens(
             node1, node2, 'colonToken', node1.colonToken, node2.colonToken) &&
         testNodes(
@@ -1720,14 +1755,15 @@
   }
 
   @override
-  bool visitLabeledStatement(LabeledStatement node1, LabeledStatement node2) {
+  bool visitLabeledStatement(
+      LabeledStatement node1, covariant LabeledStatement node2) {
     return testNodes(node1, node2, 'labels', node1.labels, node2.labels) &&
         testNodes(node1, node2, 'statement', node1.statement, node2.statement);
   }
 
   @override
   bool visitLibraryDependency(
-      LibraryDependency node1, LibraryDependency node2) {
+      LibraryDependency node1, covariant LibraryDependency node2) {
     return visitLibraryTag(node1, node2) &&
         testNodes(node1, node2, 'uri', node1.uri, node2.uri) &&
         testNodes(node1, node2, 'conditionalUris', node1.conditionalUris,
@@ -1737,7 +1773,7 @@
   }
 
   @override
-  bool visitLibraryName(LibraryName node1, LibraryName node2) {
+  bool visitLibraryName(LibraryName node1, covariant LibraryName node2) {
     return visitLibraryTag(node1, node2) &&
         testTokens(node1, node2, 'libraryKeyword', node1.libraryKeyword,
             node2.libraryKeyword) &&
@@ -1745,33 +1781,33 @@
   }
 
   @override
-  bool visitLibraryTag(LibraryTag node1, LibraryTag node2) {
+  bool visitLibraryTag(LibraryTag node1, covariant LibraryTag node2) {
     // TODO(johnniwinther): Check metadata?
     return true;
   }
 
   @override
-  bool visitLiteral(Literal node1, Literal node2) {
+  bool visitLiteral(Literal node1, covariant Literal node2) {
     return testTokens(node1, node2, 'token', node1.token, node2.token);
   }
 
   @override
-  bool visitLiteralBool(LiteralBool node1, LiteralBool node2) {
+  bool visitLiteralBool(LiteralBool node1, covariant LiteralBool node2) {
     return visitLiteral(node1, node2);
   }
 
   @override
-  bool visitLiteralDouble(LiteralDouble node1, LiteralDouble node2) {
+  bool visitLiteralDouble(LiteralDouble node1, covariant LiteralDouble node2) {
     return visitLiteral(node1, node2);
   }
 
   @override
-  bool visitLiteralInt(LiteralInt node1, LiteralInt node2) {
+  bool visitLiteralInt(LiteralInt node1, covariant LiteralInt node2) {
     return visitLiteral(node1, node2);
   }
 
   @override
-  bool visitLiteralList(LiteralList node1, LiteralList node2) {
+  bool visitLiteralList(LiteralList node1, covariant LiteralList node2) {
     return testTokens(node1, node2, 'constKeyword', node1.constKeyword,
             node2.constKeyword) &&
         testNodes(node1, node2, 'typeArguments', node1.typeArguments,
@@ -1780,7 +1816,7 @@
   }
 
   @override
-  bool visitLiteralMap(LiteralMap node1, LiteralMap node2) {
+  bool visitLiteralMap(LiteralMap node1, covariant LiteralMap node2) {
     return testTokens(node1, node2, 'constKeyword', node1.constKeyword,
             node2.constKeyword) &&
         testNodes(node1, node2, 'typeArguments', node1.typeArguments,
@@ -1789,7 +1825,8 @@
   }
 
   @override
-  bool visitLiteralMapEntry(LiteralMapEntry node1, LiteralMapEntry node2) {
+  bool visitLiteralMapEntry(
+      LiteralMapEntry node1, covariant LiteralMapEntry node2) {
     return testTokens(
             node1, node2, 'colonToken', node1.colonToken, node2.colonToken) &&
         testNodes(node1, node2, 'key', node1.key, node2.key) &&
@@ -1797,19 +1834,19 @@
   }
 
   @override
-  bool visitLiteralNull(LiteralNull node1, LiteralNull node2) {
+  bool visitLiteralNull(LiteralNull node1, covariant LiteralNull node2) {
     return visitLiteral(node1, node2);
   }
 
   @override
-  bool visitLiteralString(LiteralString node1, LiteralString node2) {
+  bool visitLiteralString(LiteralString node1, covariant LiteralString node2) {
     return testTokens(node1, node2, 'token', node1.token, node2.token) &&
         strategy.test(
             node1, node2, 'dartString', node1.dartString, node2.dartString);
   }
 
   @override
-  bool visitLiteralSymbol(LiteralSymbol node1, LiteralSymbol node2) {
+  bool visitLiteralSymbol(LiteralSymbol node1, covariant LiteralSymbol node2) {
     return testTokens(
             node1, node2, 'hashToken', node1.hashToken, node2.hashToken) &&
         testNodes(
@@ -1817,34 +1854,35 @@
   }
 
   @override
-  bool visitLoop(Loop node1, Loop node2) {
+  bool visitLoop(Loop node1, covariant Loop node2) {
     return testNodes(
             node1, node2, 'condition', node1.condition, node2.condition) &&
         testNodes(node1, node2, 'body', node1.body, node2.body);
   }
 
   @override
-  bool visitMetadata(Metadata node1, Metadata node2) {
+  bool visitMetadata(Metadata node1, covariant Metadata node2) {
     return testTokens(node1, node2, 'token', node1.token, node2.token) &&
         testNodes(
             node1, node2, 'expression', node1.expression, node2.expression);
   }
 
   @override
-  bool visitMixinApplication(MixinApplication node1, MixinApplication node2) {
+  bool visitMixinApplication(
+      MixinApplication node1, covariant MixinApplication node2) {
     return testNodes(
             node1, node2, 'superclass', node1.superclass, node2.superclass) &&
         testNodes(node1, node2, 'mixins', node1.mixins, node2.mixins);
   }
 
   @override
-  bool visitModifiers(Modifiers node1, Modifiers node2) {
+  bool visitModifiers(Modifiers node1, covariant Modifiers node2) {
     return strategy.test(node1, node2, 'flags', node1.flags, node2.flags) &&
         testNodes(node1, node2, 'nodes', node1.nodes, node2.nodes);
   }
 
   @override
-  bool visitNamedArgument(NamedArgument node1, NamedArgument node2) {
+  bool visitNamedArgument(NamedArgument node1, covariant NamedArgument node2) {
     return testTokens(
             node1, node2, 'colonToken', node1.colonToken, node2.colonToken) &&
         testNodes(node1, node2, 'name', node1.name, node2.name) &&
@@ -1854,7 +1892,7 @@
 
   @override
   bool visitNamedMixinApplication(
-      NamedMixinApplication node1, NamedMixinApplication node2) {
+      NamedMixinApplication node1, covariant NamedMixinApplication node2) {
     return testTokens(node1, node2, 'classKeyword', node1.classKeyword,
             node2.classKeyword) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -1870,14 +1908,14 @@
   }
 
   @override
-  bool visitNewExpression(NewExpression node1, NewExpression node2) {
+  bool visitNewExpression(NewExpression node1, covariant NewExpression node2) {
     return testTokens(
             node1, node2, 'newToken', node1.newToken, node2.newToken) &&
         testNodes(node1, node2, 'send', node1.send, node2.send);
   }
 
   @override
-  bool visitNodeList(NodeList node1, NodeList node2) {
+  bool visitNodeList(NodeList node1, covariant NodeList node2) {
     return testTokens(
             node1, node2, 'beginToken', node1.beginToken, node2.beginToken) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -1887,13 +1925,13 @@
   }
 
   @override
-  bool visitOperator(Operator node1, Operator node2) {
+  bool visitOperator(Operator node1, covariant Operator node2) {
     return visitIdentifier(node1, node2);
   }
 
   @override
   bool visitParenthesizedExpression(
-      ParenthesizedExpression node1, ParenthesizedExpression node2) {
+      ParenthesizedExpression node1, covariant ParenthesizedExpression node2) {
     return testTokens(
             node1, node2, 'beginToken', node1.beginToken, node2.beginToken) &&
         testNodes(
@@ -1901,7 +1939,7 @@
   }
 
   @override
-  bool visitPart(Part node1, Part node2) {
+  bool visitPart(Part node1, covariant Part node2) {
     return visitLibraryTag(node1, node2) &&
         testTokens(node1, node2, 'partKeyword', node1.partKeyword,
             node2.partKeyword) &&
@@ -1909,7 +1947,7 @@
   }
 
   @override
-  bool visitPartOf(PartOf node1, PartOf node2) {
+  bool visitPartOf(PartOf node1, covariant PartOf node2) {
     // TODO(johnniwinther): Check metadata?
     return testTokens(node1, node2, 'partKeyword', node1.partKeyword,
             node2.partKeyword) &&
@@ -1917,18 +1955,18 @@
   }
 
   @override
-  bool visitPostfix(Postfix node1, Postfix node2) {
+  bool visitPostfix(Postfix node1, covariant Postfix node2) {
     return visitNodeList(node1, node2);
   }
 
   @override
-  bool visitPrefix(Prefix node1, Prefix node2) {
+  bool visitPrefix(Prefix node1, covariant Prefix node2) {
     return visitNodeList(node1, node2);
   }
 
   @override
   bool visitRedirectingFactoryBody(
-      RedirectingFactoryBody node1, RedirectingFactoryBody node2) {
+      RedirectingFactoryBody node1, covariant RedirectingFactoryBody node2) {
     return testTokens(
             node1, node2, 'beginToken', node1.beginToken, node2.beginToken) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -1937,14 +1975,14 @@
   }
 
   @override
-  bool visitRethrow(Rethrow node1, Rethrow node2) {
+  bool visitRethrow(Rethrow node1, covariant Rethrow node2) {
     return testTokens(
             node1, node2, 'throwToken', node1.throwToken, node2.throwToken) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken);
   }
 
   @override
-  bool visitReturn(Return node1, Return node2) {
+  bool visitReturn(Return node1, covariant Return node2) {
     return testTokens(
             node1, node2, 'beginToken', node1.beginToken, node2.beginToken) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -1953,7 +1991,7 @@
   }
 
   @override
-  bool visitSend(Send node1, Send node2) {
+  bool visitSend(Send node1, covariant Send node2) {
     return strategy.test(node1, node2, 'isConditional', node1.isConditional,
             node2.isConditional) &&
         testNodes(node1, node2, 'receiver', node1.receiver, node2.receiver) &&
@@ -1963,7 +2001,7 @@
   }
 
   @override
-  bool visitSendSet(SendSet node1, SendSet node2) {
+  bool visitSendSet(SendSet node1, covariant SendSet node2) {
     return visitSend(node1, node2) &&
         testNodes(node1, node2, 'assignmentOperator', node1.assignmentOperator,
             node2.assignmentOperator);
@@ -1971,27 +2009,27 @@
 
   @override
   bool visitStringInterpolation(
-      StringInterpolation node1, StringInterpolation node2) {
+      StringInterpolation node1, covariant StringInterpolation node2) {
     return testNodes(node1, node2, 'string', node1.string, node2.string) &&
         testNodes(node1, node2, 'parts', node1.parts, node2.parts);
   }
 
   @override
   bool visitStringInterpolationPart(
-      StringInterpolationPart node1, StringInterpolationPart node2) {
+      StringInterpolationPart node1, covariant StringInterpolationPart node2) {
     return testNodes(
         node1, node2, 'expression', node1.expression, node2.expression);
   }
 
   @override
   bool visitStringJuxtaposition(
-      StringJuxtaposition node1, StringJuxtaposition node2) {
+      StringJuxtaposition node1, covariant StringJuxtaposition node2) {
     return testNodes(node1, node2, 'first', node1.first, node2.first) &&
         testNodes(node1, node2, 'second', node1.second, node2.second);
   }
 
   @override
-  bool visitSwitchCase(SwitchCase node1, SwitchCase node2) {
+  bool visitSwitchCase(SwitchCase node1, covariant SwitchCase node2) {
     return testTokens(node1, node2, 'defaultKeyword', node1.defaultKeyword,
             node2.defaultKeyword) &&
         testTokens(
@@ -2003,7 +2041,8 @@
   }
 
   @override
-  bool visitSwitchStatement(SwitchStatement node1, SwitchStatement node2) {
+  bool visitSwitchStatement(
+      SwitchStatement node1, covariant SwitchStatement node2) {
     return testTokens(node1, node2, 'switchKeyword', node1.switchKeyword,
             node2.switchKeyword) &&
         testNodes(node1, node2, 'parenthesizedExpression',
@@ -2012,12 +2051,12 @@
   }
 
   @override
-  bool visitSyncForIn(SyncForIn node1, SyncForIn node2) {
+  bool visitSyncForIn(SyncForIn node1, covariant SyncForIn node2) {
     return visitForIn(node1, node2);
   }
 
   @override
-  bool visitThrow(Throw node1, Throw node2) {
+  bool visitThrow(Throw node1, covariant Throw node2) {
     return testTokens(
             node1, node2, 'throwToken', node1.throwToken, node2.throwToken) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -2026,7 +2065,7 @@
   }
 
   @override
-  bool visitTryStatement(TryStatement node1, TryStatement node2) {
+  bool visitTryStatement(TryStatement node1, covariant TryStatement node2) {
     return testTokens(
             node1, node2, 'tryKeyword', node1.tryKeyword, node2.tryKeyword) &&
         testTokens(node1, node2, 'finallyKeyword', node1.finallyKeyword,
@@ -2040,7 +2079,7 @@
 
   @override
   bool visitNominalTypeAnnotation(
-      NominalTypeAnnotation node1, NominalTypeAnnotation node2) {
+      NominalTypeAnnotation node1, covariant NominalTypeAnnotation node2) {
     return testNodes(
             node1, node2, 'typeName', node1.typeName, node2.typeName) &&
         testNodes(node1, node2, 'typeArguments', node1.typeArguments,
@@ -2049,7 +2088,7 @@
 
   @override
   bool visitFunctionTypeAnnotation(
-      FunctionTypeAnnotation node1, FunctionTypeAnnotation node2) {
+      FunctionTypeAnnotation node1, covariant FunctionTypeAnnotation node2) {
     return testNodes(
             node1, node2, 'returnType', node1.returnType, node2.returnType) &&
         testNodes(node1, node2, 'formals', node1.formals, node2.formals) &&
@@ -2058,13 +2097,13 @@
   }
 
   @override
-  bool visitTypeVariable(TypeVariable node1, TypeVariable node2) {
+  bool visitTypeVariable(TypeVariable node1, covariant TypeVariable node2) {
     return testNodes(node1, node2, 'name', node1.name, node2.name) &&
         testNodes(node1, node2, 'bound', node1.bound, node2.bound);
   }
 
   @override
-  bool visitTypedef(Typedef node1, Typedef node2) {
+  bool visitTypedef(Typedef node1, covariant Typedef node2) {
     return testTokens(node1, node2, 'typedefKeyword', node1.typedefKeyword,
             node2.typedefKeyword) &&
         testTokens(node1, node2, 'endToken', node1.endToken, node2.endToken) &&
@@ -2078,7 +2117,7 @@
 
   @override
   bool visitVariableDefinitions(
-      VariableDefinitions node1, VariableDefinitions node2) {
+      VariableDefinitions node1, covariant VariableDefinitions node2) {
     return testNodes(
             node1, node2, 'metadata', node1.metadata, node2.metadata) &&
         testNodes(node1, node2, 'type', node1.type, node2.type) &&
@@ -2089,7 +2128,7 @@
   }
 
   @override
-  bool visitWhile(While node1, While node2) {
+  bool visitWhile(While node1, covariant While node2) {
     return testTokens(node1, node2, 'whileKeyword', node1.whileKeyword,
             node2.whileKeyword) &&
         testNodes(
@@ -2098,7 +2137,7 @@
   }
 
   @override
-  bool visitYield(Yield node1, Yield node2) {
+  bool visitYield(Yield node1, covariant Yield node2) {
     return testTokens(
             node1, node2, 'yieldToken', node1.yieldToken, node2.yieldToken) &&
         testTokens(
@@ -2109,27 +2148,28 @@
   }
 
   @override
-  bool visitNode(Node node1, Node node2) {
+  bool visitNode(Node node1, covariant Node node2) {
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 
   @override
-  bool visitExpression(Expression node1, Expression node2) {
+  bool visitExpression(Expression node1, covariant Expression node2) {
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 
   @override
-  bool visitStatement(Statement node1, Statement node2) {
+  bool visitStatement(Statement node1, covariant Statement node2) {
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 
   @override
-  bool visitStringNode(StringNode node1, StringNode node2) {
+  bool visitStringNode(StringNode node1, covariant StringNode node2) {
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 
   @override
-  bool visitTypeAnnotation(TypeAnnotation node1, TypeAnnotation node2) {
+  bool visitTypeAnnotation(
+      TypeAnnotation node1, covariant TypeAnnotation node2) {
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 }
diff --git a/pkg/compiler/lib/src/serialization/json_serializer.dart b/pkg/compiler/lib/src/serialization/json_serializer.dart
index ba995bd..b075e5b 100644
--- a/pkg/compiler/lib/src/serialization/json_serializer.dart
+++ b/pkg/compiler/lib/src/serialization/json_serializer.dart
@@ -108,7 +108,7 @@
 }
 
 /// [ValueVisitor] that generates a verbose JSON-like output.
-class PrettyPrintEncoder implements ValueVisitor {
+class PrettyPrintEncoder implements ValueVisitor<dynamic, String> {
   StringBuffer buffer;
 
   String toText(Value value) {
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 13d4ba6..d96bcf9 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -276,7 +276,8 @@
   TreeElements get treeElements => _unsupported('treeElements');
 }
 
-abstract class AstElementMixinZ implements AstElement, ElementZ {
+abstract class AstElementMixinZ<N extends Node>
+    implements AstElement, ElementZ {
   ResolvedAst _resolvedAst;
 
   // TODO(johnniwinther): This is needed for the token invariant assertion. Find
@@ -288,7 +289,7 @@
   bool get hasResolvedAst => _resolvedAst != null;
 
   @override
-  get node => _unsupported('node');
+  N get node => _unsupported('node');
 
   @override
   ResolvedAst get resolvedAst {
@@ -399,6 +400,7 @@
   bool get isTopLevel => _canonicalElement.isTopLevel;
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class LibraryElementZ extends DeserializedElementZ
     with AnalyzableElementMixin, ContainerMixin, LibraryElementCommon
     implements LibraryElement {
@@ -760,11 +762,12 @@
   bool get isClassMember => true;
 }
 
-abstract class TypedElementMixin implements DeserializedElementZ, TypedElement {
-  ResolutionDartType _type;
+abstract class TypedElementMixin<T extends ResolutionDartType>
+    implements DeserializedElementZ, TypedElement {
+  T _type;
 
   @override
-  ResolutionDartType get type {
+  T get type {
     if (_type == null) {
       _type = _decoder.getType(Key.TYPE);
     }
@@ -772,7 +775,7 @@
   }
 
   @override
-  ResolutionDartType computeType(Resolution resolution) => type;
+  T computeType(Resolution resolution) => type;
 }
 
 abstract class ParametersMixin
@@ -921,6 +924,7 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class ClassElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
@@ -929,7 +933,7 @@
         class_members.ClassMemberMixin,
         ContainerMixin,
         LibraryMemberMixin,
-        TypeDeclarationMixin<ResolutionInterfaceType>,
+        TypeDeclarationMixin,
         ClassElementMixin
     implements ClassElement {
   bool _isObject;
@@ -1020,6 +1024,10 @@
     // TODO(johnniwinther): Why can't this always be computed in ensureResolved?
     return _callType;
   }
+
+  ResolutionInterfaceType get thisType => super.thisType;
+
+  ResolutionInterfaceType get rawType => super.rawType;
 }
 
 abstract class MixinApplicationElementMixin
@@ -1051,7 +1059,8 @@
         ClassElementCommon,
         ClassElementMixin,
         class_members.ClassMemberMixin,
-        TypeDeclarationMixin<ResolutionInterfaceType>,
+        // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_MIXIN
+        TypeDeclarationMixin,
         AnalyzableElementMixin,
         AstElementMixinZ,
         MixinApplicationElementCommon,
@@ -1202,6 +1211,7 @@
   SourceSpan get sourcePosition => subclass.sourcePosition;
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class EnumClassElementZ extends ClassElementZ implements EnumClassElement {
   List<FieldElement> _enumValues;
 
@@ -1211,7 +1221,7 @@
   bool get isEnumClass => true;
 
   @override
-  List<FieldElement> get enumValues {
+  List<EnumConstantElement> get enumValues {
     if (_enumValues == null) {
       _enumValues = _decoder.getElements(Key.FIELDS);
     }
@@ -1219,14 +1229,15 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class ConstructorElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<FunctionExpression>,
         ClassMemberMixin,
         FunctionTypedElementMixin,
         ParametersMixin,
-        TypedElementMixin,
+        TypedElementMixin<ResolutionFunctionType>,
         MemberElementMixin,
         ConstructorElementCommon
     implements
@@ -1306,7 +1317,7 @@
   PrefixElement get redirectionDeferredPrefix => null;
 
   @override
-  ResolutionInterfaceType computeEffectiveTargetType(
+  ResolutionDartType computeEffectiveTargetType(
           ResolutionInterfaceType newType) =>
       newType;
 }
@@ -1416,10 +1427,11 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class ForwardingConstructorElementZ extends ElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ
+        AstElementMixinZ<FunctionExpression>
     implements
         ConstructorElement,
         // TODO(johnniwinther): Sort out whether a constructor is a method.
@@ -1441,7 +1453,7 @@
   AsyncMarker get asyncMarker => AsyncMarker.SYNC;
 
   @override
-  ResolutionInterfaceType computeEffectiveTargetType(
+  ResolutionDartType computeEffectiveTargetType(
       ResolutionInterfaceType newType) {
     return enclosingClass.thisType.substByContext(newType);
   }
@@ -1583,7 +1595,7 @@
 abstract class FieldElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<VariableDefinitions>,
         TypedElementMixin,
         MemberElementMixin
     implements FieldElement {
@@ -1638,6 +1650,7 @@
   StaticFieldElementZ(ObjectDecoder decoder) : super(decoder);
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class EnumConstantElementZ extends StaticFieldElementZ
     implements EnumConstantElement {
   EnumConstantElementZ(ObjectDecoder decoder) : super(decoder);
@@ -1650,13 +1663,14 @@
   InstanceFieldElementZ(ObjectDecoder decoder) : super(decoder);
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class FunctionElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<FunctionExpression>,
         ParametersMixin,
         FunctionTypedElementMixin,
-        TypedElementMixin,
+        TypedElementMixin<ResolutionFunctionType>,
         MemberElementMixin
     implements MethodElement {
   FunctionElementZ(ObjectDecoder decoder) : super(decoder);
@@ -1704,7 +1718,7 @@
   Element get enclosingElement => executableContext;
 
   @override
-  Element get enclosingClass => memberContext.enclosingClass;
+  ClassElementZ get enclosingClass => memberContext.enclosingClass;
 
   @override
   ExecutableElement get executableContext {
@@ -1735,13 +1749,14 @@
   TreeElements get treeElements => memberContext.treeElements;
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class LocalFunctionElementZ extends DeserializedElementZ
     with
         LocalExecutableMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<FunctionExpression>,
         ParametersMixin,
         FunctionTypedElementMixin,
-        TypedElementMixin
+        TypedElementMixin<ResolutionFunctionType>
     implements LocalFunctionElement {
   LocalFunctionElementZ(ObjectDecoder decoder) : super(decoder);
 
@@ -1759,13 +1774,14 @@
   }
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class GetterElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<FunctionExpression>,
         FunctionTypedElementMixin,
         ParametersMixin,
-        TypedElementMixin,
+        TypedElementMixin<ResolutionFunctionType>,
         MemberElementMixin
     implements GetterElement {
   AbstractFieldElement abstractField;
@@ -1804,13 +1820,14 @@
   InstanceGetterElementZ(ObjectDecoder decoder) : super(decoder);
 }
 
+// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class SetterElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<FunctionExpression>,
         FunctionTypedElementMixin,
         ParametersMixin,
-        TypedElementMixin,
+        TypedElementMixin<ResolutionFunctionType>,
         MemberElementMixin
     implements SetterElement {
   AbstractFieldElement abstractField;
@@ -1847,11 +1864,11 @@
   InstanceSetterElementZ(ObjectDecoder decoder) : super(decoder);
 }
 
-abstract class TypeDeclarationMixin<T extends GenericType>
+abstract class TypeDeclarationMixin
     implements ElementZ, TypeDeclarationElement {
   List<ResolutionDartType> _typeVariables;
-  T _rawType;
-  T _thisType;
+  GenericType _rawType;
+  GenericType _thisType;
   Name _memberName;
 
   Name get memberName {
@@ -1872,7 +1889,7 @@
     }
   }
 
-  T _createType(List<ResolutionDartType> typeArguments);
+  GenericType _createType(List<ResolutionDartType> typeArguments);
 
   @override
   List<ResolutionDartType> get typeVariables {
@@ -1881,19 +1898,19 @@
   }
 
   @override
-  T get rawType {
+  GenericType get rawType {
     _ensureTypes();
     return _rawType;
   }
 
   @override
-  T get thisType {
+  GenericType get thisType {
     _ensureTypes();
     return _thisType;
   }
 
   @override
-  T computeType(Resolution resolution) => thisType;
+  GenericType computeType(Resolution resolution) => thisType;
 
   @override
   bool get isResolved => true;
@@ -1902,10 +1919,10 @@
 class TypedefElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<Node>,
         LibraryMemberMixin,
         ParametersMixin,
-        TypeDeclarationMixin<ResolutionTypedefType>
+        TypeDeclarationMixin
     implements TypedefElement {
   ResolutionDartType _alias;
 
@@ -1941,10 +1958,17 @@
 
   @override
   void checkCyclicReference(Resolution resolution) {}
+
+  ResolutionTypedefType get thisType => super.thisType;
+
+  ResolutionTypedefType get rawType => super.rawType;
 }
 
 class TypeVariableElementZ extends DeserializedElementZ
-    with AnalyzableElementMixin, AstElementMixinZ, TypedElementMixin
+    with
+        AnalyzableElementMixin,
+        AstElementMixinZ<Node>,
+        TypedElementMixin<ResolutionTypeVariableType>
     implements TypeVariableElement {
   GenericElement _typeDeclaration;
   ResolutionTypeVariableType _type;
@@ -1977,7 +2001,7 @@
   Element get enclosingElement => typeDeclaration;
 
   @override
-  Element get enclosingClass => typeDeclaration;
+  ClassElementZ get enclosingClass => typeDeclaration;
 
   @override
   int get index => _decoder.getInt(Key.INDEX);
@@ -2002,7 +2026,7 @@
 }
 
 class SyntheticTypeVariableElementZ extends ElementZ
-    with AnalyzableElementMixin, AstElementMixinZ
+    with AnalyzableElementMixin, AstElementMixinZ<Node>
     implements TypeVariableElement {
   final TypeDeclarationElement typeDeclaration;
   final int index;
@@ -2047,7 +2071,7 @@
   Element get enclosingElement => typeDeclaration;
 
   @override
-  Element get enclosingClass => typeDeclaration;
+  ClassElementZ get enclosingClass => typeDeclaration;
 
   ResolutionDartType get bound {
     assert(_bound != null,
@@ -2066,7 +2090,10 @@
 }
 
 abstract class ParameterElementZ extends DeserializedElementZ
-    with AnalyzableElementMixin, AstElementMixinZ, TypedElementMixin
+    with
+        AnalyzableElementMixin,
+        AstElementMixinZ<VariableDefinitions>,
+        TypedElementMixin
     implements ParameterElement {
   FunctionElement _functionDeclaration;
   ConstantExpression _constant;
@@ -2122,7 +2149,7 @@
   Expression initializer;
 
   @override
-  Node node;
+  VariableDefinitions node;
 
   @override
   bool get isNamed => _decoder.getBool(Key.IS_NAMED);
@@ -2183,12 +2210,14 @@
 
   @override
   bool get isLocal => true;
+
+  ConstructorElementZ get functionDeclaration => super.functionDeclaration;
 }
 
 class LocalVariableElementZ extends DeserializedElementZ
     with
         AnalyzableElementMixin,
-        AstElementMixinZ,
+        AstElementMixinZ<VariableDefinitions>,
         LocalExecutableMixin,
         TypedElementMixin
     implements LocalVariableElement {
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index 5c90ee4..954d9e9 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -178,7 +178,8 @@
   }
 
   void serializeParameterNodes(FunctionElement function) {
-    function.functionSignature.forEachParameter((ParameterElement parameter) {
+    function.functionSignature.forEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       ParameterElement parameterImpl = parameter.implementation;
       // TODO(johnniwinther): Should we support element->node mapping as well?
       getNodeDataEncoder(parameterImpl.node)
@@ -605,13 +606,14 @@
         labelDefinitions.add(labelDefinition);
       }
     }
-    jumpTargetLabels.forEach((JumpTargetX jumpTarget, List<int> labelIds) {
+    jumpTargetLabels.forEach((JumpTarget jumpTarget, List<int> labelIds) {
       if (labelIds.isEmpty) return;
       List<LabelDefinition> labels = <LabelDefinition>[];
       for (int labelId in labelIds) {
         labels.add(labelDefinitions[labelId]);
       }
-      jumpTarget.labels = labels;
+      JumpTargetX target = jumpTarget;
+      target.labels = labels;
     });
 
     ListDecoder dataDecoder = objectDecoder.getList(Key.DATA, isOptional: true);
diff --git a/pkg/compiler/lib/src/serialization/system.dart b/pkg/compiler/lib/src/serialization/system.dart
index 4d05ff8..8ae4efc 100644
--- a/pkg/compiler/lib/src/serialization/system.dart
+++ b/pkg/compiler/lib/src/serialization/system.dart
@@ -11,6 +11,7 @@
 import '../compiler.dart';
 import '../elements/resolution_types.dart';
 import '../elements/elements.dart';
+import '../elements/entities.dart';
 import '../script.dart';
 import '../serialization/impact_serialization.dart';
 import 'package:front_end/src/fasta/scanner.dart';
@@ -100,7 +101,7 @@
           // TODO(johnniwinther): Find a cleaner way to do this. Maybe
           // `Feature.LAZY_FIELD` of the resolution impact should be used
           // instead.
-          _compiler.backend.constants.registerLazyStatic(element);
+          _compiler.backend.constants.registerLazyStatic(field);
         }
       }
     }
@@ -108,7 +109,8 @@
   }
 
   @override
-  bool isDeserialized(Element element) {
+  bool isDeserialized(Entity entity) {
+    Element element = entity;
     return deserializedLibraries.contains(element.library);
   }
 }
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index ba766cd..4a072bd 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -130,10 +130,12 @@
 class CompilerSourceFileProvider extends SourceFileProvider {
   // TODO(johnniwinther): Remove this when no longer needed for the old compiler
   // API.
-  Future<List<int>> call(Uri resourceUri) => readFromUri(resourceUri);
+  Future<List<int>> call(Uri resourceUri) =>
+      readFromUri(resourceUri).then((input) => input.data);
 
   @override
-  Future readFromUri(Uri uri, {InputKind inputKind: InputKind.utf8}) =>
+  Future<api.Input<List<int>>> readFromUri(Uri uri,
+          {InputKind inputKind: InputKind.utf8}) =>
       readBytesFromUri(uri, inputKind);
 }
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index fd57333..afc4cda 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -54,85 +54,53 @@
 import 'type_builder.dart';
 import 'types.dart';
 
-abstract class SsaAstBuilderBase extends CompilerTask
-    implements SsaBuilderTask {
+abstract class SsaAstBuilderBase extends SsaBuilderFieldMixin
+    implements SsaBuilder {
+  final CompilerTask task;
   final JavaScriptBackend backend;
 
-  SsaAstBuilderBase(this.backend) : super(backend.compiler.measurer);
+  SsaAstBuilderBase(this.task, this.backend);
 
-  /// Handle field initializer of `work.element`. Returns `true` if no code
-  /// is needed for the field.
-  ///
-  /// If `work.element` is a field with a constant initializer, the value is
-  /// registered with the world impact. Otherwise the cyclic-throw helper is
-  /// registered for the lazy value computation.
-  ///
-  /// If the field is constant, no code is needed for the field and the method
-  /// return `true`.
-  bool handleConstantField(
-      ElementCodegenWorkItem work, ClosedWorld closedWorld) {
-    MemberElement element = work.element;
-    if (element.isField) {
-      FieldElement field = element;
-      ConstantExpression constant = field.constant;
-      if (constant != null) {
-        ConstantValue initialValue =
-            backend.constants.getConstantValue(constant);
-        if (initialValue != null) {
-          work.registry.worldImpact
-              .registerConstantUse(new ConstantUse.init(initialValue));
-          // We don't need to generate code for static or top-level
-          // variables. For instance variables, we may need to generate
-          // the checked setter.
-          if (field.isStatic || field.isTopLevel) {
-            /// No code is created for this field.
-            return true;
-          }
-        } else {
-          assert(
-              field.isInstanceMember ||
-                  constant.isImplicit ||
-                  constant.isPotential,
-              failedAt(
-                  field,
-                  "Constant expression without value: "
-                  "${constant.toStructuredText()}."));
-        }
-      } else {
-        // If the constant-handler was not able to produce a result we have to
-        // go through the builder (below) to generate the lazy initializer for
-        // the static variable.
-        // We also need to register the use of the cyclic-error helper.
-        work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
-            closedWorld.commonElements.cyclicThrowHelper,
-            CallStructure.ONE_ARG));
+  ConstantValue getFieldInitialConstantValue(FieldElement field) {
+    ConstantExpression constant = field.constant;
+    if (constant != null) {
+      ConstantValue initialValue = backend.constants.getConstantValue(constant);
+      if (initialValue == null) {
+        assert(
+            field.isInstanceMember ||
+                constant.isImplicit ||
+                constant.isPotential,
+            failedAt(
+                field,
+                "Constant expression without value: "
+                "${constant.toStructuredText()}."));
       }
+      return initialValue;
     }
-    return false;
+    return null;
   }
 }
 
-class SsaAstBuilderTask extends SsaAstBuilderBase {
+class SsaAstBuilder extends SsaAstBuilderBase {
   final CodeEmitterTask emitter;
   final SourceInformationStrategy sourceInformationFactory;
 
-  String get name => 'SSA builder';
-
-  SsaAstBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory)
+  SsaAstBuilder(CompilerTask task, JavaScriptBackend backend,
+      this.sourceInformationFactory)
       : emitter = backend.emitter,
-        super(backend);
+        super(task, backend);
 
   DiagnosticReporter get reporter => backend.reporter;
 
-  HGraph build(ElementCodegenWorkItem work, ClosedWorld closedWorld) {
-    return measure(() {
-      if (handleConstantField(work, closedWorld)) {
+  HGraph build(covariant ElementCodegenWorkItem work, ClosedWorld closedWorld) {
+    return task.measure(() {
+      if (handleConstantField(work.element, work.registry, closedWorld)) {
         // No code is generated for `work.element`.
         return null;
       }
       MemberElement element = work.element.implementation;
       return reporter.withCurrentElement(element, () {
-        SsaBuilder builder = new SsaBuilder(
+        SsaAstGraphBuilder builder = new SsaAstGraphBuilder(
             work.element.implementation,
             work.resolvedAst,
             work.registry,
@@ -147,7 +115,8 @@
         if (!identical(element.kind, ElementKind.FIELD)) {
           MethodElement function = element;
           FunctionSignature signature = function.functionSignature;
-          signature.forEachOptionalParameter((ParameterElement parameter) {
+          signature.forEachOptionalParameter((_parameter) {
+            ParameterElement parameter = _parameter;
             // This ensures the default value will be computed.
             ConstantValue constant =
                 backend.constants.getConstantValue(parameter.constant);
@@ -178,7 +147,7 @@
 /**
  * This class builds SSA nodes for functions represented in AST.
  */
-class SsaBuilder extends ast.Visitor
+class SsaAstGraphBuilder extends ast.Visitor
     with
         BaseImplementationOfCompoundsMixin,
         BaseImplementationOfSetIfNullsMixin,
@@ -257,7 +226,7 @@
   TypeBuilder typeBuilder;
 
   // TODO(sigmund): make most args optional
-  SsaBuilder(
+  SsaAstGraphBuilder(
       this.target,
       this.resolvedAst,
       this.registry,
@@ -867,7 +836,8 @@
     assert(resolvedAst != null);
     localsHandler = new LocalsHandler(this, function, function.memberContext,
         function.contextClass, instanceType, nativeData, interceptorData);
-    localsHandler.closureData = closureToClassMapper.getMemberMap(function);
+    localsHandler.closureData =
+        closureDataLookup.getClosureRepresentationInfo(function);
     returnLocal =
         new SyntheticLocal("result", function, function.memberContext);
     localsHandler.updateLocal(returnLocal, graph.addConstantNull(closedWorld));
@@ -881,7 +851,8 @@
     }
 
     FunctionSignature signature = function.functionSignature;
-    signature.orderedForEachParameter((ParameterElement parameter) {
+    signature.orderedForEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       HInstruction argument = compiledArguments[argumentIndex++];
       localsHandler.updateLocal(parameter, argument);
     });
@@ -889,8 +860,8 @@
     ClassElement enclosing = function.enclosingClass;
     if ((function.isConstructor || function.isGenerativeConstructorBody) &&
         rtiNeed.classNeedsRti(enclosing)) {
-      enclosing.typeVariables
-          .forEach((ResolutionTypeVariableType typeVariable) {
+      enclosing.typeVariables.forEach((_typeVariable) {
+        ResolutionTypeVariableType typeVariable = _typeVariable;
         HInstruction argument = compiledArguments[argumentIndex++];
         localsHandler.updateLocal(
             localsHandler.getTypeVariableAsLocal(typeVariable), argument);
@@ -1013,7 +984,8 @@
 
       int index = 0;
       FunctionSignature params = callee.functionSignature;
-      params.orderedForEachParameter((ParameterElement parameter) {
+      params.orderedForEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         HInstruction argument = compiledArguments[index++];
         // Because we are inlining the initializer, we must update
         // what was given as parameter. This will be used in case
@@ -1033,18 +1005,14 @@
       resolvedAst = callee.resolvedAst;
       final oldElementInferenceResults = elementInferenceResults;
       elementInferenceResults = globalInferenceResults.resultOfMember(callee);
-      ClosureClassMap oldClosureData = localsHandler.closureData;
-      ClosureClassMap newClosureData =
-          closureToClassMapper.getMemberMap(callee);
+      ClosureRepresentationInfo oldClosureData = localsHandler.closureData;
+      ClosureRepresentationInfo newClosureData =
+          closureDataLookup.getClosureRepresentationInfo(callee);
       localsHandler.closureData = newClosureData;
       if (resolvedAst.kind == ResolvedAstKind.PARSED) {
-        // TODO(efortuna): Take out the test below for null once we are no
-        // longer dealing with the ClosureClassMap interface directly.
-        if (newClosureData.capturingScopes[resolvedAst.node] != null) {
-          localsHandler.enterScope(
-              newClosureData.capturingScopes[resolvedAst.node],
-              forGenerativeConstructorBody: callee.isGenerativeConstructorBody);
-        }
+        localsHandler.enterScope(
+            closureDataLookup.getClosureAnalysisInfo(resolvedAst.node),
+            forGenerativeConstructorBody: callee.isGenerativeConstructorBody);
       }
       buildInitializers(callee, constructorResolvedAsts, fieldValues);
       localsHandler.closureData = oldClosureData;
@@ -1270,7 +1238,8 @@
 
     // Compile field-parameters such as [:this.x:].
     FunctionSignature params = functionElement.functionSignature;
-    params.orderedForEachParameter((ParameterElement parameter) {
+    params.orderedForEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       if (parameter.isInitializingFormal) {
         // If the [element] is a field-parameter then
         // initialize the field element with its value.
@@ -1324,8 +1293,8 @@
         // HTypeInfoExpression to set on the newly create object.
         hasRtiInput = true;
         List<HInstruction> typeArguments = <HInstruction>[];
-        classElement.typeVariables
-            .forEach((ResolutionTypeVariableType typeVariable) {
+        classElement.typeVariables.forEach((_typeVariable) {
+          ResolutionTypeVariableType typeVariable = _typeVariable;
           HInstruction argument = localsHandler
               .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable));
           typeArguments.add(argument);
@@ -1386,7 +1355,8 @@
 
       FunctionSignature functionSignature = body.functionSignature;
       // Provide the parameters to the generative constructor body.
-      functionSignature.orderedForEachParameter((ParameterElement parameter) {
+      functionSignature.orderedForEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         // If [parameter] is boxed, it will be a field in the box passed as the
         // last parameter. So no need to directly pass it.
         if (!localsHandler.isBoxed(parameter)) {
@@ -1398,8 +1368,8 @@
       // pass the box to the constructor.
       // The box must be passed before any type variable.
       ClosureAnalysisInfo scopeData =
-          closureToClassMapper.getClosureAnalysisInfo(node);
-      if (scopeData.requiresContextBox()) {
+          closureDataLookup.getClosureAnalysisInfo(node);
+      if (scopeData.requiresContextBox) {
         bodyCallInputs.add(localsHandler.readLocal(scopeData.context));
       }
 
@@ -1408,8 +1378,8 @@
       if (rtiNeed.classNeedsRti(currentClass)) {
         // If [currentClass] needs RTI, we add the type variables as
         // parameters of the generative constructor body.
-        currentClass.typeVariables
-            .forEach((ResolutionTypeVariableType argument) {
+        currentClass.typeVariables.forEach((_argument) {
+          ResolutionTypeVariableType argument = _argument;
           // TODO(johnniwinther): Substitute [argument] with
           // `localsHandler.substInContext(argument)`.
           bodyCallInputs.add(localsHandler
@@ -1449,16 +1419,17 @@
 
     Map<Local, TypeMask> parameters = <Local, TypeMask>{};
     if (element is MethodElement) {
-      element.functionSignature
-          .orderedForEachParameter((ParameterElement parameter) {
+      element.functionSignature.orderedForEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         parameters[parameter] = TypeMaskFactory.inferredTypeForParameter(
             parameter, globalInferenceResults);
       });
     }
 
-    ClosureClassMap closureData = closureToClassMapper.getMemberMap(element);
-    localsHandler.startFunction(
-        element, closureData, closureData.capturingScopes[node], parameters,
+    ClosureRepresentationInfo closureData =
+        closureDataLookup.getClosureRepresentationInfo(element);
+    localsHandler.startFunction(element, closureData,
+        closureDataLookup.getClosureAnalysisInfo(node), parameters,
         isGenerativeConstructorBody: element.isGenerativeConstructorBody);
     close(new HGoto()).addSuccessor(block);
 
@@ -1470,7 +1441,8 @@
     ClassElement cls = element.enclosingClass;
     if ((element.isConstructor || element.isGenerativeConstructorBody) &&
         rtiNeed.classNeedsRti(cls)) {
-      cls.typeVariables.forEach((ResolutionTypeVariableType typeVariable) {
+      cls.typeVariables.forEach((_typeVariable) {
+        ResolutionTypeVariableType typeVariable = _typeVariable;
         HParameterValue param =
             addParameter(typeVariable.element, commonMasks.nonNullType);
         localsHandler.directLocals[
@@ -1486,9 +1458,10 @@
       // because that is where the type guards will also be inserted.
       // This way we ensure that a type guard will dominate the type
       // check.
-      signature.orderedForEachParameter((ParameterElement parameterElement) {
+      signature.orderedForEachParameter((_parameterElement) {
+        ParameterElement parameterElement = _parameterElement;
         if (element.isGenerativeConstructorBody) {
-          if (closureToClassMapper
+          if (closureDataLookup
               .getClosureAnalysisInfo(node)
               .isCaptured(parameterElement)) {
             // The parameter will be a field in the box passed as the
@@ -1733,7 +1706,7 @@
 
     loopHandler.handleLoop(
         node,
-        closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+        closureDataLookup.getClosureRepresentationInfoForLoop(node),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1749,7 +1722,7 @@
 
     loopHandler.handleLoop(
         node,
-        closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+        closureDataLookup.getClosureRepresentationInfoForLoop(node),
         () {},
         buildCondition,
         () {}, () {
@@ -1761,7 +1734,7 @@
     assert(isReachable);
     LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
     var loopClosureInfo =
-        closureToClassMapper.getClosureRepresentationInfoForLoop(node);
+        closureDataLookup.getClosureRepresentationInfoForLoop(node);
     localsHandler.startLoop(loopClosureInfo);
     loopDepth++;
     JumpHandler jumpHandler = loopHandler.beginLoopHeader(node);
@@ -1899,25 +1872,19 @@
 
   visitFunctionExpression(ast.FunctionExpression node) {
     LocalFunctionElement methodElement = elements[node];
-    ClosureClassMap nestedClosureData =
-        closureToClassMapper.getLocalFunctionMap(methodElement);
-    assert(nestedClosureData != null);
-    assert(nestedClosureData.closureClassElement != null);
-    ClosureClassElement closureClassElement =
-        nestedClosureData.closureClassElement;
-    MethodElement callElement = nestedClosureData.callElement;
+    ClosureRepresentationInfo closureInfo =
+        closureDataLookup.getClosureRepresentationInfo(methodElement);
+    ClassEntity closureClassEntity = closureInfo.closureClassEntity;
 
     List<HInstruction> capturedVariables = <HInstruction>[];
-    closureClassElement.closureFields.forEach((ClosureFieldElement field) {
-      Local capturedLocal =
-          nestedClosureData.getLocalVariableForClosureField(field);
-      assert(capturedLocal != null);
-      capturedVariables.add(localsHandler.readLocal(capturedLocal));
+    closureInfo.createdFieldEntities.forEach((Local field) {
+      assert(field != null);
+      capturedVariables.add(localsHandler.readLocal(field));
     });
 
-    TypeMask type = new TypeMask.nonNullExact(closureClassElement, closedWorld);
-    push(new HCreate(closureClassElement, capturedVariables, type,
-        callMethod: callElement, localFunction: methodElement)
+    TypeMask type = new TypeMask.nonNullExact(closureClassEntity, closedWorld);
+    push(new HCreate(closureClassEntity, capturedVariables, type,
+        callMethod: closureInfo.callMethod, localFunction: methodElement)
       ..sourceInformation = sourceInformationBuilder.buildCreate(node));
   }
 
@@ -3324,7 +3291,7 @@
   bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
     if (closedWorld.isUsedAsMixin(cls)) return true;
 
-    return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
+    return closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
       return !rtiSubstitutions.isTrivialSubstitution(subclass, cls);
     });
   }
@@ -3450,7 +3417,7 @@
       }
     }
     ResolutionInterfaceType type = elements.getType(node);
-    ResolutionInterfaceType expectedType =
+    ResolutionDartType expectedType =
         constructorDeclaration.computeEffectiveTargetType(type);
     expectedType = localsHandler.substInContext(expectedType);
 
@@ -3518,7 +3485,7 @@
       // can depend on a length type discovered in optimization.
       bool canThrow = true;
       if (inputs[0].isInteger(closedWorld) && inputs[0] is HConstant) {
-        var constant = inputs[0];
+        dynamic constant = inputs[0];
         int value = constant.constant.primitiveValue;
         if (0 <= value && value < 0x100000000) canThrow = false;
       }
@@ -3608,11 +3575,15 @@
     bool definitelyFails = false;
 
     void addTypeVariableBoundCheck(
-        ResolutionInterfaceType instance,
-        ResolutionDartType typeArgument,
-        ResolutionTypeVariableType typeVariable,
-        ResolutionDartType bound) {
+        InterfaceType _instance,
+        DartType _typeArgument,
+        TypeVariableType _typeVariable,
+        DartType _bound) {
       if (definitelyFails) return;
+      ResolutionInterfaceType instance = _instance;
+      ResolutionDartType typeArgument = _typeArgument;
+      ResolutionTypeVariableType typeVariable = _typeVariable;
+      ResolutionDartType bound = _bound;
 
       int subtypeRelation = types.computeSubtypeRelation(typeArgument, bound);
       if (subtypeRelation == DartTypes.IS_SUBTYPE) return;
@@ -4113,7 +4084,8 @@
       int positions = 0;
       var filteredArguments = <HInstruction>[];
       var parameterNameMap = new Map<String, js.Expression>();
-      params.orderedForEachParameter((ParameterElement parameter) {
+      params.orderedForEachParameter((_parameter) {
+        ParameterElement parameter = _parameter;
         // TODO(jacobr): consider throwing if parameter names do not match
         // names of properties in the class.
         assert(parameter.isNamed);
@@ -4388,7 +4360,7 @@
 
   @override
   void visitSuperMethodSet(
-      ast.Send node, MethodElement method, ast.Node rhs, _) {
+      ast.SendSet node, MethodElement method, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
 
@@ -4399,8 +4371,8 @@
   }
 
   @override
-  void visitUnresolvedSuperIndexSet(
-      ast.Send node, Element element, ast.Node index, ast.Node rhs, _) {
+  void visitUnresolvedSuperIndexSet(ast.SendSet node, ErroneousElement element,
+      ast.Node index, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
 
@@ -4427,20 +4399,20 @@
   }
 
   @override
-  void visitUnresolvedSuperGetterIndexPrefix(ast.Send node, Element element,
+  void visitUnresolvedSuperGetterIndexPrefix(ast.SendSet node, Element element,
       MethodElement setter, ast.Node index, IncDecOperator operator, _) {
     handleSuperSendSet(node);
   }
 
   @override
-  void visitUnresolvedSuperGetterIndexPostfix(ast.Send node, Element element,
+  void visitUnresolvedSuperGetterIndexPostfix(ast.SendSet node, Element element,
       MethodElement setter, ast.Node index, IncDecOperator operator, _) {
     handleSuperSendSet(node);
   }
 
   @override
   void visitUnresolvedSuperSetterIndexPrefix(
-      ast.Send node,
+      ast.SendSet node,
       MethodElement indexFunction,
       Element element,
       ast.Node index,
@@ -4451,7 +4423,7 @@
 
   @override
   void visitUnresolvedSuperSetterIndexPostfix(
-      ast.Send node,
+      ast.SendSet node,
       MethodElement indexFunction,
       Element element,
       ast.Node index,
@@ -4486,7 +4458,7 @@
 
   @override
   void visitUnresolvedSuperGetterCompoundIndexSet(
-      ast.Send node,
+      ast.SendSet node,
       Element element,
       MethodElement setter,
       ast.Node index,
@@ -4498,7 +4470,7 @@
 
   @override
   void visitUnresolvedSuperSetterCompoundIndexSet(
-      ast.Send node,
+      ast.SendSet node,
       MethodElement getter,
       Element element,
       ast.Node index,
@@ -4509,7 +4481,7 @@
   }
 
   @override
-  void visitUnresolvedSuperCompoundIndexSet(ast.Send node, Element element,
+  void visitUnresolvedSuperCompoundIndexSet(ast.SendSet node, Element element,
       ast.Node index, AssignmentOperator operator, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
@@ -4534,13 +4506,13 @@
 
   @override
   void visitUnresolvedSuperPrefix(
-      ast.Send node, Element element, IncDecOperator operator, _) {
+      ast.SendSet node, Element element, IncDecOperator operator, _) {
     handleSuperSendSet(node);
   }
 
   @override
   void visitUnresolvedSuperPostfix(
-      ast.Send node, Element element, IncDecOperator operator, _) {
+      ast.SendSet node, Element element, IncDecOperator operator, _) {
     handleSuperSendSet(node);
   }
 
@@ -4575,19 +4547,19 @@
   }
 
   @override
-  void visitSuperMethodCompound(ast.Send node, FunctionElement method,
+  void visitSuperMethodCompound(ast.Send node, MethodElement method,
       AssignmentOperator operator, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
 
   @override
-  void visitUnresolvedSuperGetterCompound(ast.Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, ast.Node rhs, _) {
+  void visitUnresolvedSuperGetterCompound(ast.SendSet node, Element element,
+      SetterElement setter, AssignmentOperator operator, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
 
   @override
-  void visitUnresolvedSuperSetterCompound(ast.Send node, MethodElement getter,
+  void visitUnresolvedSuperSetterCompound(ast.Send node, GetterElement getter,
       Element element, AssignmentOperator operator, ast.Node rhs, _) {
     handleSuperSendSet(node);
   }
@@ -5181,12 +5153,14 @@
     ClassElement targetClass = targetConstructor.enclosingClass;
     if (rtiNeed.classNeedsRti(targetClass)) {
       ClassElement cls = redirectingConstructor.enclosingClass;
-      ResolutionInterfaceType targetType =
+      ResolutionDartType targetType =
           redirectingConstructor.computeEffectiveTargetType(cls.thisType);
       targetType = localsHandler.substInContext(targetType);
-      targetType.typeArguments.forEach((ResolutionDartType argument) {
-        inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
-      });
+      if (targetType is ResolutionInterfaceType) {
+        targetType.typeArguments.forEach((ResolutionDartType argument) {
+          inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+        });
+      }
     }
     pushInvokeStatic(node, targetConstructor.declaration, inputs);
     HInstruction value = pop();
@@ -5470,7 +5444,7 @@
     buildProtectedByFinally(() {
       loopHandler.handleLoop(
           node,
-          closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+          closureDataLookup.getClosureRepresentationInfoForLoop(node),
           buildInitializer,
           buildCondition,
           buildUpdate,
@@ -5542,7 +5516,7 @@
 
     loopHandler.handleLoop(
         node,
-        closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+        closureDataLookup.getClosureRepresentationInfoForLoop(node),
         buildInitializer,
         buildCondition,
         () {},
@@ -5666,7 +5640,7 @@
 
     loopHandler.handleLoop(
         node,
-        closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+        closureDataLookup.getClosureRepresentationInfoForLoop(node),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -5751,14 +5725,14 @@
     listConstructor = constructorElement.effectiveTarget;
 
     ResolutionInterfaceType type = elements.getType(node);
-    ResolutionInterfaceType expectedType =
+    ResolutionDartType expectedType =
         constructorElement.computeEffectiveTargetType(type);
     expectedType = localsHandler.substInContext(expectedType);
 
     ClassElement cls = listConstructor.enclosingClass;
 
     MethodElement createFunction = listConstructor;
-    if (rtiNeed.classNeedsRti(cls)) {
+    if (expectedType is ResolutionInterfaceType && rtiNeed.classNeedsRti(cls)) {
       List<HInstruction> typeInputs = <HInstruction>[];
       expectedType.typeArguments.forEach((ResolutionDartType argument) {
         typeInputs
@@ -5937,7 +5911,7 @@
     localsHandler.updateLocal(switchTarget, initialValue);
 
     JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
-    var switchCases = node.cases;
+    dynamic switchCases = node.cases;
     if (!hasDefault) {
       // Use [:null:] as the marker for a synthetic default clause.
       // The synthetic default is added because otherwise, there would be no
@@ -6019,7 +5993,7 @@
     void buildLoop() {
       loopHandler.handleLoop(
           node,
-          closureToClassMapper.getClosureRepresentationInfoForLoop(node),
+          closureDataLookup.getClosureRepresentationInfoForLoop(node),
           () {},
           buildCondition,
           () {},
@@ -6597,7 +6571,7 @@
  * non-literal subexpressions.
  */
 class StringBuilderVisitor extends ast.Visitor {
-  final SsaBuilder builder;
+  final SsaAstGraphBuilder builder;
   final ast.Node diagnosticNode;
 
   /**
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index b384fd1..3b99d41 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -41,11 +41,13 @@
 import 'locals_handler.dart';
 import 'loop_handler.dart';
 import 'nodes.dart';
+import 'ssa.dart';
 import 'ssa_branch_builder.dart';
 import 'switch_continue_analysis.dart';
 import 'type_builder.dart';
 
-class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
+class KernelSsaGraphBuilder extends ir.Visitor
+    with GraphBuilder, SsaBuilderFieldMixin {
   final ir.Node target;
   final bool _targetIsConstructorBody;
   final MemberEntity targetElement;
@@ -58,7 +60,7 @@
   final ClosedWorld closedWorld;
   final CodegenWorldBuilder _worldBuilder;
   final CodegenRegistry registry;
-  final ClosureClassMaps closureToClassMapper;
+  final ClosureDataLookup closureDataLookup;
 
   /// Helper accessor for all kernel function-like targets (Procedure,
   /// FunctionExpression, FunctionDeclaration) of the inner FunctionNode itself.
@@ -98,7 +100,7 @@
   /// this is a slow path.
   bool _inExpressionOfThrow = false;
 
-  KernelSsaBuilder(
+  KernelSsaGraphBuilder(
       this.targetElement,
       ClassEntity contextClass,
       this.target,
@@ -109,7 +111,7 @@
       this.closedWorld,
       this._worldBuilder,
       this.registry,
-      this.closureToClassMapper,
+      this.closureDataLookup,
       // TODO(het): Should sourceInformationBuilder be in GraphBuilder?
       this.sourceInformationBuilder,
       this.functionNode,
@@ -138,6 +140,13 @@
         _targetFunction = (target as ir.Procedure).function;
         buildFunctionNode(_targetFunction);
       } else if (target is ir.Field) {
+        if (handleConstantField(targetElement, registry, closedWorld)) {
+          // No code is generated for `targetElement`: All references inline the
+          // constant value.
+          return null;
+        } else if (targetElement.isStatic || targetElement.isTopLevel) {
+          backend.constants.registerLazyStatic(targetElement);
+        }
         buildField(target);
       } else if (target is ir.Constructor) {
         if (_targetIsConstructorBody) {
@@ -160,6 +169,12 @@
     });
   }
 
+  @override
+  ConstantValue getFieldInitialConstantValue(FieldEntity field) {
+    assert(field == targetElement);
+    return _elementMap.getFieldConstantValue(target);
+  }
+
   void buildField(ir.Field field) {
     openFunction();
     if (field.initializer != null) {
@@ -221,11 +236,6 @@
     });
   }
 
-  /// Comparator for the canonical order or named arguments.
-  int namedOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
-    return a.name.compareTo(b.name);
-  }
-
   /// Builds a generative constructor.
   ///
   /// Generative constructors are built in stages, in effect inlining the
@@ -273,7 +283,7 @@
     // Doing this instead of fieldValues.forEach because we haven't defined the
     // order of the arguments here. We can define that with JElements.
     ClassEntity cls = _elementMap.getClass(constructedClass);
-    InterfaceType thisType = _elementMap.getThisType(cls);
+    InterfaceType thisType = _elementMap.elementEnvironment.getThisType(cls);
     _worldBuilder.forEachInstanceField(cls,
         (ClassEntity enclosingClass, FieldEntity member) {
       var value = fieldValues[member];
@@ -339,9 +349,9 @@
 
       // If there are locals that escape (i.e. mutated in closures), we pass the
       // box to the constructor.
-      ClosureAnalysisInfo scopeData = closureToClassMapper
+      ClosureAnalysisInfo scopeData = closureDataLookup
           .getClosureAnalysisInfo(constructorElement.resolvedAst.node);
-      if (scopeData.requiresContextBox()) {
+      if (scopeData.requiresContextBox) {
         bodyCallInputs.add(localsHandler.readLocal(scopeData.context));
       }
 
@@ -595,22 +605,18 @@
 
     // Set the locals handler state as if we were inlining the constructor.
     ConstructorEntity astElement = _elementMap.getConstructor(constructor);
-    ClosureClassMap oldClosureData = localsHandler.closureData;
-    ClosureClassMap newClosureData =
-        closureToClassMapper.getMemberMap(astElement);
+    ClosureRepresentationInfo oldClosureData = localsHandler.closureData;
+    ClosureRepresentationInfo newClosureData =
+        closureDataLookup.getClosureRepresentationInfo(astElement);
     if (astElement is ConstructorElement) {
       // TODO(johnniwinther): Support constructor (body) entities.
       ResolvedAst resolvedAst = astElement.resolvedAst;
       localsHandler.closureData = newClosureData;
       if (resolvedAst.kind == ResolvedAstKind.PARSED) {
-        // TODO(efortuna): Take out the test below for null once we are no
-        // longer dealing with the ClosureClassMap interface directly.
-        if (newClosureData.capturingScopes[resolvedAst.node] != null) {
-          localsHandler.enterScope(
-              newClosureData.capturingScopes[resolvedAst.node],
-              forGenerativeConstructorBody:
-                  astElement.isGenerativeConstructorBody);
-        }
+        localsHandler.enterScope(
+            closureDataLookup.getClosureAnalysisInfo(resolvedAst.node),
+            forGenerativeConstructorBody:
+                astElement.isGenerativeConstructorBody);
       }
     }
     inlinedFrom(astElement, () {
@@ -697,10 +703,11 @@
     HBasicBlock block = graph.addNewBlock();
     open(graph.entry);
 
-    ClosureClassMap closureData =
-        closureToClassMapper.getMemberMap(targetElement);
-    localsHandler.startFunction(targetElement, closureData,
-        closureData.capturingScopes[functionNode], parameterMap,
+    localsHandler.startFunction(
+        targetElement,
+        closureDataLookup.getClosureRepresentationInfo(targetElement),
+        closureDataLookup.getClosureAnalysisInfo(functionNode),
+        parameterMap,
         isGenerativeConstructorBody: _targetIsConstructorBody);
     close(new HGoto()).addSuccessor(block);
 
@@ -756,7 +763,7 @@
   void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) {
     HInstruction prefixConstant =
         graph.addConstantString(checkLoad.import.name, closedWorld);
-    var prefixElement = astAdapter.getElement(checkLoad.import);
+    PrefixElement prefixElement = astAdapter.getElement(checkLoad.import);
     HInstruction uriConstant = graph.addConstantString(
         prefixElement.deferredImport.uri.toString(), closedWorld);
     _pushStaticInvocation(
@@ -903,7 +910,7 @@
     loopHandler.handleLoop(
         forStatement,
         localsMap.getClosureRepresentationInfoForLoop(
-            closureToClassMapper, forStatement),
+            closureDataLookup, forStatement),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1032,7 +1039,7 @@
     loopHandler.handleLoop(
         forInStatement,
         localsMap.getClosureRepresentationInfoForLoop(
-            closureToClassMapper, forInStatement),
+            closureDataLookup, forInStatement),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1083,7 +1090,7 @@
     loopHandler.handleLoop(
         forInStatement,
         localsMap.getClosureRepresentationInfoForLoop(
-            closureToClassMapper, forInStatement),
+            closureDataLookup, forInStatement),
         buildInitializer,
         buildCondition,
         () {},
@@ -1130,7 +1137,7 @@
     loopHandler.handleLoop(
         forInStatement,
         localsMap.getClosureRepresentationInfoForLoop(
-            closureToClassMapper, forInStatement),
+            closureDataLookup, forInStatement),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1181,7 +1188,7 @@
     loopHandler.handleLoop(
         whileStatement,
         localsMap.getClosureRepresentationInfoForLoop(
-            closureToClassMapper, whileStatement),
+            closureDataLookup, whileStatement),
         () {},
         buildCondition,
         () {}, () {
@@ -1195,7 +1202,7 @@
     // LoopHandler.handleLoop with some tricks about when the "update" happens.
     LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
     LoopClosureRepresentationInfo loopClosureInfo = localsMap
-        .getClosureRepresentationInfoForLoop(closureToClassMapper, doStatement);
+        .getClosureRepresentationInfoForLoop(closureDataLookup, doStatement);
     localsHandler.startLoop(loopClosureInfo);
     JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement);
     HLoopInformation loopInfo = current.loopInformation;
@@ -1297,7 +1304,9 @@
           null,
           loopEntryBlock.loopInformation.target,
           loopEntryBlock.loopInformation.labels,
-          sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement)));
+          // TODO(johnniwinther): Provide source information like:
+          // sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement))
+          null);
       loopEntryBlock.setBlockFlow(loopBlockInfo, current);
       loopInfo.loopBlockInformation = loopBlockInfo;
     } else {
@@ -1439,7 +1448,6 @@
   /// continue statements from simple switch statements.
   JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) {
     JumpTarget target = localsMap.getJumpTarget(node);
-    assert(target is KernelJumpTarget);
     if (target == null) {
       // No breaks or continues to this node.
       return new NullJumpHandler(reporter);
@@ -1716,7 +1724,7 @@
       loopHandler.handleLoop(
           switchStatement,
           localsMap.getClosureRepresentationInfoForLoop(
-              closureToClassMapper, switchStatement),
+              closureDataLookup, switchStatement),
           () {},
           buildCondition,
           () {},
@@ -2601,7 +2609,7 @@
 
     if (instruction is HConstant) {
       js.Name name =
-          astAdapter.getNameForJsGetName(argument, instruction.constant);
+          _elementMap.getNameForJsGetName(instruction.constant, namer);
       stack.add(graph.addConstantStringFromName(name, closedWorld));
       return;
     }
@@ -2653,7 +2661,8 @@
 
     js.Template template;
     if (instruction is HConstant) {
-      template = astAdapter.getJsBuiltinTemplate(instruction.constant);
+      template =
+          _elementMap.getJsBuiltinTemplate(instruction.constant, emitter);
     }
     if (template == null) {
       reporter.reportErrorMessage(
@@ -2717,8 +2726,8 @@
     if (argumentInstruction is HConstant) {
       ConstantValue argumentConstant = argumentInstruction.constant;
       if (argumentConstant is TypeConstantValue &&
-          argumentConstant.representedType is ResolutionInterfaceType) {
-        ResolutionInterfaceType type = argumentConstant.representedType;
+          argumentConstant.representedType is InterfaceType) {
+        InterfaceType type = argumentConstant.representedType;
         // TODO(sra): Check that type is a subclass of [Interceptor].
         ConstantValue constant = new InterceptorConstantValue(type.element);
         HInstruction instruction = graph.addConstant(constant, closedWorld);
@@ -2836,26 +2845,20 @@
   @override
   visitFunctionNode(ir.FunctionNode node) {
     Local methodElement = _elementMap.getLocalFunction(node);
-    ClosureClassMap nestedClosureData =
-        closureToClassMapper.getLocalFunctionMap(methodElement);
-    assert(nestedClosureData != null);
-    assert(nestedClosureData.closureClassElement != null);
-    ClosureClassElement closureClassElement =
-        nestedClosureData.closureClassElement;
-    MethodElement callElement = nestedClosureData.callElement;
+    ClosureRepresentationInfo closureInfo =
+        closureDataLookup.getClosureRepresentationInfo(methodElement);
+    ClassEntity closureClassEntity = closureInfo.closureClassEntity;
 
     List<HInstruction> capturedVariables = <HInstruction>[];
-    closureClassElement.closureFields.forEach((ClosureFieldElement field) {
-      Local capturedLocal =
-          nestedClosureData.getLocalVariableForClosureField(field);
+    closureInfo.createdFieldEntities.forEach((Local capturedLocal) {
       assert(capturedLocal != null);
       capturedVariables.add(localsHandler.readLocal(capturedLocal));
     });
 
-    TypeMask type = new TypeMask.nonNullExact(closureClassElement, closedWorld);
+    TypeMask type = new TypeMask.nonNullExact(closureClassEntity, closedWorld);
     // TODO(efortuna): Add source information here.
-    push(new HCreate(closureClassElement, capturedVariables, type,
-        callMethod: callElement, localFunction: methodElement));
+    push(new HCreate(closureClassEntity, capturedVariables, type,
+        callMethod: closureInfo.callMethod, localFunction: methodElement));
   }
 
   @override
@@ -3047,7 +3050,11 @@
       _addTypeArguments(arguments, invocation.arguments);
     }
     TypeMask typeMask = new TypeMask.nonNullExact(cls, closedWorld);
+    InterfaceType type = _elementMap.createInterfaceType(
+        target.enclosingClass, invocation.arguments.types);
+    addImplicitInstantiation(type);
     _pushStaticInvocation(constructor, arguments, typeMask);
+    removeImplicitInstantiation(type);
   }
 
   @override
@@ -3277,7 +3284,7 @@
   HBasicBlock exitBlock;
   HTry tryInstruction;
   HLocalValue exception;
-  KernelSsaBuilder kernelBuilder;
+  KernelSsaGraphBuilder kernelBuilder;
 
   /// True if the code surrounding this try statement was also part of a
   /// try/catch/finally statement.
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 57f36ec..b199ce5 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../closure.dart' show ClosureClassMaps;
+import '../closure.dart' show ClosureDataLookup;
 import '../constants/constant_system.dart';
 import '../common/codegen.dart' show CodegenRegistry;
 import '../common_elements.dart';
@@ -72,7 +72,7 @@
   GlobalTypeInferenceResults get globalInferenceResults =>
       compiler.globalInference.results;
 
-  ClosureClassMaps get closureToClassMapper => compiler.closureToClassMapper;
+  ClosureDataLookup get closureDataLookup => compiler.closureDataLookup;
 
   NativeData get nativeData => closedWorld.nativeData;
 
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index cde68b7..c092992 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -71,7 +71,7 @@
 
   bool visitInvoke(HInvoke invoke) {
     if (!invoke.isInterceptedCall) return false;
-    var interceptor = invoke.inputs[0];
+    dynamic interceptor = invoke.inputs[0];
     if (interceptor is! HInterceptor) return false;
 
     // TODO(sra): Move this per-call code to visitInterceptor.
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index bb78b62..7f02cf9 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:js_runtime/shared/embedded_names.dart';
 import 'package:kernel/ast.dart' as ir;
 
 import '../closure.dart';
@@ -17,7 +16,6 @@
 import '../elements/modelx.dart';
 import '../elements/resolution_types.dart';
 import '../elements/types.dart';
-import '../js/js.dart' as js;
 import '../js_backend/js_backend.dart';
 import '../kernel/element_map.dart';
 import '../kernel/kernel.dart';
@@ -111,7 +109,7 @@
 
   /// Called to find the corresponding Kernel element for a particular Element
   /// before traversing over it with a Kernel visitor.
-  ir.Node getInitialKernelNode(MemberElement originTarget) {
+  ir.Node getMemberNode(MemberElement originTarget) {
     ir.Node target;
     if (originTarget.isPatch) {
       originTarget = originTarget.origin;
@@ -125,10 +123,10 @@
       // Closures require a lookup one level deeper in the closure class mapper.
       if (target == null) {
         MethodElement originTargetFunction = originTarget;
-        ClosureClassMap classMap = _compiler.closureToClassMapper
-            .getClosureToClassMapping(originTargetFunction);
-        if (classMap.closureElement != null) {
-          target = kernel.localFunctions[classMap.closureElement];
+        ClosureRepresentationInfo classMap = _compiler.closureDataLookup
+            .getClosureRepresentationInfo(originTargetFunction);
+        if (classMap.closureEntity != null) {
+          target = kernel.localFunctions[classMap.closureEntity];
         }
       }
     } else if (originTarget is FieldElement) {
@@ -241,35 +239,6 @@
     });
   }
 
-  js.Name getNameForJsGetName(ir.Node argument, ConstantValue constant) {
-    int index = _extractEnumIndexFromConstantValue(
-        constant, _compiler.resolution.commonElements.jsGetNameEnum);
-    if (index == null) return null;
-    return _backend.namer
-        .getNameForJsGetName(getNode(argument), JsGetName.values[index]);
-  }
-
-  js.Template getJsBuiltinTemplate(ConstantValue constant) {
-    int index = _extractEnumIndexFromConstantValue(
-        constant, _compiler.resolution.commonElements.jsBuiltinEnum);
-    if (index == null) return null;
-    return _backend.emitter.builtinTemplateFor(JsBuiltin.values[index]);
-  }
-
-  int _extractEnumIndexFromConstantValue(
-      ConstantValue constant, ClassEntity classElement) {
-    if (constant is ConstructedConstantValue) {
-      if (constant.type.element == classElement) {
-        assert(constant.fields.length == 1 || constant.fields.length == 2);
-        ConstantValue indexConstant = constant.fields.values.first;
-        if (indexConstant is IntConstantValue) {
-          return indexConstant.primitiveValue;
-        }
-      }
-    }
-    return null;
-  }
-
   DartType getDartType(ir.DartType type) {
     return _typeConverter.convert(type);
   }
@@ -327,8 +296,8 @@
 
   @override
   LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
-      ClosureClassMaps closureClassMaps, ir.TreeNode node) {
-    return closureClassMaps.getClosureRepresentationInfoForLoop(getNode(node));
+      ClosureDataLookup closureLookup, ir.TreeNode node) {
+    return closureLookup.getClosureRepresentationInfoForLoop(getNode(node));
   }
 }
 
@@ -444,14 +413,14 @@
   KernelJumpTarget(this.targetStatement, KernelAstAdapter adapter,
       {bool makeContinueLabel = false}) {
     originalStatement = targetStatement;
-    this.labels = <LabelDefinition>[];
+    this.labels = <LabelDefinition<ast.Node>>[];
     if (targetStatement is ir.WhileStatement ||
         targetStatement is ir.DoStatement ||
         targetStatement is ir.ForStatement ||
         targetStatement is ir.ForInStatement) {
       // Currently these labels are set at resolution on the element itself.
       // Once that gets updated, this logic can change downstream.
-      JumpTarget target = adapter.elements
+      JumpTarget<ast.Node> target = adapter.elements
           .getTargetDefinition(adapter.getNode(targetStatement));
       if (target != null) {
         labels.addAll(target.labels);
@@ -480,7 +449,7 @@
   }
 
   @override
-  LabelDefinition addLabel(ast.Label label, String labelName) {
+  LabelDefinition<ast.Node> addLabel(ast.Label label, String labelName) {
     LabelDefinition result = new LabelDefinitionX(label, labelName, this);
     labels.add(result);
     return result;
@@ -499,13 +468,13 @@
   bool get isTarget => isBreakTarget || isContinueTarget;
 
   @override
-  List<LabelDefinition> labels;
+  List<LabelDefinition<ast.Node>> labels;
 
   @override
   String get name => 'target';
 
   @override
-  ast.Node get statement => null;
+  ast.Label get statement => null;
 
   String toString() => 'Target:$targetStatement';
 }
diff --git a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
index f051ba0..920b61c 100644
--- a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
@@ -11,7 +11,7 @@
 
 /// Visits and concatenates the expressions in a string concatenation.
 class KernelStringBuilder extends ir.Visitor {
-  final KernelSsaBuilder builder;
+  final KernelSsaGraphBuilder builder;
   KernelAstAdapter get astAdapter => builder.astAdapter;
 
   /// The string value generated so far.
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index b55cded..dd6ce4f 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -32,7 +32,7 @@
   Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>();
   Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>();
   final GraphBuilder builder;
-  ClosureClassMap closureData;
+  ClosureRepresentationInfo closureData;
   Map<TypeVariableType, TypeVariableLocal> typeVariableLocals =
       new Map<TypeVariableType, TypeVariableLocal>();
   final Entity executableContext;
@@ -140,7 +140,7 @@
       {bool forGenerativeConstructorBody: false}) {
     // See if any variable in the top-scope of the function is captured. If yes
     // we need to create a box-object.
-    if (!closureInfo.requiresContextBox()) return;
+    if (!closureInfo.requiresContextBox) return;
     HInstruction box;
     // The scope has captured variables.
     if (forGenerativeConstructorBody) {
@@ -154,8 +154,9 @@
     directLocals[closureInfo.context] = box;
     // Make sure that accesses to the boxed locals go into the box. We also
     // need to make sure that parameters are copied into the box if necessary.
-    closureInfo.forEachCapturedVariable(
-        (LocalVariableElement from, BoxFieldElement to) {
+    closureInfo.forEachCapturedVariable((_from, _to) {
+      LocalVariableElement from = _from;
+      BoxFieldElement to = _to;
       // The [from] can only be a parameter for function-scopes and not
       // loop scopes.
       if (from.isRegularParameter && !forGenerativeConstructorBody) {
@@ -196,8 +197,11 @@
   /// Documentation wanted -- johnniwinther
   ///
   /// Invariant: [function] must be an implementation element.
-  void startFunction(MemberEntity element, ClosureClassMap closureData,
-      ClosureScope scopeData, Map<Local, TypeMask> parameters,
+  void startFunction(
+      MemberEntity element,
+      ClosureRepresentationInfo closureData,
+      ClosureAnalysisInfo scopeData,
+      Map<Local, TypeMask> parameters,
       {bool isGenerativeConstructorBody}) {
     assert(!(element is MemberElement && !element.isImplementation),
         failedAt(element));
@@ -205,7 +209,7 @@
 
     parameters.forEach((Local local, TypeMask typeMask) {
       if (isGenerativeConstructorBody) {
-        if (scopeData != null && scopeData.isCaptured(local)) {
+        if (scopeData.isCaptured(local)) {
           // The parameter will be a field in the box passed as the
           // last parameter. So no need to have it.
           return;
@@ -216,14 +220,8 @@
       directLocals[local] = parameter;
     });
 
-    if (scopeData != null) {
-      // TODO(efortuna): Remove the above if wrapper (always execute this step)
-      // when the switch away from ClosureClassMap is complete (prior behavior
-      // in enterScope it was acceptable to pass in a null scopeData, but no
-      // longer).
-      enterScope(scopeData,
-          forGenerativeConstructorBody: isGenerativeConstructorBody);
-    }
+    enterScope(scopeData,
+        forGenerativeConstructorBody: isGenerativeConstructorBody);
 
     // If the freeVariableMapping is not empty, then this function was a
     // nested closure that captures variables. Redirect the captured
@@ -237,7 +235,7 @@
           new HThis(closureData.thisLocal, commonMasks.nonNullType);
       builder.graph.thisInstruction = thisInstruction;
       builder.graph.entry.addAtEntry(thisInstruction);
-      updateLocal(closureData.closureElement, thisInstruction);
+      updateLocal(closureData.closureEntity, thisInstruction);
     } else if (element.isInstanceMember) {
       // Once closures have been mapped to classes their instance members might
       // not have any thisElement if the closure was created inside a static
@@ -295,7 +293,7 @@
   bool isAccessedDirectly(Local local) {
     assert(local != null);
     return !redirectionMapping.containsKey(local) &&
-        !closureData.variablesUsedInTryOrGenerator.contains(local);
+        !closureData.variableIsUsedInTryOrSync(local);
   }
 
   bool isStoredInClosureField(Local local) {
@@ -313,7 +311,7 @@
   }
 
   bool isUsedInTryOrGenerator(Local local) {
-    return closureData.variablesUsedInTryOrGenerator.contains(local);
+    return closureData.variableIsUsedInTryOrSync(local);
   }
 
   /// Returns an [HInstruction] for the given element. If the element is
@@ -342,7 +340,7 @@
       return value;
     } else if (isStoredInClosureField(local)) {
       ClosureFieldElement redirect = redirectionMapping[local];
-      HInstruction receiver = readLocal(closureData.closureElement);
+      HInstruction receiver = readLocal(closureData.closureEntity);
       TypeMask type = local is BoxLocal
           ? commonMasks.nonNullType
           : getTypeOfCapturedVariable(redirect);
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index a122783..3ce6289 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -308,9 +308,9 @@
 
 /// A loop handler for the builder that just uses AST nodes directly.
 class SsaLoopHandler extends LoopHandler<ast.Node> {
-  final SsaBuilder builder;
+  final SsaAstGraphBuilder builder;
 
-  SsaLoopHandler(SsaBuilder builder)
+  SsaLoopHandler(SsaAstGraphBuilder builder)
       : this.builder = builder,
         super(builder);
 
@@ -346,11 +346,11 @@
 // TODO(het): Since kernel simplifies loop breaks and continues, we should
 // rewrite the loop handler from scratch to account for the simplified structure
 class KernelLoopHandler extends LoopHandler<ir.TreeNode> {
-  final KernelSsaBuilder builder;
+  final KernelSsaGraphBuilder builder;
 
   KernelAstAdapter get astAdapter => builder.astAdapter;
 
-  KernelLoopHandler(KernelSsaBuilder builder)
+  KernelLoopHandler(KernelSsaGraphBuilder builder)
       : this.builder = builder,
         super(builder);
 
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 371d76d..5ac6bc1 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1211,8 +1211,8 @@
   // These methods should be overwritten by instructions that
   // participate in global value numbering.
   int typeCode() => HInstruction.UNDEFINED_TYPECODE;
-  bool typeEquals(HInstruction other) => false;
-  bool dataEquals(HInstruction other) => false;
+  bool typeEquals(covariant HInstruction other) => false;
+  bool dataEquals(covariant HInstruction other) => false;
 
   accept(HVisitor visitor);
 
@@ -1695,11 +1695,11 @@
   HInvokeDynamic(Selector selector, this.mask, this.element,
       List<HInstruction> inputs, TypeMask type,
       [bool isIntercepted = false])
-      : super(inputs, type),
-        this.selector = selector,
+      : this.selector = selector,
         specializer = isIntercepted
             ? InvokeDynamicSpecializer.lookupSpecializer(selector)
-            : const InvokeDynamicSpecializer();
+            : const InvokeDynamicSpecializer(),
+        super(inputs, type);
   toString() => 'invoke dynamic: selector=$selector, mask=$mask';
   HInstruction get receiver => inputs[0];
   HInstruction getDartReceiver(ClosedWorld closedWorld) {
@@ -2512,7 +2512,7 @@
   HThis(ThisLocal element, TypeMask type) : super(element, type);
 
   ThisLocal get sourceElement => super.sourceElement;
-  void set sourceElement(ThisLocal local) {
+  void set sourceElement(covariant ThisLocal local) {
     super.sourceElement = local;
   }
 
@@ -3001,8 +3001,8 @@
   HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
       TypeMask type, HInstruction input, HInstruction typeRepresentation)
       : checkedType = type,
-        super(<HInstruction>[input, typeRepresentation], type),
-        receiverTypeCheckSelector = null {
+        receiverTypeCheckSelector = null,
+        super(<HInstruction>[input, typeRepresentation], type) {
     assert(!typeExpression.isTypedef);
     sourceElement = input.sourceElement;
   }
@@ -3010,8 +3010,8 @@
   HTypeConversion.viaMethodOnType(this.typeExpression, this.kind, TypeMask type,
       HInstruction reifiedType, HInstruction input)
       : checkedType = type,
-        super(<HInstruction>[reifiedType, input], type),
-        receiverTypeCheckSelector = null {
+        receiverTypeCheckSelector = null,
+        super(<HInstruction>[reifiedType, input], type) {
     // This form is currently used only for function types.
     assert(typeExpression.isFunctionType);
     assert(kind == CHECKED_MODE_CHECK || kind == CAST_TYPE_CHECK);
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index b4a059b..3a0b393 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -482,7 +482,7 @@
         // [:noSuchMethod:] we just ignore it.
         &&
         node.selector.applies(element)) {
-      MethodElement method = element;
+      FunctionEntity method = element;
 
       if (_nativeData.isNativeMember(method)) {
         HInstruction folded = tryInlineNativeMethod(node, method);
@@ -490,11 +490,9 @@
       } else {
         // TODO(ngeoffray): If the method has optional parameters,
         // we should pass the default values.
-        ResolutionFunctionType type = method.type;
-        int optionalParameterCount =
-            type.optionalParameterTypes.length + type.namedParameters.length;
-        if (optionalParameterCount == 0 ||
-            type.parameterTypes.length + optionalParameterCount ==
+        ParameterStructure parameters = method.parameterStructure;
+        if (parameters.optionalParameters == 0 ||
+            parameters.requiredParameters + parameters.optionalParameters ==
                 node.selector.argumentCount) {
           node.element = method;
         }
@@ -923,7 +921,7 @@
   }
 
   HInstruction visitGetLength(HGetLength node) {
-    var receiver = node.receiver;
+    dynamic receiver = node.receiver;
     if (_graph.allocatedFixedLists.contains(receiver)) {
       // TODO(ngeoffray): checking if the second input is an integer
       // should not be necessary but it currently makes it easier for
@@ -935,7 +933,7 @@
     } else if (receiver.isConstantList() || receiver.isConstantString()) {
       return _graph.addConstantInt(receiver.constant.length, _closedWorld);
     } else {
-      var type = receiver.instructionType;
+      dynamic type = receiver.instructionType;
       if (type.isContainer && type.length != null) {
         HInstruction constant =
             _graph.addConstantInt(type.length, _closedWorld);
@@ -963,7 +961,7 @@
 
   HInstruction visitIndex(HIndex node) {
     if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
-      var instruction = node.receiver;
+      dynamic instruction = node.receiver;
       List<ConstantValue> entries = instruction.constant.entries;
       instruction = node.index;
       int index = instruction.constant.primitiveValue;
@@ -1025,14 +1023,16 @@
     }
 
     HInstruction receiver = node.getDartReceiver(_closedWorld);
-    FieldElement field =
+    FieldEntity field =
         findConcreteFieldForDynamicAccess(receiver, node.selector);
     if (field == null || !field.isAssignable) return node;
     // Use `node.inputs.last` in case the call follows the interceptor calling
     // convention, but is not a call on an interceptor.
     HInstruction value = node.inputs.last;
     if (_options.enableTypeAssertions) {
-      ResolutionDartType type = field.type;
+      // TODO(johnniwinther): Support field entities.
+      FieldElement element = field;
+      DartType type = element.type;
       if (!type.treatAsRaw ||
           type.isTypeVariable ||
           type.unaliased.isFunctionType) {
diff --git a/pkg/compiler/lib/src/ssa/rasta_ssa_builder_task.dart b/pkg/compiler/lib/src/ssa/rasta_ssa_builder_task.dart
index 002d204..c47b4f9 100644
--- a/pkg/compiler/lib/src/ssa/rasta_ssa_builder_task.dart
+++ b/pkg/compiler/lib/src/ssa/rasta_ssa_builder_task.dart
@@ -1,6 +1,8 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
+import '../common/tasks.dart';
 import '../elements/elements.dart';
 import '../io/source_information.dart';
 import '../js_backend/backend.dart' show JavaScriptBackend;
@@ -13,17 +15,18 @@
 import 'builder_kernel.dart';
 
 /// Task for building SSA kernel IR generated from rasta.
-class RastaSsaBuilderTask extends SsaAstBuilderBase {
+class RastaSsaBuilder extends SsaAstBuilderBase {
   final SourceInformationStrategy sourceInformationFactory;
 
   String get name => 'SSA kernel builder';
 
-  RastaSsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory)
-      : super(backend);
+  RastaSsaBuilder(CompilerTask task, JavaScriptBackend backend,
+      this.sourceInformationFactory)
+      : super(task, backend);
 
-  HGraph build(ElementCodegenWorkItem work, ClosedWorld closedWorld) {
-    return measure(() {
-      if (handleConstantField(work, closedWorld)) {
+  HGraph build(covariant ElementCodegenWorkItem work, ClosedWorld closedWorld) {
+    return task.measure(() {
+      if (handleConstantField(work.element, work.registry, closedWorld)) {
         // No code is generated for `work.element`.
         return null;
       }
@@ -34,10 +37,10 @@
           work.resolvedAst, kernel.nodeToAst, kernel.nodeToElement);
       KernelAstTypeInferenceMap typeInferenceMap =
           new KernelAstTypeInferenceMap(astAdapter);
-      KernelSsaBuilder builder = new KernelSsaBuilder(
+      KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
           element,
           element.contextClass,
-          astAdapter.getInitialKernelNode(element),
+          astAdapter.getMemberNode(element),
           backend.compiler,
           astAdapter,
           typeInferenceMap,
@@ -45,7 +48,7 @@
           closedWorld,
           backend.compiler.codegenWorldBuilder,
           work.registry,
-          backend.compiler.closureToClassMapper,
+          backend.compiler.closureDataLookup,
           sourceInformationFactory.createBuilderForContext(work.element),
           resolvedAst.kind == ResolvedAstKind.PARSED ? resolvedAst.node : null,
           targetIsConstructorBody: element is ConstructorBodyElement);
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index ba197d1..c36361c 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -4,13 +4,16 @@
 
 library ssa;
 
-import '../common/codegen.dart' show CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem, CodegenRegistry;
 import '../common/tasks.dart' show CompilerTask, Measurer;
+import '../constants/values.dart';
 import '../elements/elements.dart' show MethodElement;
-import '../elements/entities.dart' show MemberEntity;
+import '../elements/entities.dart' show FieldEntity, MemberEntity;
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
+import '../universe/call_structure.dart';
+import '../universe/use.dart';
 import '../world.dart' show ClosedWorld;
 
 import 'codegen.dart';
@@ -26,11 +29,14 @@
   SsaFunctionCompiler(JavaScriptBackend backend, Measurer measurer,
       SourceInformationStrategy sourceInformationFactory)
       : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
-        _builder = backend.compiler.backendStrategy
-            .createSsaBuilderTask(backend, sourceInformationFactory),
+        _builder = new SsaBuilderTask(backend, sourceInformationFactory),
         optimizer = new SsaOptimizerTask(backend),
         backend = backend;
 
+  void onCodegenStart() {
+    _builder.onCodegenStart();
+  }
+
   /// Generates JavaScript code for `work.element`.
   /// Using the ssa builder, optimizer and codegenerator.
   js.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld) {
@@ -52,8 +58,69 @@
   }
 }
 
-abstract class SsaBuilderTask implements CompilerTask {
+abstract class SsaBuilder {
   /// Creates the [HGraph] for [work] or returns `null` if no code is needed
   /// for [work].
   HGraph build(CodegenWorkItem work, ClosedWorld closedWorld);
 }
+
+class SsaBuilderTask extends CompilerTask {
+  final JavaScriptBackend _backend;
+  final SourceInformationStrategy _sourceInformationFactory;
+  SsaBuilder _builder;
+
+  SsaBuilderTask(this._backend, this._sourceInformationFactory)
+      : super(_backend.compiler.measurer);
+
+  void onCodegenStart() {
+    _builder = _backend.compiler.backendStrategy
+        .createSsaBuilder(this, _backend, _sourceInformationFactory);
+  }
+
+  /// Creates the [HGraph] for [work] or returns `null` if no code is needed
+  /// for [work].
+  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
+    return _builder.build(work, closedWorld);
+  }
+}
+
+abstract class SsaBuilderFieldMixin {
+  ConstantValue getFieldInitialConstantValue(covariant FieldEntity field);
+
+  /// Handle field initializer of [element]. Returns `true` if no code
+  /// is needed for the field.
+  ///
+  /// If [element] is a field with a constant initializer, the value is
+  /// registered with the world impact. Otherwise the cyclic-throw helper is
+  /// registered for the lazy value computation.
+  ///
+  /// If the field is constant, no code is needed for the field and the method
+  /// returns `true`.
+  bool handleConstantField(
+      MemberEntity element, CodegenRegistry registry, ClosedWorld closedWorld) {
+    if (element.isField) {
+      ConstantValue initialValue = getFieldInitialConstantValue(element);
+      if (initialValue != null) {
+        registry.worldImpact
+            .registerConstantUse(new ConstantUse.init(initialValue));
+        // We don't need to generate code for static or top-level
+        // variables. For instance variables, we may need to generate
+        // the checked setter.
+        if (element.isStatic || element.isTopLevel) {
+          /// No code is created for this field: All references inline the
+          /// constant value.
+          return true;
+        }
+      } else {
+        // If the constant-handler was not able to produce a result we have to
+        // go through the builder (below) to generate the lazy initializer for
+        // the static variable.
+        // We also need to register the use of the cyclic-error helper.
+        registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
+            closedWorld.commonElements.cyclicThrowHelper,
+            CallStructure.ONE_ARG));
+      }
+    }
+    return false;
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 028157a..a565bd2 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -214,7 +214,8 @@
     if (!checkOrTrustTypes) return;
 
     FunctionSignature signature = function.functionSignature;
-    signature.orderedForEachParameter((ParameterElement parameter) {
+    signature.orderedForEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
       HInstruction argument = builder.localsHandler.readLocal(parameter);
       potentiallyCheckOrTrustType(argument, parameter.type);
     });
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 9ebbc55..29cc9ab 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -4,6 +4,7 @@
 
 import '../common_elements.dart' show CommonElements;
 import '../elements/elements.dart';
+import '../elements/entities.dart';
 import '../native/native.dart' as native;
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
@@ -17,7 +18,11 @@
   }
 
   static TypeMask inferredTypeForMember(
-      MemberElement element, GlobalTypeInferenceResults results) {
+      MemberEntity element, GlobalTypeInferenceResults results) {
+    // TODO(johnniwinther): Support inferred types for member entities.
+    if (element is! MemberElement) {
+      return results.closedWorld.commonMasks.dynamicType;
+    }
     return results.resultOfMember(element).type ??
         results.closedWorld.commonMasks.dynamicType;
   }
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 49e27f61..e13b834 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -132,21 +132,21 @@
 
   const IntValue(this.value, info) : super(info);
 
-  Value operator +(other) {
+  Value operator +(dynamic other) {
     if (other.isZero) return this;
     if (other is! IntValue) return other + this;
     ConstantSystem constantSystem = info.constantSystem;
-    var constant = constantSystem.add.fold(
+    dynamic constant = constantSystem.add.fold(
         constantSystem.createInt(value), constantSystem.createInt(other.value));
     if (!constant.isInt) return const UnknownValue();
     return info.newIntValue(constant.primitiveValue);
   }
 
-  Value operator -(other) {
+  Value operator -(dynamic other) {
     if (other.isZero) return this;
     if (other is! IntValue) return -other + this;
     ConstantSystem constantSystem = info.constantSystem;
-    var constant = constantSystem.subtract.fold(
+    dynamic constant = constantSystem.subtract.fold(
         constantSystem.createInt(value), constantSystem.createInt(other.value));
     if (!constant.isInt) return const UnknownValue();
     return info.newIntValue(constant.primitiveValue);
@@ -155,25 +155,26 @@
   Value operator -() {
     if (isZero) return this;
     ConstantSystem constantSystem = info.constantSystem;
-    var constant = constantSystem.negate.fold(constantSystem.createInt(value));
+    dynamic constant =
+        constantSystem.negate.fold(constantSystem.createInt(value));
     if (!constant.isInt) return const UnknownValue();
     return info.newIntValue(constant.primitiveValue);
   }
 
-  Value operator &(other) {
+  Value operator &(dynamic other) {
     if (other is! IntValue) return const UnknownValue();
     ConstantSystem constantSystem = info.constantSystem;
-    var constant = constantSystem.bitAnd.fold(
+    dynamic constant = constantSystem.bitAnd.fold(
         constantSystem.createInt(value), constantSystem.createInt(other.value));
     return info.newIntValue(constant.primitiveValue);
   }
 
-  Value min(other) {
+  Value min(dynamic other) {
     if (other is! IntValue) return other.min(this);
     return this.value < other.value ? this : other;
   }
 
-  Value max(other) {
+  Value max(dynamic other) {
     if (other is! IntValue) return other.max(this);
     return this.value < other.value ? other : this;
   }
@@ -969,7 +970,7 @@
   }
 
   Range visitConditionalBranch(HConditionalBranch branch) {
-    var condition = branch.condition;
+    dynamic condition = branch.condition;
     // TODO(ngeoffray): Handle complex conditions.
     if (condition is! HRelational) return info.newUnboundRange();
     if (condition is HIdentity) return info.newUnboundRange();
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 57c5724..ad6140a 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -243,7 +243,7 @@
   // When looking for the checkedInstructionOrNonGenerateAtUseSite of t3 we must
   // return t2.
   HInstruction checkedInstructionOrNonGenerateAtUseSite(HCheck check) {
-    var checked = check.checkedInput;
+    dynamic checked = check.checkedInput;
     while (checked is HCheck) {
       HInstruction next = checked.checkedInput;
       if (generateAtUseSite.contains(next)) break;
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index a4478e7..6f4f91e 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -25,12 +25,12 @@
         EnumConstantElement,
         ExecutableElement,
         FieldElement,
+        FormalElement,
         FunctionElement,
         GetterElement,
         InitializingFormalElement,
         LibraryElement,
         MemberSignature,
-        ParameterElement,
         ResolvedAst,
         SetterElement,
         TypeDeclarationElement,
@@ -654,7 +654,7 @@
       type = const ResolutionDynamicType();
       returnType = const ResolutionVoidType();
 
-      element.functionSignature.forEachParameter((ParameterElement parameter) {
+      element.functionSignature.forEachParameter((FormalElement parameter) {
         if (parameter.isInitializingFormal) {
           InitializingFormalElement fieldParameter = parameter;
           checkAssignable(parameter, parameter.type,
@@ -1685,7 +1685,7 @@
   /** Dart Programming Language Specification: 11.10 Return */
   visitReturn(Return node) {
     if (identical(node.beginToken.stringValue, 'native')) {
-      return;
+      return null;
     }
 
     final Node expression = node.expression;
diff --git a/pkg/compiler/lib/src/types/container_type_mask.dart b/pkg/compiler/lib/src/types/container_type_mask.dart
index edad3af..cd5697a 100644
--- a/pkg/compiler/lib/src/types/container_type_mask.dart
+++ b/pkg/compiler/lib/src/types/container_type_mask.dart
@@ -56,7 +56,7 @@
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
diff --git a/pkg/compiler/lib/src/types/dictionary_type_mask.dart b/pkg/compiler/lib/src/types/dictionary_type_mask.dart
index fc7a8a5..0c4bd80 100644
--- a/pkg/compiler/lib/src/types/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/types/dictionary_type_mask.dart
@@ -53,7 +53,7 @@
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 7a1dea2..1bd4289 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -526,7 +526,8 @@
     }
   }
 
-  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
+  bool needsNoSuchMethodHandling(
+      Selector selector, covariant ClosedWorld closedWorld) {
     // A call on an empty type mask is either dead code, or a call on
     // `null`.
     if (isEmptyOrNull) return false;
diff --git a/pkg/compiler/lib/src/types/forwarding_type_mask.dart b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
index 04ee5c0..974f255 100644
--- a/pkg/compiler/lib/src/types/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
@@ -93,7 +93,8 @@
     return forwardTo.intersection(other, closedWorld);
   }
 
-  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
+  bool needsNoSuchMethodHandling(
+      Selector selector, covariant ClosedWorld closedWorld) {
     return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
   }
 
diff --git a/pkg/compiler/lib/src/types/map_type_mask.dart b/pkg/compiler/lib/src/types/map_type_mask.dart
index 1ff8566..4fe6a79 100644
--- a/pkg/compiler/lib/src/types/map_type_mask.dart
+++ b/pkg/compiler/lib/src/types/map_type_mask.dart
@@ -59,7 +59,7 @@
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index 2832b75..b5ace96 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -96,7 +96,7 @@
     bool useSubclass = masks.every((e) => !e.isSubtype);
     bool isNullable = masks.any((e) => e.isNullable);
 
-    List masksBases = masks.map((mask) => mask.base).toList();
+    List<ClassEntity> masksBases = masks.map((mask) => mask.base).toList();
     Iterable<ClassEntity> candidates =
         closedWorld.commonSupertypesOf(masksBases);
 
@@ -137,7 +137,7 @@
     return new TypeMask(bestElement, bestKind, isNullable, closedWorld);
   }
 
-  TypeMask union(var other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return this;
 
@@ -151,7 +151,7 @@
     return new TypeMask.unionOf(newList, closedWorld);
   }
 
-  TypeMask intersection(var other, ClosedWorld closedWorld) {
+  TypeMask intersection(dynamic other, ClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return other;
     if (other.isUnion && this == other) return this;
@@ -189,8 +189,10 @@
 
   TypeMask nonNullable() {
     if (!isNullable) return this;
-    Iterable<FlatTypeMask> newIterable =
-        disjointMasks.map((e) => e.nonNullable());
+    Iterable<FlatTypeMask> newIterable = disjointMasks.map((e) {
+      FlatTypeMask r = e.nonNullable();
+      return r;
+    });
     return new UnionTypeMask._internal(newIterable);
   }
 
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 9df3c2d..13a0cdb 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -343,7 +343,8 @@
       {bool instantiatedOnly: false,
       bool sorted: true,
       ClassElement withRespectTo}) {
-    bool isRelatedTo(ClassElement subclass) {
+    bool isRelatedTo(ClassEntity _subclass) {
+      ClassElement subclass = _subclass;
       return subclass == withRespectTo ||
           subclass.implementsInterface(withRespectTo);
     }
@@ -366,7 +367,7 @@
     if (_directSubclasses.isEmpty) {
       sb.write(']');
     } else {
-      var subclasses = _directSubclasses;
+      dynamic subclasses = _directSubclasses;
       if (sorted) {
         subclasses = _directSubclasses.toList()
           ..sort((a, b) {
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 7fb0523..bc80c65 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -10,13 +10,13 @@
 abstract class CodegenWorldBuilder implements WorldBuilder {
   /// Calls [f] with every instance field, together with its declarer, in an
   /// instance of [cls].
-  void forEachInstanceField(
-      ClassEntity cls, void f(ClassEntity declarer, FieldEntity field));
+  void forEachInstanceField(covariant ClassEntity cls,
+      void f(ClassEntity declarer, FieldEntity field));
 
   /// Calls [f] for each parameter of [function] providing the type and name of
-  /// the parameter.
-  void forEachParameter(
-      FunctionEntity function, void f(DartType type, String name));
+  /// the parameter and the [defaultValue] if the parameter is optional.
+  void forEachParameter(covariant FunctionEntity function,
+      void f(DartType type, String name, ConstantValue defaultValue));
 
   void forEachInvokedName(
       f(String name, Map<Selector, SelectorConstraints> selectors));
@@ -27,6 +27,12 @@
   void forEachInvokedSetter(
       f(String name, Map<Selector, SelectorConstraints> selectors));
 
+  /// Returns `true` if [field] has a constant initializer.
+  bool hasConstantFieldInitializer(covariant FieldEntity field);
+
+  /// Returns the constant initializer for [field].
+  ConstantValue getConstantFieldInitializer(covariant FieldEntity field);
+
   /// Returns `true` if [member] is invoked as a setter.
   bool hasInvokedSetter(MemberEntity member, ClosedWorld world);
 
@@ -320,7 +326,7 @@
     _invokedSetters.forEach(f);
   }
 
-  void registerIsCheck(DartType type) {
+  void registerIsCheck(covariant DartType type) {
     isChecks.add(type.unaliased);
   }
 
@@ -417,14 +423,14 @@
     });
   }
 
-  void _processInstantiatedClassMember(
-      ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed) {
+  void _processInstantiatedClassMember(ClassEntity cls,
+      covariant MemberEntity member, MemberUsedCallback memberUsed) {
     if (!member.isInstanceMember) return;
     _getMemberUsage(member, memberUsed);
   }
 
   _MemberUsage _getMemberUsage(
-      MemberEntity member, MemberUsedCallback memberUsed) {
+      covariant MemberEntity member, MemberUsedCallback memberUsed) {
     return _instanceMemberUsage.putIfAbsent(member, () {
       String memberName = member.name;
       ClassEntity cls = member.enclosingClass;
@@ -542,7 +548,10 @@
 }
 
 class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
+  final JavaScriptConstantCompiler _constants;
+
   ElementCodegenWorldBuilderImpl(
+      this._constants,
       ElementEnvironment elementEnvironment,
       NativeBasicData nativeBasicData,
       ClosedWorld world,
@@ -550,6 +559,18 @@
       : super(elementEnvironment, nativeBasicData, world,
             selectorConstraintsStrategy);
 
+  @override
+  bool hasConstantFieldInitializer(FieldElement field) {
+    return field.constant != null;
+  }
+
+  @override
+  ConstantValue getConstantFieldInitializer(FieldElement field) {
+    assert(field.constant != null,
+        failedAt(field, "Field $field doesn't have a constant initial value."));
+    return _constants.getConstantValue(field.constant);
+  }
+
   /// Calls [f] with every instance field, together with its declarer, in an
   /// instance of [cls].
   void forEachInstanceField(
@@ -559,11 +580,18 @@
   }
 
   @override
-  void forEachParameter(
-      MethodElement function, void f(DartType type, String name)) {
+  void forEachParameter(MethodElement function,
+      void f(DartType type, String name, ConstantValue defaultValue)) {
     FunctionSignature parameters = function.functionSignature;
-    parameters.forEachParameter((ParameterElement parameter) {
-      f(parameter.type, parameter.name);
+    parameters.orderedForEachParameter((_parameter) {
+      ParameterElement parameter = _parameter;
+      ConstantValue value;
+      if (parameter.constant != null) {
+        value = _constants.getConstantValue(parameter.constant);
+      } else {
+        value = new NullConstantValue();
+      }
+      f(parameter.type, parameter.name, value);
     });
   }
 
@@ -599,7 +627,10 @@
 }
 
 class KernelCodegenWorldBuilder extends CodegenWorldBuilderImpl {
+  KernelToElementMapImpl _elementMap;
+
   KernelCodegenWorldBuilder(
+      this._elementMap,
       ElementEnvironment elementEnvironment,
       NativeBasicData nativeBasicData,
       ClosedWorld world,
@@ -608,9 +639,19 @@
             selectorConstraintsStrategy);
 
   @override
-  void forEachParameter(
-      FunctionEntity function, void f(DartType type, String name)) {
-    throw new UnimplementedError('KernelCodegenWorldBuilder.forEachParameter');
+  bool hasConstantFieldInitializer(FieldEntity field) {
+    return _elementMap.hasConstantFieldInitializer(field);
+  }
+
+  @override
+  ConstantValue getConstantFieldInitializer(FieldEntity field) {
+    return _elementMap.getConstantFieldInitializer(field);
+  }
+
+  @override
+  void forEachParameter(FunctionEntity function,
+      void f(DartType type, String name, ConstantValue defaultValue)) {
+    _elementMap.forEachParameter(function, f);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/universe/element_world_builder.dart b/pkg/compiler/lib/src/universe/element_world_builder.dart
index 6a0ac26..50beb8c 100644
--- a/pkg/compiler/lib/src/universe/element_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/element_world_builder.dart
@@ -63,8 +63,8 @@
 
     _instantiationInfo.forEach((cls, info) {
       if (info.instantiationMap != null) {
-        info.instantiationMap
-            .forEach((ConstructorElement constructor, Set<Instance> set) {
+        info.instantiationMap.forEach((_constructor, Set<Instance> set) {
+          ConstructorElement constructor = _constructor;
           for (Instance instance in set) {
             if (instance.isRedirection) {
               continue;
@@ -74,7 +74,7 @@
                   .addInstantiation(constructor, instance.type, instance.kind);
             } else {
               ConstructorElement target = constructor.effectiveTarget;
-              ResolutionInterfaceType targetType =
+              ResolutionDartType targetType =
                   constructor.computeEffectiveTargetType(instance.type);
               ClassElement cls = target.enclosingClass;
               bool isNative = _nativeBasicData.isNativeClass(cls);
@@ -86,8 +86,10 @@
               } else {
                 kind = Instantiation.DIRECTLY_INSTANTIATED;
               }
-              infoFor(targetType.element)
-                  .addInstantiation(target, targetType, kind);
+              if (targetType is ResolutionInterfaceType) {
+                infoFor(targetType.element)
+                    .addInstantiation(target, targetType, kind);
+              }
             }
           }
         });
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index ca18c1f..2260ed8 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -178,10 +178,10 @@
         isList = false;
       }
       if (isList) {
-        List list = elements;
+        List<MemberEntity> list = elements;
         list.add(element);
       } else {
-        Set set = elements;
+        Set<MemberEntity> set = elements;
         set.add(element);
       }
       if (!cache.isEmpty) cache.clear();
@@ -191,7 +191,7 @@
   void remove(MemberEntity element) {
     assert(element.name == name);
     if (isList) {
-      List list = elements;
+      List<MemberEntity> list = elements;
       int index = list.indexOf(element);
       if (index < 0) return;
       MemberEntity last = list.removeLast();
@@ -200,7 +200,7 @@
       }
       if (!cache.isEmpty) cache.clear();
     } else {
-      Set set = elements;
+      Set<MemberEntity> set = elements;
       if (set.remove(element)) {
         // To avoid wobbling between the two representations, we do
         // not transition back to the list representation even if we
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 0b8cdec..6f06e5a 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -29,7 +29,7 @@
   /// subtypes. The latter case only contains spurious information from
   /// instantiations through factory constructors and mixins.
   // TODO(johnniwinther): Improve semantic precision.
-  bool isImplemented(ClassEntity cls);
+  bool isImplemented(covariant ClassEntity cls);
 
   /// Set of all fields that are statically known to be written to.
   Iterable<FieldEntity> get fieldSetters;
@@ -431,7 +431,7 @@
     return _implementedClasses.contains(cls);
   }
 
-  void registerClosurizedMember(FunctionEntity element) {
+  void registerClosurizedMember(MemberEntity element) {
     closurizedMembers.add(element);
     FunctionType type = _elementEnvironment.getFunctionType(element);
     if (type.containsTypeVariables) {
@@ -575,7 +575,7 @@
     return constraints.addReceiverConstraint(mask);
   }
 
-  void registerIsCheck(DartType type) {
+  void registerIsCheck(covariant DartType type) {
     isChecks.add(type);
   }
 
@@ -654,7 +654,8 @@
   /// Called to create a [_ClassUsage] for [cls].
   ///
   /// Subclasses override this to ensure needed invariants on [cls].
-  _ClassUsage _createClassUsage(ClassEntity cls) => new _ClassUsage(cls);
+  _ClassUsage _createClassUsage(covariant ClassEntity cls) =>
+      new _ClassUsage(cls);
 
   /// Return the canonical [_ClassUsage] for [cls].
   _ClassUsage _getClassUsage(ClassEntity cls) {
@@ -709,8 +710,8 @@
     map[memberName].addAll(remaining);
   }
 
-  void _processInstantiatedClassMember(
-      ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed) {
+  void _processInstantiatedClassMember(ClassEntity cls,
+      covariant MemberEntity member, MemberUsedCallback memberUsed) {
     if (!member.isInstanceMember) return;
     String memberName = member.name;
     // The obvious thing to test here would be "member.isNative",
@@ -774,7 +775,8 @@
     _allTypedefs.add(typdef);
   }
 
-  void registerMixinUse(ClassEntity mixinApplication, ClassEntity mixin) {
+  void registerMixinUse(
+      covariant ClassEntity mixinApplication, covariant ClassEntity mixin) {
     // TODO(johnniwinther): Add map restricted to live classes.
     // We don't support patch classes as mixin.
     Set<ClassEntity> users =
@@ -803,24 +805,24 @@
     return usage != null && usage.hasUse;
   }
 
-  bool checkClass(ClassEntity cls);
-  bool validateClass(ClassEntity cls);
+  bool checkClass(covariant ClassEntity cls);
+  bool validateClass(covariant ClassEntity cls);
 
   /// Returns the class mixed into [cls] if any.
-  ClassEntity getAppliedMixin(ClassEntity cls);
+  ClassEntity getAppliedMixin(covariant ClassEntity cls);
 
   /// Returns the hierarchy depth of [cls].
-  int getHierarchyDepth(ClassEntity cls);
+  int getHierarchyDepth(covariant ClassEntity cls);
 
   /// Returns `true` if [cls] implements `Function` either explicitly or through
   /// a `call` method.
-  bool implementsFunction(ClassEntity cls);
+  bool implementsFunction(covariant ClassEntity cls);
 
   /// Returns the superclass of [cls] if any.
-  ClassEntity getSuperClass(ClassEntity cls);
+  ClassEntity getSuperClass(covariant ClassEntity cls);
 
   /// Returns all supertypes of [cls].
-  Iterable<InterfaceType> getSupertypes(ClassEntity cls);
+  Iterable<InterfaceType> getSupertypes(covariant ClassEntity cls);
 
   ClassHierarchyNode _ensureClassHierarchyNode(ClassEntity cls) {
     assert(checkClass(cls));
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index f2ac141..e5d5e16 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -18,6 +18,8 @@
 import '../elements/types.dart';
 import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../js_backend/backend_usage.dart' show BackendUsageBuilder;
+import '../js_backend/constant_handler_javascript.dart'
+    show JavaScriptConstantCompiler;
 import '../js_backend/interceptor_data.dart' show InterceptorDataBuilder;
 import '../js_backend/native_data.dart' show NativeBasicData, NativeDataBuilder;
 import '../kernel/element_map_impl.dart';
@@ -55,11 +57,11 @@
   /// Returns whether [element] is a potential target when being
   /// invoked on a receiver with this constraint. [selector] is used to ensure
   /// library privacy is taken into account.
-  bool canHit(MemberElement element, Selector selector, World world);
+  bool canHit(MemberEntity element, Selector selector, covariant World world);
 
   /// Returns whether this [TypeMask] applied to [selector] can hit a
   /// [noSuchMethod].
-  bool needsNoSuchMethodHandling(Selector selector, World world);
+  bool needsNoSuchMethodHandling(Selector selector, covariant World world);
 }
 
 /// The combined constraints on receivers all the dynamic call sites of the same
@@ -97,7 +99,7 @@
   ///
   /// Ideally the selector constraints for calls `foo` with two positional
   /// arguments apply to `A.foo` but `B.foo`.
-  bool applies(MemberEntity element, Selector selector, World world);
+  bool applies(MemberEntity element, Selector selector, covariant World world);
 
   /// Returns `true` if at least one of the receivers matching these constraints
   /// in the closed [world] have no implementation matching [selector].
@@ -110,14 +112,14 @@
   ///
   /// the potential receiver `new A()` has no implementation of `foo` and thus
   /// needs to handle the call through its `noSuchMethod` handler.
-  bool needsNoSuchMethodHandling(Selector selector, World world);
+  bool needsNoSuchMethodHandling(Selector selector, covariant World world);
 }
 
 /// A mutable [SelectorConstraints] used in [WorldBuilder].
 abstract class UniverseSelectorConstraints extends SelectorConstraints {
   /// Adds [constraint] to these selector constraints. Return `true` if the set
   /// of potential receivers expanded due to the new constraint.
-  bool addReceiverConstraint(ReceiverConstraint constraint);
+  bool addReceiverConstraint(covariant ReceiverConstraint constraint);
 }
 
 /// Strategy for computing the constraints on potential receivers of dynamic
diff --git a/pkg/compiler/lib/src/util/emptyset.dart b/pkg/compiler/lib/src/util/emptyset.dart
index 809df0b..728e902 100644
--- a/pkg/compiler/lib/src/util/emptyset.dart
+++ b/pkg/compiler/lib/src/util/emptyset.dart
@@ -31,7 +31,7 @@
   bool containsAll(Iterable<Object> other) => other.isEmpty;
 
   Set<E> union(Set<E> other) => new Set.from(other);
-  Set<E> intersection(Set<E> other) => this;
+  Set<E> intersection(Set<Object> other) => this;
   Set<E> difference(Set<Object> other) => this;
   Set<E> toSet() => new Set();
 }
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index 086273c..febfe5f 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -7,8 +7,8 @@
 import 'dart:collection' show MapBase, IterableBase;
 
 class Maplet<K, V> extends MapBase<K, V> {
-  static const _MARKER = const _MapletMarker();
-  static const CAPACITY = 8;
+  static const _MapletMarker _MARKER = const _MapletMarker();
+  static const int CAPACITY = 8;
 
 // The maplet can be in one of four states:
   //
@@ -22,7 +22,7 @@
   // the keys and they may contain markers for deleted elements. After
   // the keys there are [CAPACITY] entries for the values.
 
-  var _key = _MARKER;
+  dynamic _key = _MARKER;
   var _value;
   var _extra;
 
@@ -54,7 +54,7 @@
     }
   }
 
-  bool containsKey(K key) {
+  bool containsKey(Object key) {
     if (_extra == null) {
       return _key == key;
     } else if (_MARKER == _extra) {
@@ -70,7 +70,7 @@
     }
   }
 
-  V operator [](K key) {
+  V operator [](Object key) {
     if (_extra == null) {
       return (_key == key) ? _value : null;
     } else if (_MARKER == _extra) {
@@ -166,7 +166,7 @@
     }
   }
 
-  V remove(K key) {
+  V remove(Object key) {
     if (_extra == null) {
       if (_key != key) return null;
       _key = _MARKER;
diff --git a/pkg/compiler/lib/src/util/setlet.dart b/pkg/compiler/lib/src/util/setlet.dart
index c9d3fe5..3d8da64 100644
--- a/pkg/compiler/lib/src/util/setlet.dart
+++ b/pkg/compiler/lib/src/util/setlet.dart
@@ -7,8 +7,8 @@
 import 'dart:collection' show IterableBase;
 
 class Setlet<E> extends IterableBase<E> implements Set<E> {
-  static const _MARKER = const _SetletMarker();
-  static const CAPACITY = 8;
+  static const _SetletMarker _MARKER = const _SetletMarker();
+  static const int CAPACITY = 8;
 
   // The setlet can be in one of four states:
   //
@@ -19,7 +19,7 @@
   //
   // When the setlet is list-backed, the list in the contents field
   // may have empty slots filled with the marker value.
-  var _contents = _MARKER;
+  dynamic _contents = _MARKER;
   var _extra;
 
   Setlet();
@@ -57,7 +57,7 @@
     }
   }
 
-  bool contains(E element) {
+  bool contains(Object element) {
     if (_extra == null) {
       return _contents == element;
     } else if (_MARKER == _extra) {
@@ -232,7 +232,7 @@
     }
   }
 
-  bool containsAll(Iterable<E> other) {
+  bool containsAll(Iterable<Object> other) {
     for (E e in other) {
       if (!this.contains(e)) return false;
     }
@@ -247,7 +247,7 @@
 
   Set<E> union(Set<E> other) => new Set<E>.from(this)..addAll(other);
 
-  Setlet<E> intersection(Set<E> other) =>
+  Setlet<E> intersection(Set<Object> other) =>
       new Setlet<E>.from(this.where((e) => other.contains(e)));
 
   Setlet<E> difference(Set<Object> other) =>
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index f7f5120..abcf426 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -253,7 +253,8 @@
   /// Returns whether [element] will be the one used at runtime when being
   /// invoked on an instance of [cls]. [selector] is used to ensure library
   /// privacy is taken into account.
-  bool hasElementIn(ClassEntity cls, Selector selector, Entity element);
+  bool hasElementIn(
+      covariant ClassEntity cls, Selector selector, covariant Entity element);
 
   /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
   /// of known classes.
@@ -365,7 +366,7 @@
 
   /// Adds the closure class [cls] to the inference world. The class is
   /// considered directly instantiated.
-  void registerClosureClass(ClassElement cls);
+  void registerClosureClass(covariant ClassElement cls);
 }
 
 abstract class OpenWorld implements World {
@@ -373,7 +374,7 @@
   ///
   /// This ensures that class hierarchy queries can be performed on [cls] and
   /// classes that extend or implement it.
-  void registerClass(ClassEntity cls);
+  void registerClass(covariant ClassEntity cls);
 
   void registerUsedElement(MemberEntity element);
   void registerTypedef(TypedefElement typedef);
@@ -484,23 +485,24 @@
     return cachedMasks.putIfAbsent(base, createMask);
   }
 
-  bool checkEntity(Entity element);
+  bool checkEntity(covariant Entity element);
 
-  bool checkClass(ClassEntity cls);
+  bool checkClass(covariant ClassEntity cls);
 
-  bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true});
+  bool checkInvariants(covariant ClassEntity cls,
+      {bool mustBeInstantiated: true});
 
-  OrderedTypeSet getOrderedTypeSet(ClassEntity cls);
+  OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
 
-  int getHierarchyDepth(ClassEntity cls);
+  int getHierarchyDepth(covariant ClassEntity cls);
 
-  ClassEntity getSuperClass(ClassEntity cls);
+  ClassEntity getSuperClass(covariant ClassEntity cls);
 
-  Iterable<ClassEntity> getInterfaces(ClassEntity cls);
+  Iterable<ClassEntity> getInterfaces(covariant ClassEntity cls);
 
-  ClassEntity getAppliedMixin(ClassEntity cls);
+  ClassEntity getAppliedMixin(covariant ClassEntity cls);
 
-  bool isNamedMixinApplication(ClassEntity cls);
+  bool isNamedMixinApplication(covariant ClassEntity cls);
 
   @override
   bool isInstantiated(ClassEntity cls) {
@@ -801,8 +803,8 @@
 
   /// Returns whether a [selector] call on an instance of [cls]
   /// will hit a method at runtime, and not go through [noSuchMethod].
-  bool hasConcreteMatch(ClassEntity cls, Selector selector,
-      {ClassEntity stopAtSuperclass});
+  bool hasConcreteMatch(covariant ClassEntity cls, Selector selector,
+      {covariant ClassEntity stopAtSuperclass});
 
   @override
   bool needsNoSuchMethod(
@@ -1075,12 +1077,12 @@
     return sideEffects;
   }
 
-  SideEffects getSideEffectsOfElement(Entity element) {
+  SideEffects getSideEffectsOfElement(covariant Entity element) {
     assert(checkEntity(element));
     return _sideEffects.putIfAbsent(element, _makeSideEffects);
   }
 
-  static _makeSideEffects() => new SideEffects();
+  static SideEffects _makeSideEffects() => new SideEffects();
 
   @override
   SideEffects getCurrentlyKnownSideEffects(Entity element) {
diff --git a/pkg/compiler/testing.json b/pkg/compiler/testing.json
index ba002e5..31caf62 100644
--- a/pkg/compiler/testing.json
+++ b/pkg/compiler/testing.json
@@ -10,118 +10,15 @@
 
     "uris": [
       ".",
-      "../../tests/compiler/dart2js/"
+      "../../tests/compiler/dart2js/",
+      "../../tests/utils/"
     ],
 
     "exclude": [
-      "^tests/compiler/dart2js/analyze_api_test\\.dart",
-      "^tests/compiler/dart2js/analyze_test_test\\.dart",
-      "^tests/compiler/dart2js/bad_output_io_test\\.dart",
-      "^tests/compiler/dart2js/boolified_operator_test\\.dart",
-      "^tests/compiler/dart2js/codegen_helper\\.dart",
-      "^tests/compiler/dart2js/constant_expression_evaluate_test\\.dart",
-      "^tests/compiler/dart2js/constant_expression_test\\.dart",
-      "^tests/compiler/dart2js/dart2js_batch2_test\\.dart",
-      "^tests/compiler/dart2js/dart2js_batch_test\\.dart",
-      "^tests/compiler/dart2js/dart2js_resolver_test\\.dart",
-      "^tests/compiler/dart2js/data/dart2js_batch2_run\\.dart",
-      "^tests/compiler/dart2js/data/mirrors_helper\\.dart",
-      "^tests/compiler/dart2js/data/one_line_dart_program\\.dart",
-      "^tests/compiler/dart2js/deferred_custom_element_test\\.dart",
-      "^tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test\\.dart",
-      "^tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test\\.dart",
-      "^tests/compiler/dart2js/deferred_follow_constant_dependencies_test\\.dart",
-      "^tests/compiler/dart2js/deferred_follow_implicit_super_regression_test\\.dart",
-      "^tests/compiler/dart2js/deferred_inline_restrictions_test\\.dart",
-      "^tests/compiler/dart2js/deferred_load_graph_segmentation2_test\\.dart",
-      "^tests/compiler/dart2js/deferred_load_graph_segmentation_test\\.dart",
-      "^tests/compiler/dart2js/deferred_mirrors_test\\.dart",
-      "^tests/compiler/dart2js/deferred_not_in_main_test\\.dart",
-      "^tests/compiler/dart2js/embedded_category_api_boundary_test\\.dart",
-      "^tests/compiler/dart2js/exit_code_test\\.dart",
-      "^tests/compiler/dart2js/expect_annotations2_test\\.dart",
-      "^tests/compiler/dart2js/flatten_test\\.dart",
-      "^tests/compiler/dart2js/gvn_dynamic_field_get_test\\.dart",
-      "^tests/compiler/dart2js/import_mirrors_test\\.dart",
-      "^tests/compiler/dart2js/import_test\\.dart",
-      "^tests/compiler/dart2js/in_user_code_test\\.dart",
-      "^tests/compiler/dart2js/interop_anonymous_unreachable_test\\.dart",
-      "^tests/compiler/dart2js/js_constant_test\\.dart",
-      "^tests/compiler/dart2js/js_parser_statements_test\\.dart",
-      "^tests/compiler/dart2js/js_spec_optimization_test\\.dart",
-      "^tests/compiler/dart2js/jsinterop/world_test\\.dart",
-      "^tests/compiler/dart2js/kernel/class_hierarchy_test\\.dart",
-      "^tests/compiler/dart2js/kernel/closed_world_test\\.dart",
-      "^tests/compiler/dart2js/kernel/visitor_test\\.dart",
-      "^tests/compiler/dart2js/least_upper_bound_test\\.dart",
-      "^tests/compiler/dart2js/library_resolution_test\\.dart",
-      "^tests/compiler/dart2js/list_tracer2_test\\.dart",
-      "^tests/compiler/dart2js/list_tracer3_test\\.dart",
-      "^tests/compiler/dart2js/members_test\\.dart",
-      "^tests/compiler/dart2js/memory_compiler\\.dart",
-      "^tests/compiler/dart2js/message_kind_helper\\.dart",
-      "^tests/compiler/dart2js/metadata_test\\.dart",
-      "^tests/compiler/dart2js/minimal_resolution_test\\.dart",
-      "^tests/compiler/dart2js/mirrors_used_test\\.dart",
-      "^tests/compiler/dart2js/mixin_typevariable_test\\.dart",
-      "^tests/compiler/dart2js/mock_compiler\\.dart",
-      "^tests/compiler/dart2js/modulo_remainder_test\\.dart",
-      "^tests/compiler/dart2js/needs_no_such_method_test\\.dart",
-      "^tests/compiler/dart2js/no_such_method_enabled_test\\.dart",
-      "^tests/compiler/dart2js/output_collector\\.dart",
-      "^tests/compiler/dart2js/override_inheritance_test\\.dart",
-      "^tests/compiler/dart2js/package_root_test\\.dart",
-      "^tests/compiler/dart2js/partial_parser_test\\.dart",
-      "^tests/compiler/dart2js/patch_test\\.dart",
-      "^tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package\\.dart",
-      "^tests/compiler/dart2js/quarantined/http_test\\.dart",
-      "^tests/compiler/dart2js/reexport_handled_test\\.dart",
-      "^tests/compiler/dart2js/resolution_test\\.dart",
-      "^tests/compiler/dart2js/resolver_test\\.dart",
-      "^tests/compiler/dart2js/serialization/analysis_test_helper\\.dart",
-      "^tests/compiler/dart2js/serialization/compilation_test_helper\\.dart",
-      "^tests/compiler/dart2js/serialization/duplicate_library_test\\.dart",
-      "^tests/compiler/dart2js/serialization/equivalence_test\\.dart",
-      "^tests/compiler/dart2js/serialization/model_test_helper\\.dart",
-      "^tests/compiler/dart2js/serialization/test_helper\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_closure_test\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_const_closure2_test\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_const_closure_default_test\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_const_closure_test\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_global_field_closure_test\\.dart",
-      "^tests/compiler/dart2js/simple_inferrer_test\\.dart",
-      "^tests/compiler/dart2js/size_test\\.dart",
-      "^tests/compiler/dart2js/source_map_validator_helper\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/data/invokes_test_file\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/diff_view\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/html_parts\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/lax_json\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/mapping_test\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/nomapping_test\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/output_structure\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/save\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/sourcemap_helper\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/sourcemap_html_helper\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/stacktrace_test\\.dart",
-      "^tests/compiler/dart2js/subtype_test\\.dart",
-      "^tests/compiler/dart2js/subtypeset_test\\.dart",
-      "^tests/compiler/dart2js/tdiv_test\\.dart",
-      "^tests/compiler/dart2js/token_naming_test\\.dart",
-      "^tests/compiler/dart2js/trust_type_annotations_test\\.dart",
-      "^tests/compiler/dart2js/type_checker_test\\.dart",
-      "^tests/compiler/dart2js/type_equals_test\\.dart",
-      "^tests/compiler/dart2js/type_inference8_test\\.dart",
-      "^tests/compiler/dart2js/type_mask2_test\\.dart",
-      "^tests/compiler/dart2js/type_mask_test\\.dart",
-      "^tests/compiler/dart2js/type_order_test\\.dart",
-      "^tests/compiler/dart2js/type_representation_test\\.dart",
-      "^tests/compiler/dart2js/type_substitution_test\\.dart",
-      "^tests/compiler/dart2js/type_variable_occurrence_test\\.dart",
-      "^tests/compiler/dart2js/unused_empty_map_test\\.dart",
-      "^tests/compiler/dart2js/world_test\\.dart",
-
-      "^tests/compiler/dart2js/path with spaces/.*"
+      "^tests/compiler/dart2js/data/.*",
+      "^tests/compiler/dart2js/path with spaces/.*",
+      "^tests/compiler/dart2js/sourcemaps/data/.*",
+      "^tests/utils/dummy\\.dart"
     ]
   }
 }
diff --git a/pkg/compiler/testing_dart.json b/pkg/compiler/testing_dart.json
new file mode 100644
index 0000000..78152a3
--- /dev/null
+++ b/pkg/compiler/testing_dart.json
@@ -0,0 +1,127 @@
+{
+"":"Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file",
+"":"for details. All rights reserved. Use of this source code is governed by a",
+"":"BSD-style license that can be found in the LICENSE.md file.",
+
+  "packages": "../../.packages",
+
+  "analyze": {
+    "options": "analysis_options_dart.yaml",
+
+    "uris": [
+      ".",
+      "../../tests/compiler/dart2js/"
+    ],
+
+    "exclude": [
+      "^tests/compiler/dart2js/analyze_api_test\\.dart",
+      "^tests/compiler/dart2js/analyze_test_test\\.dart",
+      "^tests/compiler/dart2js/bad_output_io_test\\.dart",
+      "^tests/compiler/dart2js/boolified_operator_test\\.dart",
+      "^tests/compiler/dart2js/codegen_helper\\.dart",
+      "^tests/compiler/dart2js/constant_expression_evaluate_test\\.dart",
+      "^tests/compiler/dart2js/constant_expression_test\\.dart",
+      "^tests/compiler/dart2js/dart2js_batch2_test\\.dart",
+      "^tests/compiler/dart2js/dart2js_batch_test\\.dart",
+      "^tests/compiler/dart2js/dart2js_resolver_test\\.dart",
+      "^tests/compiler/dart2js/data/dart2js_batch2_run\\.dart",
+      "^tests/compiler/dart2js/data/mirrors_helper\\.dart",
+      "^tests/compiler/dart2js/data/one_line_dart_program\\.dart",
+      "^tests/compiler/dart2js/deferred_custom_element_test\\.dart",
+      "^tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test\\.dart",
+      "^tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test\\.dart",
+      "^tests/compiler/dart2js/deferred_follow_constant_dependencies_test\\.dart",
+      "^tests/compiler/dart2js/deferred_follow_implicit_super_regression_test\\.dart",
+      "^tests/compiler/dart2js/deferred_inline_restrictions_test\\.dart",
+      "^tests/compiler/dart2js/deferred_load_graph_segmentation2_test\\.dart",
+      "^tests/compiler/dart2js/deferred_load_graph_segmentation_test\\.dart",
+      "^tests/compiler/dart2js/deferred_mirrors_test\\.dart",
+      "^tests/compiler/dart2js/deferred_not_in_main_test\\.dart",
+      "^tests/compiler/dart2js/embedded_category_api_boundary_test\\.dart",
+      "^tests/compiler/dart2js/exit_code_test\\.dart",
+      "^tests/compiler/dart2js/expect_annotations2_test\\.dart",
+      "^tests/compiler/dart2js/flatten_test\\.dart",
+      "^tests/compiler/dart2js/gvn_dynamic_field_get_test\\.dart",
+      "^tests/compiler/dart2js/import_mirrors_test\\.dart",
+      "^tests/compiler/dart2js/import_test\\.dart",
+      "^tests/compiler/dart2js/in_user_code_test\\.dart",
+      "^tests/compiler/dart2js/interop_anonymous_unreachable_test\\.dart",
+      "^tests/compiler/dart2js/js_constant_test\\.dart",
+      "^tests/compiler/dart2js/js_parser_statements_test\\.dart",
+      "^tests/compiler/dart2js/js_spec_optimization_test\\.dart",
+      "^tests/compiler/dart2js/jsinterop/world_test\\.dart",
+      "^tests/compiler/dart2js/kernel/class_hierarchy_test\\.dart",
+      "^tests/compiler/dart2js/kernel/closed_world_test\\.dart",
+      "^tests/compiler/dart2js/kernel/visitor_test\\.dart",
+      "^tests/compiler/dart2js/least_upper_bound_test\\.dart",
+      "^tests/compiler/dart2js/library_resolution_test\\.dart",
+      "^tests/compiler/dart2js/list_tracer2_test\\.dart",
+      "^tests/compiler/dart2js/list_tracer3_test\\.dart",
+      "^tests/compiler/dart2js/members_test\\.dart",
+      "^tests/compiler/dart2js/memory_compiler\\.dart",
+      "^tests/compiler/dart2js/message_kind_helper\\.dart",
+      "^tests/compiler/dart2js/metadata_test\\.dart",
+      "^tests/compiler/dart2js/minimal_resolution_test\\.dart",
+      "^tests/compiler/dart2js/mirrors_used_test\\.dart",
+      "^tests/compiler/dart2js/mixin_typevariable_test\\.dart",
+      "^tests/compiler/dart2js/mock_compiler\\.dart",
+      "^tests/compiler/dart2js/modulo_remainder_test\\.dart",
+      "^tests/compiler/dart2js/needs_no_such_method_test\\.dart",
+      "^tests/compiler/dart2js/no_such_method_enabled_test\\.dart",
+      "^tests/compiler/dart2js/output_collector\\.dart",
+      "^tests/compiler/dart2js/override_inheritance_test\\.dart",
+      "^tests/compiler/dart2js/package_root_test\\.dart",
+      "^tests/compiler/dart2js/partial_parser_test\\.dart",
+      "^tests/compiler/dart2js/patch_test\\.dart",
+      "^tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package\\.dart",
+      "^tests/compiler/dart2js/quarantined/http_test\\.dart",
+      "^tests/compiler/dart2js/reexport_handled_test\\.dart",
+      "^tests/compiler/dart2js/resolution_test\\.dart",
+      "^tests/compiler/dart2js/resolver_test\\.dart",
+      "^tests/compiler/dart2js/serialization/analysis_test_helper\\.dart",
+      "^tests/compiler/dart2js/serialization/compilation_test_helper\\.dart",
+      "^tests/compiler/dart2js/serialization/duplicate_library_test\\.dart",
+      "^tests/compiler/dart2js/serialization/equivalence_test\\.dart",
+      "^tests/compiler/dart2js/serialization/model_test_helper\\.dart",
+      "^tests/compiler/dart2js/serialization/test_helper\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_closure_test\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_const_closure2_test\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_const_closure_default_test\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_const_closure_test\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_global_field_closure_test\\.dart",
+      "^tests/compiler/dart2js/simple_inferrer_test\\.dart",
+      "^tests/compiler/dart2js/size_test\\.dart",
+      "^tests/compiler/dart2js/source_map_validator_helper\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/data/invokes_test_file\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/diff_view\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/html_parts\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/lax_json\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/mapping_test\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/nomapping_test\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/output_structure\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/save\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/sourcemap_helper\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/sourcemap_html_helper\\.dart",
+      "^tests/compiler/dart2js/sourcemaps/stacktrace_test\\.dart",
+      "^tests/compiler/dart2js/subtype_test\\.dart",
+      "^tests/compiler/dart2js/subtypeset_test\\.dart",
+      "^tests/compiler/dart2js/tdiv_test\\.dart",
+      "^tests/compiler/dart2js/token_naming_test\\.dart",
+      "^tests/compiler/dart2js/trust_type_annotations_test\\.dart",
+      "^tests/compiler/dart2js/type_checker_test\\.dart",
+      "^tests/compiler/dart2js/type_equals_test\\.dart",
+      "^tests/compiler/dart2js/type_inference8_test\\.dart",
+      "^tests/compiler/dart2js/type_mask2_test\\.dart",
+      "^tests/compiler/dart2js/type_mask_test\\.dart",
+      "^tests/compiler/dart2js/type_order_test\\.dart",
+      "^tests/compiler/dart2js/type_representation_test\\.dart",
+      "^tests/compiler/dart2js/type_substitution_test\\.dart",
+      "^tests/compiler/dart2js/type_variable_occurrence_test\\.dart",
+      "^tests/compiler/dart2js/unused_empty_map_test\\.dart",
+      "^tests/compiler/dart2js/world_test\\.dart",
+
+      "^tests/compiler/dart2js/path with spaces/.*"
+    ]
+  }
+}
diff --git a/pkg/compiler/tool/dart2js_profile_many.dart b/pkg/compiler/tool/dart2js_profile_many.dart
index fed5e21..9b3d1c2 100644
--- a/pkg/compiler/tool/dart2js_profile_many.dart
+++ b/pkg/compiler/tool/dart2js_profile_many.dart
@@ -20,8 +20,8 @@
 }
 
 void main(List<String> args) {
-  List options = [];
-  List files = [];
+  var options = <String>[];
+  var files = <String>[];
 
   for (String arg in args) {
     if (arg.startsWith('-')) {
diff --git a/pkg/compiler/tool/perf.dart b/pkg/compiler/tool/perf.dart
index 44d4f36..bea1371 100644
--- a/pkg/compiler/tool/perf.dart
+++ b/pkg/compiler/tool/perf.dart
@@ -344,10 +344,11 @@
       selfTask.measureSubtask('KernelCompiler.compileLoadedLibraries', () {
         ResolutionEnqueuer resolutionEnqueuer = startResolution();
         WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
-        mainFunction = frontendStrategy.computeMain(rootLibrary, mainImpact);
-        mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
+        var mainFunction =
+            frontendStrategy.computeMain(rootLibrary, mainImpact);
+        mirrorUsageAnalyzerTask.analyzeUsage(rootLibrary);
 
-        deferredLoadTask.beforeResolution(this);
+        deferredLoadTask.beforeResolution(rootLibrary);
         impactStrategy = backend.createImpactStrategy(
             supportDeferredLoad: deferredLoadTask.isProgramSplit,
             supportDumpInfo: options.dumpInfo,
@@ -379,7 +380,7 @@
         }
 
         backend.onResolutionEnd();
-        closeResolution();
+        closeResolution(mainFunction);
         var program = (backend as dynamic).kernelTask.program;
         print('total libraries: ${program.libraries.length}');
       });
diff --git a/pkg/compiler/tool/track_memory.dart b/pkg/compiler/tool/track_memory.dart
index 46891a4..0ba0e7c 100644
--- a/pkg/compiler/tool/track_memory.dart
+++ b/pkg/compiler/tool/track_memory.dart
@@ -151,8 +151,8 @@
       color: true);
 
   sb.write(' | ');
-  var maxUsed = max(lastMaxUsed, newUsed + oldUsed);
-  var maxCapacity = max(lastMaxCapacity, newCapacity + oldCapacity);
+  int maxUsed = max(lastMaxUsed, newUsed + oldUsed);
+  int maxCapacity = max(lastMaxCapacity, newCapacity + oldCapacity);
   _writeNumber(sb, lastMaxUsed, maxUsed);
   _writeNumber(sb, lastMaxCapacity, maxCapacity, color: true);
   stdout.write('$sb');
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
index acde51b..d38077b 100644
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
@@ -175,10 +175,9 @@
 
   bool _superAllowed = true;
 
-  List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[];
-  List<JS.Method> _superHelpers = <JS.Method>[];
+  final _superHelpers = new Map<String, JS.Method>();
 
-  List<TypeParameterType> _typeParamInConst = null;
+  List<TypeParameterType> _typeParamInConst;
 
   /// Whether we are currently generating code for the body of a `JS()` call.
   bool _isInForeignJS = false;
@@ -395,13 +394,20 @@
       libraryPrefix.addAll(libraryJSName.split('.'));
     }
 
+    var original = e;
+    var variableElement = e;
+    if (original is PropertyAccessorElement) {
+      variableElement = original.variable;
+      if (original.isSynthetic) e = variableElement;
+    }
+
     String elementJSName;
     if (findAnnotation(e, isPublicJSAnnotation) != null) {
       elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? '';
     }
 
-    if (e is TopLevelVariableElement) {
-      elementJSName = _jsInteropStaticMemberName(e);
+    if (variableElement is TopLevelVariableElement) {
+      elementJSName = _jsInteropStaticMemberName(original);
     }
     if (elementJSName == null) return null;
 
@@ -426,34 +432,31 @@
     return access;
   }
 
-  String _jsInteropStaticMemberName(Element e, {String name}) {
-    if (e == null ||
-        e.library == null ||
+  String _jsInteropStaticMemberName(Element e) {
+    if (e?.library == null ||
         findAnnotation(e.library, isPublicJSAnnotation) == null) {
       return null;
     }
-    if (e is PropertyInducingElement) {
-      // Assume properties have consistent JS names for getters and setters.
-      return _jsInteropStaticMemberName(e.getter, name: e.name) ??
-          _jsInteropStaticMemberName(e.setter, name: e.name);
-    }
     if (e is ExecutableElement && e.isExternal) {
-      return getAnnotationName(e, isPublicJSAnnotation) ?? name ?? e.name;
+      return getAnnotationName(e, isPublicJSAnnotation) ??
+          (e is PropertyAccessorElement ? e.variable : e).name;
+    }
+    if (e is PropertyInducingElement && e.getter.isExternal) {
+      return getAnnotationName(e, isPublicJSAnnotation) ?? e.name;
     }
     return null;
   }
 
-  JS.Expression _emitJSInteropStaticMemberName(Element e) {
+  String _emitJSInteropStaticMemberName(Element e) {
     var name = _jsInteropStaticMemberName(e);
-    if (name == null) return null;
     // We do not support statics names with JS annotations containing dots.
     // See https://github.com/dart-lang/sdk/issues/27926
-    if (name.contains('.')) {
-      throw new UnimplementedError(
+    if (name != null && name.contains('.')) {
+      throw new UnsupportedError(
           'We do not support JS annotations containing dots on static members. '
           'See https://github.com/dart-lang/sdk/issues/27926');
     }
-    return js.string(name);
+    return name;
   }
 
   /// Flattens blocks in [items] to a single list.
@@ -904,7 +907,7 @@
 
     var body = <JS.Statement>[];
     _initExtensionSymbols(classElem, methods, fields, body);
-    _emitSuperHelperSymbols(_superHelperSymbols, body);
+    _emitSuperHelperSymbols(body);
 
     // Emit the class, e.g. `core.Object = class Object { ... }`
     _defineClass(classElem, className, classExpr, body);
@@ -1136,12 +1139,11 @@
     }
   }
 
-  void _emitSuperHelperSymbols(
-      List<JS.TemporaryId> superHelperSymbols, List<JS.Statement> body) {
-    for (var id in superHelperSymbols) {
+  void _emitSuperHelperSymbols(List<JS.Statement> body) {
+    for (var id in _superHelpers.values.map((m) => m.name as JS.TemporaryId)) {
       body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
     }
-    superHelperSymbols.clear();
+    _superHelpers.clear();
   }
 
   void _emitVirtualFieldSymbols(
@@ -1431,8 +1433,7 @@
     }
 
     // Add all of the super helper methods
-    jsMethods.addAll(_superHelpers);
-    _superHelpers.clear();
+    jsMethods.addAll(_superHelpers.values);
 
     return jsMethods.where((m) => m != null).toList(growable: false);
   }
@@ -2767,7 +2768,7 @@
 
     // library member
     if (element.enclosingElement is CompilationUnitElement) {
-      return _emitTopLevelName(element);
+      return _emitTopLevelName(accessor);
     }
 
     var name = element.name;
@@ -2778,7 +2779,7 @@
       bool isStatic = element.isStatic;
       var type = element.enclosingElement.type;
       var member = _emitMemberName(name,
-          isStatic: isStatic, type: type, element: element);
+          isStatic: isStatic, type: type, element: accessor);
 
       if (isStatic) {
         var dynType = _emitStaticAccess(type);
@@ -2795,7 +2796,7 @@
         var safeName = _emitMemberName(name,
             isStatic: isStatic,
             type: type,
-            element: element,
+            element: accessor,
             alwaysSymbolizeNative: true);
         return _callHelper('bind(this, #)', safeName);
       }
@@ -3183,72 +3184,56 @@
     return new JS.MetaLet(vars, [_emitSet(lhs, inc)]);
   }
 
-  JS.Expression _emitSet(Expression lhs, Expression rhs) {
-    if (lhs is IndexExpression) {
-      var target = _getTarget(lhs);
+  JS.Expression _emitSet(Expression left, Expression right) {
+    if (left is IndexExpression) {
+      var target = _getTarget(left);
       if (_useNativeJsIndexer(target.staticType)) {
-        return js
-            .call('#[#] = #', [_visit(target), _visit(lhs.index), _visit(rhs)]);
+        return js.call(
+            '#[#] = #', [_visit(target), _visit(left.index), _visit(right)]);
       }
-      return _emitSend(target, '[]=', [lhs.index, rhs]);
+      return _emitSend(target, '[]=', [left.index, right]);
     }
 
-    if (lhs is SimpleIdentifier) {
-      return _emitSetSimpleIdentifier(lhs, rhs);
+    if (left is SimpleIdentifier) {
+      return _emitSetSimpleIdentifier(left, right);
     }
 
     Expression target = null;
     SimpleIdentifier id;
-    if (lhs is PropertyAccess) {
-      if (lhs.operator.lexeme == '?.') {
-        return _emitNullSafeSet(lhs, rhs);
+    if (left is PropertyAccess) {
+      if (left.operator.lexeme == '?.') {
+        return _emitNullSafeSet(left, right);
       }
-      target = _getTarget(lhs);
-      id = lhs.propertyName;
-    } else if (lhs is PrefixedIdentifier) {
-      if (isLibraryPrefix(lhs.prefix)) {
-        return _emitSet(lhs.identifier, rhs);
+      target = _getTarget(left);
+      id = left.propertyName;
+    } else if (left is PrefixedIdentifier) {
+      if (isLibraryPrefix(left.prefix)) {
+        return _emitSet(left.identifier, right);
       }
-      target = lhs.prefix;
-      id = lhs.identifier;
+      target = left.prefix;
+      id = left.identifier;
     } else {
       assert(false);
     }
 
-    assert(target != null);
-
-    if (target is SuperExpression) {
-      return _emitSetSuper(lhs, target, id, rhs);
-    }
-
-    if (target != null && isDynamicInvoke(target)) {
+    if (isDynamicInvoke(target)) {
       return _callHelper('#(#, #, #)', [
         _emitDynamicOperationName('dput'),
         _visit(target),
         _emitMemberName(id.name),
-        _visit(rhs)
+        _visit(right)
       ]);
     }
 
     var accessor = id.staticElement;
-    var element =
-        accessor is PropertyAccessorElement ? accessor.variable : accessor;
-
-    if (element is ClassMemberElement && element is! ConstructorElement) {
-      bool isStatic = element.isStatic;
-      if (isStatic) {
-        if (element is FieldElement) {
-          return _emitSetStaticProperty(lhs, element, rhs);
-        }
-        return _badAssignment('Unknown static: $element', lhs, rhs);
-      }
-      if (element is FieldElement) {
-        return _emitWriteInstanceProperty(
-            lhs, _visit(target), element, _visit(rhs));
+    if (accessor is PropertyAccessorElement) {
+      var field = accessor.variable;
+      if (field is FieldElement) {
+        return _emitSetField(left, right, field, _visit(target));
       }
     }
 
-    return _badAssignment('Unhandled assignment', lhs, rhs);
+    return _badAssignment('Unhandled assignment', left, right);
   }
 
   JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) {
@@ -3263,9 +3248,9 @@
   /// identifier assignment targets (local, top level library member, implicit
   /// `this` or class, etc.)
   JS.Expression _emitSetSimpleIdentifier(
-      SimpleIdentifier node, Expression rhs) {
+      SimpleIdentifier node, Expression right) {
     JS.Expression unimplemented() {
-      return _badAssignment("Unimplemented: unknown name '$node'", node, rhs);
+      return _badAssignment("Unimplemented: unknown name '$node'", node, right);
     }
 
     var accessor = resolutionMap.staticElementForIdentifier(node);
@@ -3281,31 +3266,18 @@
     }
 
     if (element is LocalVariableElement || element is ParameterElement) {
-      return _emitSetLocal(node, element, rhs);
+      return _emitSetLocal(node, element, right);
     }
 
     if (element.enclosingElement is CompilationUnitElement) {
       // Top level library member.
-      return _emitSetTopLevel(node, element, rhs);
+      return _emitSetTopLevel(node, accessor, right);
     }
 
     // Unqualified class member. This could mean implicit `this`, or implicit
     // static from the same class.
-    if (element is ClassMemberElement) {
-      bool isStatic = element.isStatic;
-      if (isStatic) {
-        if (element is FieldElement) {
-          return _emitSetStaticProperty(node, element, rhs);
-        }
-        return unimplemented();
-      }
-
-      // For instance members, we add implicit-this.
-      if (element is FieldElement) {
-        return _emitWriteInstanceProperty(
-            node, new JS.This(), element, _visit(rhs));
-      }
-      return unimplemented();
+    if (element is FieldElement) {
+      return _emitSetField(node, right, element, new JS.This());
     }
 
     // We should not get here.
@@ -3331,42 +3303,23 @@
 
   /// Emits assignment to library scope element [element].
   JS.Expression _emitSetTopLevel(
-      Expression lhs, Element element, Expression rhs) {
+      Expression lhs, PropertyAccessorElement element, Expression rhs) {
     return _visit<JS.Expression>(rhs)
         .toAssignExpression(annotate(_emitTopLevelName(element), lhs));
   }
 
   /// Emits assignment to a static field element or property.
-  JS.Expression _emitSetStaticProperty(
-      Expression lhs, Element element, Expression rhs) {
-    // For static methods, we add the raw type name, without generics or
-    // library prefix. We don't need those because static calls can't use
-    // the generic type.
-    ClassElement classElement = element.enclosingElement;
-    var type = classElement.type;
-    var dynType = _emitStaticAccess(type);
-    var member = _emitMemberName(element.name,
-        isStatic: true, type: type, element: element);
-    return _visit<JS.Expression>(rhs).toAssignExpression(
-        annotate(new JS.PropertyAccess(dynType, member), lhs));
-  }
-
-  /// Emits an assignment to the [element] property of instance referenced by
-  /// [jsTarget].
-  JS.Expression _emitWriteInstanceProperty(Expression lhs,
-      JS.Expression jsTarget, Element element, JS.Expression value) {
-    String memberName = element.name;
-    var type = (element.enclosingElement as ClassElement).type;
-    var name = _emitMemberName(memberName, type: type, element: element);
-    return value.toAssignExpression(
-        annotate(new JS.PropertyAccess(jsTarget, name), lhs));
-  }
-
-  JS.Expression _emitSetSuper(Expression lhs, SuperExpression target,
-      SimpleIdentifier id, Expression rhs) {
-    // TODO(sra): Determine whether and access helper is required for the
-    // setter. For now fall back on the r-value path.
-    return _visit<JS.Expression>(rhs).toAssignExpression(_visit(lhs));
+  JS.Expression _emitSetField(Expression left, Expression right,
+      FieldElement field, JS.Expression jsTarget) {
+    var type = field.enclosingElement.type;
+    var isStatic = field.isStatic;
+    var member = _emitMemberName(field.name,
+        isStatic: isStatic, type: type, element: field.setter);
+    jsTarget = isStatic
+        ? new JS.PropertyAccess(_emitStaticAccess(type), member)
+        : _emitTargetAccess(jsTarget, member, field.setter);
+    return _visit<JS.Expression>(right)
+        .toAssignExpression(annotate(jsTarget, left));
   }
 
   JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
@@ -3451,75 +3404,78 @@
     return _emitMethodCall(target, node);
   }
 
-  JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
-    var args = _emitArgumentList(node.argumentList);
-    var typeArgs = _emitInvokeTypeArguments(node);
-
-    if (target is SuperExpression && !_superAllowed) {
-      return _emitSuperHelperCall(typeArgs, args, target, node);
-    }
-
-    return _emitMethodCallInternal(target, node, args, typeArgs);
-  }
-
-  JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs,
-      List<JS.Expression> args, SuperExpression target, MethodInvocation node) {
-    var fakeTypeArgs =
-        typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false);
-    var fakeArgs =
-        args.map((_) => new JS.TemporaryId('a')).toList(growable: false);
-    var combinedFakeArgs = <JS.TemporaryId>[];
-    if (fakeTypeArgs != null) {
-      combinedFakeArgs.addAll(fakeTypeArgs);
-    }
-    combinedFakeArgs.addAll(fakeArgs);
-
-    var forwardedCall =
-        _emitMethodCallInternal(target, node, fakeArgs, fakeTypeArgs);
-    var superForwarder = _getSuperHelperFor(
-        node.methodName.name, forwardedCall, combinedFakeArgs);
-
-    var combinedRealArgs = <JS.Expression>[];
-    if (typeArgs != null) {
-      combinedRealArgs.addAll(typeArgs);
-    }
-    combinedRealArgs.addAll(args);
-
-    return js.call('this.#(#)', [superForwarder, combinedRealArgs]);
-  }
-
-  JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall,
-      List<JS.Expression> helperArgs) {
-    var helperMethod =
-        new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)]));
-    var helperMethodName = new JS.TemporaryId('super\$$name');
-    _superHelperSymbols.add(helperMethodName);
-    _superHelpers.add(new JS.Method(helperMethodName, helperMethod));
-    return helperMethodName;
-  }
-
-  JS.Expression _emitTarget(Expression target, Element element, bool isStatic) {
+  JS.Expression _emitTarget(Expression target, Element member, bool isStatic) {
     if (isStatic) {
-      if (element is ConstructorElement) {
-        return _emitConstructorAccess(element.enclosingElement.type);
+      if (member is ConstructorElement) {
+        return _emitConstructorAccess(member.enclosingElement.type);
       }
-      if (element is ExecutableElement) {
-        return _emitStaticAccess(
-            (element.enclosingElement as ClassElement).type);
+      if (member is PropertyAccessorElement) {
+        var field = member.variable;
+        if (field is FieldElement) {
+          return _emitStaticAccess(field.enclosingElement.type);
+        }
       }
-      if (element is FieldElement) {
-        return _emitStaticAccess(element.enclosingElement.type);
+      if (member is MethodElement) {
+        return _emitStaticAccess(member.enclosingElement.type);
       }
     }
     return _visit(target);
   }
 
-  /// Emits a (possibly generic) instance, or static method call.
-  JS.Expression _emitMethodCallInternal(
-      Expression target,
-      MethodInvocation node,
-      List<JS.Expression> args,
-      List<JS.Expression> typeArgs) {
+  /// Emits the [JS.PropertyAccess] for accessors or method calls to
+  /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
+  JS.Expression _emitTargetAccess(
+      JS.Expression jsTarget, JS.Expression jsName, Element member) {
+    if (!_superAllowed && jsTarget is JS.Super) {
+      return _getSuperHelper(member, jsName)
+        ..sourceInformation = jsTarget.sourceInformation;
+    }
+    return new JS.PropertyAccess(jsTarget, jsName);
+  }
+
+  JS.Expression _getSuperHelper(Element member, JS.Expression jsName) {
+    var jsMethod = _superHelpers.putIfAbsent(member.name, () {
+      if (member is PropertyAccessorElement) {
+        var field = member.variable as FieldElement;
+        var name = field.name;
+        var isSetter = member.isSetter;
+        var fn = js.call(
+            isSetter
+                ? 'function(x) { super[#] = x; }'
+                : 'function() { return super[#]; }',
+            [jsName]);
+        return new JS.Method(new JS.TemporaryId(name), fn,
+            isGetter: !isSetter, isSetter: isSetter);
+      } else {
+        var method = member as MethodElement;
+        var name = method.name;
+        // For generic methods, we can simply pass along the type arguments,
+        // and let the resulting closure accept the actual arguments.
+        List<JS.Identifier> params;
+        if (method.typeParameters.isNotEmpty) {
+          params = _emitTypeFormals(method.typeParameters);
+        } else {
+          params = [];
+          for (var param in method.parameters) {
+            if (param.parameterKind == ParameterKind.NAMED) {
+              params.add(namedArgumentTemp);
+              break;
+            }
+            params.add(new JS.Identifier(param.name));
+          }
+        }
+        var fn = js.call(
+            'function(#) { return super[#](#); }', [params, jsName, params]);
+        return new JS.Method(new JS.TemporaryId(name), fn);
+      }
+    });
+    return new JS.PropertyAccess(new JS.This(), jsMethod.name);
+  }
+
+  JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
+    var args = _emitArgumentList(node.argumentList);
+    var typeArgs = _emitInvokeTypeArguments(node);
+
     var type = getStaticType(target);
     var element = node.methodName.staticElement;
     bool isStatic = element is ExecutableElement && element.isStatic;
@@ -3546,8 +3502,7 @@
       assert(typeArgs == null); // Object methods don't take type args.
       return _callHelper('#(#, #)', [name, jsTarget, args]);
     }
-
-    jsTarget = new JS.PropertyAccess(jsTarget, memberName);
+    jsTarget = _emitTargetAccess(jsTarget, memberName, element);
     if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
 
     return new JS.Call(jsTarget, args);
@@ -3994,12 +3949,9 @@
       }
     }
 
-    JS.Expression objExpr;
-    if (target is ClassElement) {
-      objExpr = _emitTopLevelName(target);
-    } else {
-      objExpr = emitLibraryName(target);
-    }
+    var objExpr = target is ClassElement
+        ? _emitTopLevelName(target)
+        : emitLibraryName(target);
 
     return _callHelperStatement('defineLazy(#, { # });', [objExpr, methods]);
   }
@@ -4718,7 +4670,7 @@
   JS.This visitThisExpression(ThisExpression node) => new JS.This();
 
   @override
-  JS.Super visitSuperExpression(SuperExpression node) => new JS.Super();
+  JS.Expression visitSuperExpression(SuperExpression node) => new JS.Super();
 
   @override
   visitPrefixedIdentifier(PrefixedIdentifier node) {
@@ -4819,35 +4771,6 @@
         (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression);
   }
 
-  /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
-  JS.Expression _emitAccess(
-      Expression target, SimpleIdentifier memberId, DartType resultType) {
-    Element member = memberId.staticElement;
-    if (member is PropertyAccessorElement) {
-      member = (member as PropertyAccessorElement).variable;
-    }
-    String memberName = memberId.name;
-    var typeArgs = _getTypeArgs(member, resultType);
-
-    if (target is SuperExpression && !_superAllowed) {
-      return _emitSuperHelperAccess(target, member, memberName, typeArgs);
-    }
-    return _emitAccessInternal(target, member, memberName, typeArgs);
-  }
-
-  JS.Expression _emitSuperHelperAccess(SuperExpression target, Element member,
-      String memberName, List<JS.Expression> typeArgs) {
-    var fakeTypeArgs =
-        typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false);
-
-    var forwardedAccess =
-        _emitAccessInternal(target, member, memberName, fakeTypeArgs);
-    var superForwarder = _getSuperHelperFor(
-        memberName, forwardedAccess, fakeTypeArgs ?? const []);
-
-    return js.call('this.#(#)', [superForwarder, typeArgs ?? const []]);
-  }
-
   List<JS.Expression> _getTypeArgs(Element member, DartType instantiated) {
     DartType type;
     if (member is ExecutableElement) {
@@ -4861,44 +4784,50 @@
     return _emitFunctionTypeArguments(type, instantiated);
   }
 
-  JS.LiteralString _emitDynamicOperationName(String name) =>
-      js.string(options.replCompile ? '${name}Repl' : name);
+  /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
+  JS.Expression _emitAccess(
+      Expression target, SimpleIdentifier memberId, DartType resultType) {
+    var accessor = memberId.staticElement;
+    // If `member` is a getter/setter, get the corresponding
+    var field =
+        accessor is PropertyAccessorElement ? accessor.variable : accessor;
+    String memberName = memberId.name;
+    var typeArgs = _getTypeArgs(accessor, resultType);
 
-  JS.Expression _emitAccessInternal(Expression target, Element member,
-      String memberName, List<JS.Expression> typeArgs) {
-    bool isStatic = member is ClassMemberElement && member.isStatic;
+    bool isStatic = field is ClassMemberElement && field.isStatic;
     var name = _emitMemberName(memberName,
-        type: getStaticType(target), isStatic: isStatic, element: member);
+        type: getStaticType(target), isStatic: isStatic, element: accessor);
     if (isDynamicInvoke(target)) {
       return _callHelper('#(#, #)',
           [_emitDynamicOperationName('dload'), _visit(target), name]);
     }
 
-    var jsTarget = _emitTarget(target, member, isStatic);
-    bool isSuper = jsTarget is JS.Super;
+    var jsTarget = _emitTarget(target, accessor, isStatic);
+
+    var isSuper = jsTarget is JS.Super;
     if (isSuper &&
-        !member.isSynthetic &&
-        member is FieldElementImpl &&
-        !virtualFields.isVirtual(member)) {
+        accessor.isSynthetic &&
+        field is FieldElementImpl &&
+        !virtualFields.isVirtual(field)) {
       // If super.x is a sealed field, then x is an instance property since
       // subclasses cannot override x.
-      jsTarget = new JS.This();
+      jsTarget = annotate(new JS.This(), target);
     }
 
     JS.Expression result;
-    if (member != null && member is MethodElement && !isStatic) {
+    if (accessor is MethodElement && !isStatic) {
       // Tear-off methods: explicitly bind it.
       // To be safe always use the symbolized name when binding on a native
-      // class as bind assumes the name will match the name class sigatures
+      // class as bind assumes the name will match the name class signatures
       // which is symbolized for native classes.
       var safeName = _emitMemberName(memberName,
           type: getStaticType(target),
           isStatic: isStatic,
-          element: member,
+          element: accessor,
           alwaysSymbolizeNative: true);
       if (isSuper) {
-        result =
-            _callHelper('bind(this, #, #.#)', [safeName, jsTarget, safeName]);
+        result = _callHelper('bind(this, #, #)',
+            [safeName, _emitTargetAccess(jsTarget, name, accessor)]);
       } else if (_isObjectMemberCall(target, memberName)) {
         result = _callHelper('bind(#, #, #.#)',
             [jsTarget, _propertyName(memberName), _runtimeModule, memberName]);
@@ -4908,7 +4837,7 @@
     } else if (_isObjectMemberCall(target, memberName)) {
       result = _callHelper('#(#)', [memberName, jsTarget]);
     } else {
-      result = js.call('#.#', [jsTarget, name]);
+      result = _emitTargetAccess(jsTarget, name, accessor);
     }
     if (typeArgs == null) {
       return result;
@@ -4916,6 +4845,9 @@
     return _callHelper('gbind(#, #)', [result, typeArgs]);
   }
 
+  JS.LiteralString _emitDynamicOperationName(String name) =>
+      js.string(options.replCompile ? '${name}Repl' : name);
+
   /// Emits a generic send, like an operator method.
   ///
   /// **Please note** this function does not support method invocation syntax
@@ -5487,7 +5419,7 @@
       Element element}) {
     // Static members skip the rename steps and may require JS interop renames.
     if (isStatic) {
-      return _emitJSInteropStaticMemberName(element) ?? _propertyName(name);
+      return _propertyName(_emitJSInteropStaticMemberName(element) ?? name);
     }
 
     if (name.startsWith('_')) {
diff --git a/pkg/dev_compiler/lib/src/compiler/js_interop.dart b/pkg/dev_compiler/lib/src/compiler/js_interop.dart
index 7e9fcc8..03d64b5 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_interop.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_interop.dart
@@ -74,8 +74,11 @@
 /// the SDK), or `null` if there's none. This is used to control the name
 /// under which functions are compiled and exported.
 String getJSExportName(Element e) {
+  var original = e;
+  if (original is PropertyAccessorElement) e = original.variable;
   if (e.source.isInSystemLibrary) {
-    return getAnnotationName(e, isJSExportNameAnnotation) ?? e.name;
+    var real = original.isSynthetic ? e : original;
+    return getAnnotationName(real, isJSExportNameAnnotation) ?? e.name;
   }
   return e.name;
 }
diff --git a/pkg/front_end/example/incremental_reload/run.dart b/pkg/front_end/example/incremental_reload/run.dart
index 0e196d7..411e7cf 100644
--- a/pkg/front_end/example/incremental_reload/run.dart
+++ b/pkg/front_end/example/incremental_reload/run.dart
@@ -46,7 +46,7 @@
 import 'dart:async';
 import 'dart:convert' show ASCII;
 
-import 'package:front_end/src/vm/reload.dart';
+import '../../tool/vm/reload.dart';
 
 import 'compiler_with_invalidation.dart';
 
diff --git a/pkg/front_end/lib/resolved_ast_generator.dart b/pkg/front_end/lib/resolved_ast_generator.dart
deleted file mode 100644
index 4b37d38..0000000
--- a/pkg/front_end/lib/resolved_ast_generator.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Defines a front-end API for converting source code to resolved ASTs.
-///
-/// Note: this entire library is deprecated.  It is provided as a migration path
-/// until dev_compiler supports Dart Kernel.  Once dev_compiler has been
-/// converted to use Dart Kernel, this functionality will be removed.
-@deprecated
-library front_end.resolved_ast_generator;
-
-import 'dart:async';
-import 'compiler_options.dart';
-import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
-import 'package:analyzer/dart/element/element.dart' show LibraryElement;
-
-/// Processes the build unit whose source files are in [sources].
-///
-/// Intended for modular compilation.
-///
-/// [sources] should be the complete set of source files for a build unit
-/// (including both library and part files).  All of the library files are
-/// compiled to resolved ASTs.
-///
-/// The compilation process is hermetic, meaning that the only files which will
-/// be read are those listed in [sources], [CompilerOptions.inputSummaries], and
-/// [CompilerOptions.sdkSummary].  If a source file attempts to refer to a file
-/// which is not obtainable from these paths, that will result in an error, even
-/// if the file exists on the filesystem.
-///
-/// Any `part` declarations found in [sources] must refer to part files which
-/// are also listed in [sources], otherwise an error results.  (It is not
-/// permitted to refer to a part file declared in another build unit).
-@deprecated
-Future<ResolvedAsts> resolvedAstsFor(
-        List<Uri> sources, CompilerOptions options) =>
-    throw new UnimplementedError();
-
-/// Representation of the resolved ASTs of a build unit.
-///
-/// Not intended to be implemented or extended by clients.
-@deprecated
-abstract class ResolvedAsts {
-  /// The resolved ASTs of the build unit's source libraries.
-  ///
-  /// There is one sub-list per source library; each sub-list consists of the
-  /// resolved AST for the library's defining compilation unit, followed by the
-  /// resolved ASTs for any of the library's part files.
-  List<List<CompilationUnit>> get compilationUnits;
-
-  /// Given a [LibraryElement] referred to by [compilationUnits], determine the
-  /// path to the summary that the library originated from.  If the
-  /// [LibraryElement] did not originate from a summary (i.e. because it
-  /// originated from one of the source files of *this* build unit), return
-  /// `null`.
-  ///
-  /// This can be used by the client to determine which build unit any
-  /// referenced element originated from.
-  String getOriginatingSummary(LibraryElement element);
-}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index 7279ca7..e87c1a2 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -8,6 +8,7 @@
 
 import 'package:kernel/ast.dart' show Library, Program, Source;
 
+import '../errors.dart' show internalError;
 import '../loader.dart' show Loader;
 import '../target_implementation.dart' show TargetImplementation;
 import 'dill_library_builder.dart' show DillLibraryBuilder;
@@ -39,6 +40,9 @@
   }
 
   Future<Null> buildOutline(DillLibraryBuilder builder) async {
+    if (builder.library == null) {
+      internalError("Builder.library for ${builder.uri} should not be null.");
+    }
     builder.library.classes.forEach(builder.addClass);
     builder.library.procedures.forEach(builder.addMember);
     builder.library.typedefs.forEach(builder.addTypedef);
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 959407b..1528888 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -92,7 +92,17 @@
 
   final bool enableNative;
 
-  final bool isBuiltinLibrary;
+  /// Whether to ignore an unresolved reference to `main` within the body of
+  /// `_getMainClosure` when compiling the current library.
+  ///
+  /// This as a temporary workaround. The standalone VM and flutter have
+  /// special logic to resolve `main` in `_getMainClosure`, this flag is used to
+  /// ignore that reference to `main`, but only on libraries where we expect to
+  /// see it (today that is dart:_builtin and dart:ui).
+  ///
+  // TODO(ahe,sigmund): remove when the VM gets rid of the special rule, see
+  // https://github.com/dart-lang/sdk/issues/28989.
+  final bool ignoreMainInGetMainClosure;
 
   @override
   final Uri uri;
@@ -169,8 +179,8 @@
       : enclosingScope = scope,
         library = library,
         enableNative = library.loader.target.enableNative(library),
-        isBuiltinLibrary =
-            library.uri.scheme == 'dart' && library.uri.path == "_builtin",
+        ignoreMainInGetMainClosure = library.uri.scheme == 'dart' &&
+            (library.uri.path == "_builtin" || library.uri.path == "ui"),
         needsImplicitSuperInitializer =
             coreTypes.objectClass != classBuilder?.cls,
         typePromoter = _typeInferrer.typePromoter,
@@ -854,7 +864,7 @@
     Expression b = popForValue();
     Expression a = popForValue();
     VariableDeclaration variable = new VariableDeclaration.forValue(a);
-    push(makeLet(
+    push(new KernelIfNullExpression(
         variable,
         new KernelConditionalExpression(
             buildIsNull(new VariableGet(variable), offsetForToken(token)),
@@ -1081,10 +1091,9 @@
           return new UnresolvedAccessor(this, n, token);
         }
         return new ThisPropertyAccessor(this, token, n, null, null);
-      } else if (isBuiltinLibrary &&
+      } else if (ignoreMainInGetMainClosure &&
           name == "main" &&
           member?.name == "_getMainClosure") {
-        // TODO(ahe): https://github.com/dart-lang/sdk/issues/28989
         return new KernelNullLiteral()..fileOffset = offsetForToken(token);
       } else {
         return new UnresolvedAccessor(this, n, token);
@@ -2648,7 +2657,10 @@
     debugEvent("Assert");
     Expression message = popForValueIfNotNull(commaToken);
     Expression condition = popForValue();
-    AssertStatement statement = new AssertStatement(condition, message);
+    AssertStatement statement = new AssertStatement(condition,
+        conditionStartOffset: leftParenthesis.offset + 1,
+        conditionEndOffset: rightParenthesis.offset,
+        message: message);
     switch (kind) {
       case Assert.Statement:
         push(statement);
diff --git a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
index df6267c..a894a3a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
@@ -11,13 +11,12 @@
         KernelComplexAssignment,
         KernelConditionalExpression,
         KernelMethodInvocation,
+        KernelNullAwarePropertyGet,
         KernelPropertyAssign,
         KernelPropertyGet,
-        KernelPropertySet,
         KernelThisExpression,
         KernelVariableDeclaration,
-        KernelVariableGet,
-        KernelVariableSet;
+        KernelVariableGet;
 
 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken;
 
@@ -218,7 +217,7 @@
     helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel);
     var write = variable.isFinal || variable.isConst
         ? makeInvalidWrite(value)
-        : new KernelVariableSet(variable, value)
+        : new VariableSet(variable, value)
       ..fileOffset = offsetForToken(token);
     complexAssignment?.write = write;
     return write;
@@ -251,7 +250,7 @@
 
   Expression _makeSimpleWrite(Expression value, bool voidContext,
       KernelComplexAssignment complexAssignment) {
-    var write = new KernelPropertySet(receiver, name, value, setter)
+    var write = new PropertySet(receiver, name, value, setter)
       ..fileOffset = offsetForToken(token);
     complexAssignment?.write = write;
     return write;
@@ -272,7 +271,7 @@
 
   Expression _makeWrite(Expression value, bool voidContext,
       KernelComplexAssignment complexAssignment) {
-    var write = new KernelPropertySet(receiverAccess(), name, value, setter)
+    var write = new PropertySet(receiverAccess(), name, value, setter)
       ..fileOffset = offsetForToken(token);
     complexAssignment?.write = write;
     return write;
@@ -309,9 +308,8 @@
 
   Expression _makeWrite(Expression value, bool voidContext,
       KernelComplexAssignment complexAssignment) {
-    var write =
-        new KernelPropertySet(new KernelThisExpression(), name, value, setter)
-          ..fileOffset = offsetForToken(token);
+    var write = new PropertySet(new KernelThisExpression(), name, value, setter)
+      ..fileOffset = offsetForToken(token);
     complexAssignment?.write = write;
     return write;
   }
@@ -340,7 +338,7 @@
 
   Expression _makeWrite(Expression value, bool voidContext,
       KernelComplexAssignment complexAssignment) {
-    var write = new KernelPropertySet(receiverAccess(), name, value, setter)
+    var write = new PropertySet(receiverAccess(), name, value, setter)
       ..fileOffset = offsetForToken(token);
     complexAssignment?.write = write;
     return write;
@@ -348,19 +346,22 @@
 
   Expression _finish(
       Expression body, KernelComplexAssignment complexAssignment) {
-    var nullAwareGuard = new KernelConditionalExpression(
-        buildIsNull(receiverAccess(), offsetForToken(token)),
+    var offset = offsetForToken(token);
+    var nullAwareGuard = new ConditionalExpression(
+        buildIsNull(receiverAccess(), offset),
         new NullLiteral(),
-        body)
-      ..fileOffset = offsetForToken(token);
-    body = makeLet(receiver, nullAwareGuard);
+        body,
+        const DynamicType())
+      ..fileOffset = offset;
     if (complexAssignment != null) {
+      body = makeLet(receiver, nullAwareGuard);
       KernelPropertyAssign kernelPropertyAssign = complexAssignment;
       kernelPropertyAssign.nullAwareGuard = nullAwareGuard;
       kernelPropertyAssign.desugared = body;
       return kernelPropertyAssign;
     } else {
-      return body;
+      return new KernelNullAwarePropertyGet(receiver, nullAwareGuard)
+        ..fileOffset = offset;
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 5043976..7630c71 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -4,6 +4,9 @@
 
 library fasta.kernel_class_builder;
 
+import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
+    show KernelMember;
+
 import 'package:kernel/ast.dart'
     show
         Class,
@@ -195,6 +198,14 @@
       }
     }
     // TODO(ahe): Handle other cases: accessors, operators, and fields.
+
+    // Also record any cases where a field or getter/setter overrides something
+    // in a superclass, since this information will be needed for type
+    // inference.
+    if (declaredMember is KernelMember &&
+        identical(declaredMember.enclosingClass, cls)) {
+      KernelMember.recordOverride(declaredMember, interfaceMember);
+    }
   }
 
   void checkMethodOverride(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index daf3301..b00f560 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -28,8 +28,6 @@
         ThisExpression,
         VariableGet;
 
-import 'package:front_end/src/scanner/token.dart' show Token;
-
 import '../modifier.dart' show constMask, finalMask, staticMask;
 
 import '../names.dart' show indexGetName;
@@ -120,14 +118,7 @@
     ///       String toString() => { 0: ‘E.id0’, . . ., n-1: ‘E.idn-1’}[index]
     ///     }
     members["index"] = new KernelFieldBuilder(
-        null,
-        intType,
-        "index",
-        finalMask,
-        parent,
-        charOffset,
-        // Synthetic token to signal this field is initialized.
-        new Token.eof(charOffset));
+        null, intType, "index", finalMask, parent, charOffset, null, true);
     KernelConstructorBuilder constructorBuilder = new KernelConstructorBuilder(
         null,
         constMask,
@@ -145,15 +136,8 @@
     constructors[""] = constructorBuilder;
     int index = 0;
     List<MapEntry> toStringEntries = <MapEntry>[];
-    KernelFieldBuilder valuesBuilder = new KernelFieldBuilder(
-        null,
-        listType,
-        "values",
-        constMask | staticMask,
-        parent,
-        charOffset,
-        // Synthetic token to signal this field is initialized.
-        new Token.eof(charOffset));
+    KernelFieldBuilder valuesBuilder = new KernelFieldBuilder(null, listType,
+        "values", constMask | staticMask, parent, charOffset, null, true);
     members["values"] = valuesBuilder;
     KernelProcedureBuilder toStringBuilder = new KernelProcedureBuilder(
         null,
@@ -185,15 +169,8 @@
         constantNamesAndOffsets[i] = null;
         continue;
       }
-      KernelFieldBuilder fieldBuilder = new KernelFieldBuilder(
-          null,
-          selfType,
-          name,
-          constMask | staticMask,
-          parent,
-          charOffset,
-          // Synthetic token to signal this field is initialized.
-          new Token.eof(charOffset));
+      KernelFieldBuilder fieldBuilder = new KernelFieldBuilder(null, selfType,
+          name, constMask | staticMask, parent, charOffset, null, true);
       members[name] = fieldBuilder;
       toStringEntries.add(new MapEntry(
           new IntLiteral(index), new StringLiteral("$className.$name")));
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index ee90588..a17f1ce 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -31,19 +31,25 @@
     show Builder, FieldBuilder, KernelTypeBuilder, MetadataBuilder;
 
 class KernelFieldBuilder extends FieldBuilder<Expression> {
-  final Field field;
+  final KernelField field;
   final List<MetadataBuilder> metadata;
   final KernelTypeBuilder type;
-  final Token initializerToken;
+  final Token initializerTokenForInference;
+  final bool hasInitializer;
 
-  KernelFieldBuilder(this.metadata, this.type, String name, int modifiers,
-      Builder compilationUnit, int charOffset, this.initializerToken)
+  KernelFieldBuilder(
+      this.metadata,
+      this.type,
+      String name,
+      int modifiers,
+      Builder compilationUnit,
+      int charOffset,
+      this.initializerTokenForInference,
+      this.hasInitializer)
       : field = new KernelField(null, fileUri: compilationUnit?.relativeFileUri)
           ..fileOffset = charOffset,
         super(name, modifiers, compilationUnit, charOffset);
 
-  bool get hasInitializer => initializerToken != null;
-
   void set initializer(Expression value) {
     if (!hasInitializer && value is! NullLiteral && !isConst && !isFinal) {
       internalError("Attempt to set initializer on field without initializer.");
@@ -51,6 +57,9 @@
     field.initializer = value..parent = field;
   }
 
+  bool get isEligibleForInference =>
+      type == null && (hasInitializer || isInstanceMember);
+
   Field build(SourceLibraryBuilder library) {
     field.name ??= new Name(name, library.target);
     if (type != null) {
@@ -63,8 +72,8 @@
       ..hasImplicitGetter = isInstanceMember
       ..hasImplicitSetter = isInstanceMember && !isConst && !isFinal
       ..isStatic = !isInstanceMember;
-    if (initializerToken != null && !initializerToken.isEof) {
-      library.loader.typeInferenceEngine.recordField(field);
+    if (isEligibleForInference) {
+      library.loader.typeInferenceEngine.recordMember(field);
     }
     return field;
   }
@@ -74,7 +83,7 @@
   @override
   void prepareInitializerInference(
       SourceLibraryBuilder library, ClassBuilder currentClass) {
-    if (initializerToken != null && !initializerToken.isEof) {
+    if (isEligibleForInference) {
       var memberScope =
           currentClass == null ? library.scope : currentClass.scope;
       // TODO(paulberry): Is it correct to pass library.uri into BodyBuilder, or
@@ -83,22 +92,24 @@
       var listener = new TypeInferenceListener();
       var typeInferrer = typeInferenceEngine.createTopLevelTypeInferrer(
           listener, field.enclosingClass?.thisType, field);
-      var bodyBuilder = new BodyBuilder(
-          library,
-          this,
-          memberScope,
-          null,
-          typeInferenceEngine.classHierarchy,
-          typeInferenceEngine.coreTypes,
-          currentClass,
-          isInstanceMember,
-          library.uri,
-          typeInferrer);
-      Parser parser = new Parser(bodyBuilder);
-      Token token = parser.parseExpression(initializerToken);
-      Expression expression = bodyBuilder.popForValue();
-      bodyBuilder.checkEmpty(token.charOffset);
-      initializer = expression;
+      if (hasInitializer) {
+        var bodyBuilder = new BodyBuilder(
+            library,
+            this,
+            memberScope,
+            null,
+            typeInferenceEngine.classHierarchy,
+            typeInferenceEngine.coreTypes,
+            currentClass,
+            isInstanceMember,
+            library.uri,
+            typeInferrer);
+        Parser parser = new Parser(bodyBuilder);
+        Token token = parser.parseExpression(initializerTokenForInference);
+        Expression expression = bodyBuilder.popForValue();
+        bodyBuilder.checkEmpty(token.charOffset);
+        initializer = expression;
+      }
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 67b1641..933fe62 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -464,12 +464,18 @@
   }
 
   @override
-  void addField(List<MetadataBuilder> metadata, int modifiers,
-      KernelTypeBuilder type, String name, int charOffset, Token initializer) {
+  void addField(
+      List<MetadataBuilder> metadata,
+      int modifiers,
+      KernelTypeBuilder type,
+      String name,
+      int charOffset,
+      Token initializerTokenForInference,
+      bool hasInitializer) {
     addBuilder(
         name,
-        new KernelFieldBuilder(
-            metadata, type, name, modifiers, this, charOffset, initializer),
+        new KernelFieldBuilder(metadata, type, name, modifiers, this,
+            charOffset, initializerTokenForInference, hasInitializer),
         charOffset);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 6a5b9a3..7c54474 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -4,6 +4,15 @@
 
 library fasta.kernel_procedure_builder;
 
+import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
+    show KernelProcedure;
+
+import 'package:front_end/src/fasta/source/source_library_builder.dart'
+    show SourceLibraryBuilder;
+
+import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
+    show TypeInferenceListener;
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
@@ -165,7 +174,7 @@
     return function = result;
   }
 
-  Member build(LibraryBuilder library);
+  Member build(SourceLibraryBuilder library);
 
   void becomeNative(Loader loader) {
     target.isExternal = true;
@@ -185,7 +194,7 @@
 }
 
 class KernelProcedureBuilder extends KernelFunctionBuilder {
-  final Procedure procedure;
+  final KernelProcedure procedure;
   final int charOpenParenOffset;
 
   AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
@@ -206,7 +215,7 @@
       int charEndOffset,
       [String nativeMethodName,
       this.redirectionTarget])
-      : procedure = new Procedure(null, kind, null,
+      : procedure = new KernelProcedure(null, kind, null,
             fileUri: compilationUnit?.relativeFileUri)
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset,
@@ -236,7 +245,18 @@
     }
   }
 
-  Procedure build(LibraryBuilder library) {
+  bool get isEligibleForGetterSetterInference {
+    if (!isInstanceMember) return false;
+    if (isGetter) {
+      return returnType == null;
+    } else if (isSetter) {
+      return formals != null && formals.length > 0 && formals[0].type == null;
+    } else {
+      return false;
+    }
+  }
+
+  Procedure build(SourceLibraryBuilder library) {
     // TODO(ahe): I think we may call this twice on parts. Investigate.
     if (procedure.name == null) {
       procedure.function = buildFunction(library);
@@ -249,10 +269,24 @@
       procedure.isConst = isConst;
       procedure.name = new Name(name, library.target);
     }
+    if (isEligibleForGetterSetterInference) {
+      library.loader.typeInferenceEngine.recordMember(procedure);
+    }
     return procedure;
   }
 
   Procedure get target => procedure;
+
+  @override
+  void prepareInitializerInference(
+      SourceLibraryBuilder library, ClassBuilder currentClass) {
+    if (isEligibleForGetterSetterInference) {
+      var typeInferenceEngine = library.loader.typeInferenceEngine;
+      var listener = new TypeInferenceListener();
+      typeInferenceEngine.createTopLevelTypeInferrer(
+          listener, procedure.enclosingClass?.thisType, procedure);
+    }
+  }
 }
 
 // TODO(ahe): Move this to own file?
@@ -297,7 +331,7 @@
     return isRedirectingGenerativeConstructorImplementation(constructor);
   }
 
-  Constructor build(LibraryBuilder library) {
+  Constructor build(SourceLibraryBuilder library) {
     if (constructor.name == null) {
       constructor.function = buildFunction(library);
       constructor.function.parent = constructor;
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 c737ffd..003251f 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
@@ -53,6 +53,34 @@
   }
 }
 
+bool _isOverloadableArithmeticOperator(String name) {
+  return identical(name, '+') ||
+      identical(name, '-') ||
+      identical(name, '*') ||
+      identical(name, '%');
+}
+
+bool _isUserDefinableOperator(String name) {
+  return identical(name, '<') ||
+      identical(name, '>') ||
+      identical(name, '<=') ||
+      identical(name, '>=') ||
+      identical(name, '==') ||
+      identical(name, '-') ||
+      identical(name, '+') ||
+      identical(name, '/') ||
+      identical(name, '~/') ||
+      identical(name, '*') ||
+      identical(name, '%') ||
+      identical(name, '|') ||
+      identical(name, '^') ||
+      identical(name, '&') ||
+      identical(name, '<<') ||
+      identical(name, '>>') ||
+      identical(name, '[]=') ||
+      identical(name, '~');
+}
+
 /// Concrete shadow object representing a set of invocation arguments.
 class KernelArguments extends Arguments {
   bool _hasExplicitTypeArguments;
@@ -343,7 +371,8 @@
           .findMethodInvocationMember(writeContext, combiner, silent: true);
       if (combinerMember is Procedure) {
         isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
-            .isOverloadedArithmeticOperator(combinerMember);
+            .isOverloadedArithmeticOperatorAndType(
+                combinerMember, writeContext);
       }
       if (isPostIncDec) {
         return inferredType;
@@ -549,30 +578,6 @@
   }
 }
 
-/// Shadow object for [DirectPropertySet].
-class KernelDirectPropertySet extends DirectPropertySet
-    implements KernelExpression {
-  KernelDirectPropertySet(Expression receiver, Member target, Expression value)
-      : super(receiver, target, value);
-
-  KernelDirectPropertySet.byReference(
-      Expression receiver, Reference targetReference, Expression value)
-      : super.byReference(receiver, targetReference, value);
-
-  @override
-  void _collectDependencies(KernelDependencyCollector collector) {
-    // Assignment expressions are not immediately evident expressions.
-    collector.recordNotImmediatelyEvident(fileOffset);
-  }
-
-  @override
-  DartType _inferExpression(
-      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    // TODO(scheglov): implement.
-    return typeNeeded ? const DynamicType() : null;
-  }
-}
-
 /// Concrete shadow object representing a double literal in kernel form.
 class KernelDoubleLiteral extends DoubleLiteral implements KernelExpression {
   KernelDoubleLiteral(double value) : super(value);
@@ -655,26 +660,21 @@
 }
 
 /// Concrete shadow object representing a field in kernel form.
-class KernelField extends Field {
-  bool _implicitlyTyped = true;
-
+class KernelField extends Field implements KernelMember {
+  @override
   FieldNode _fieldNode;
 
-  bool _isInferred = false;
-
+  @override
   KernelTypeInferrer _typeInferrer;
 
   KernelField(Name name, {String fileUri}) : super(name, fileUri: fileUri) {}
 
   @override
-  void set type(DartType value) {
-    _implicitlyTyped = false;
-    super.type = value;
-  }
-
-  void _setInferredType(DartType inferredType) {
-    _isInferred = true;
-    super.type = inferredType;
+  void setInferredType(
+      TypeInferenceEngineImpl engine, String uri, DartType inferredType) {
+    engine.instrumentation?.record(Uri.parse(uri), fileOffset, 'topType',
+        new InstrumentationValueForType(inferredType));
+    type = inferredType;
   }
 }
 
@@ -756,11 +756,13 @@
         inferrer.inferExpression(parameter.initializer, parameter.type, false);
       }
     }
-    var oldClosureContext = inferrer.closureContext;
-    inferrer.closureContext =
-        new ClosureContext(inferrer, function.asyncMarker, function.returnType);
-    inferrer.inferStatement(function.body);
-    inferrer.closureContext = oldClosureContext;
+    if (!inferrer.isTopLevel) {
+      var oldClosureContext = inferrer.closureContext;
+      inferrer.closureContext = new ClosureContext(
+          inferrer, function.asyncMarker, function.returnType);
+      inferrer.inferStatement(function.body);
+      inferrer.closureContext = oldClosureContext;
+    }
     inferrer.listener.functionDeclarationExit(this);
   }
 }
@@ -933,6 +935,56 @@
   }
 }
 
+/// Concrete shadow object representing an if-null expression.
+///
+/// An if-null expression of the form `a ?? b` is represented as the kernel
+/// expression:
+///
+///     let v = a in v == null ? b : v
+class KernelIfNullExpression extends Let implements KernelExpression {
+  KernelIfNullExpression(VariableDeclaration variable, Expression body)
+      : super(variable, body);
+
+  @override
+  ConditionalExpression get body => super.body;
+
+  /// Returns the expression to the left of `??`.
+  Expression get _lhs => variable.initializer;
+
+  /// Returns the expression to the right of `??`.
+  Expression get _rhs => body.then;
+
+  @override
+  void _collectDependencies(KernelDependencyCollector collector) {
+    // If-null expressions are not immediately evident expressions.
+    collector.recordNotImmediatelyEvident(fileOffset);
+  }
+
+  @override
+  DartType _inferExpression(
+      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+    typeNeeded = inferrer.listener.ifNullEnter(this, typeContext) || typeNeeded;
+    // To infer `e0 ?? e1` in context K:
+    // - Infer e0 in context K to get T0
+    var lhsType = inferrer.inferExpression(_lhs, typeContext, true);
+    variable.type = lhsType;
+    // - Let J = T0 if K is `_` else K.
+    var rhsContext = typeContext ?? lhsType;
+    // - Infer e1 in context J to get T1
+    var rhsType =
+        inferrer.inferExpression(_rhs, rhsContext, typeContext == null);
+    // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
+    //   UP(t0, t1)
+    // - Then the inferred type is T.
+    var inferredType = typeContext == null
+        ? inferrer.typeSchemaEnvironment.getLeastUpperBound(lhsType, rhsType)
+        : greatestClosure(inferrer.coreTypes, typeContext);
+    body.staticType = inferredType;
+    inferrer.listener.ifNullExit(this, inferredType);
+    return inferredType;
+  }
+}
+
 /// Concrete shadow object representing an if statement in kernel form.
 class KernelIfStatement extends IfStatement implements KernelStatement {
   KernelIfStatement(Expression condition, Statement then, Statement otherwise)
@@ -1256,6 +1308,33 @@
   }
 }
 
+/// Abstract shadow object representing a field or procedure in kernel form.
+abstract class KernelMember implements Member {
+  String get fileUri;
+
+  FieldNode get _fieldNode;
+
+  void set _fieldNode(FieldNode value);
+
+  KernelTypeInferrer get _typeInferrer;
+
+  void set _typeInferrer(KernelTypeInferrer value);
+
+  void setInferredType(
+      TypeInferenceEngineImpl engine, String uri, DartType inferredType);
+
+  static FieldNode getFieldNode(Member member) {
+    if (member is KernelMember) return member._fieldNode;
+    return null;
+  }
+
+  static void recordOverride(KernelMember member, Member overriddenMember) {
+    if (member._fieldNode != null) {
+      member._fieldNode.overrides.add(overriddenMember);
+    }
+  }
+}
+
 /// Shadow object for [MethodInvocation].
 class KernelMethodInvocation extends MethodInvocation
     implements KernelExpression {
@@ -1273,10 +1352,7 @@
     // The inference dependencies are the inference dependencies of the
     // receiver.
     collector.collectDependencies(receiver);
-    if (identical(name, '+') ||
-        identical(name, '-') ||
-        identical(name, '*') ||
-        identical(name, '%')) {
+    if (_isOverloadableArithmeticOperator(name.name)) {
       collector.collectDependencies(arguments.positional[0]);
     }
   }
@@ -1293,14 +1369,28 @@
         inferrer.findMethodInvocationMember(receiverType, this);
     if (interfaceMember is Procedure) {
       isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
-          .isOverloadedArithmeticOperator(interfaceMember);
+          .isOverloadedArithmeticOperatorAndType(interfaceMember, receiverType);
     }
     var calleeType = inferrer.getCalleeFunctionType(
         interfaceMember, receiverType, name, !_isImplicitCall);
+    bool forceArgumentInference = false;
+    if (inferrer.isDryRun) {
+      if (_isUserDefinableOperator(name.name)) {
+        // If this is an overloadable arithmetic operator, then type inference
+        // might depend on the RHS, so conservatively assume it does.
+        forceArgumentInference = _isOverloadableArithmeticOperator(name.name);
+      } else {
+        // If no type arguments were given, then type inference might depend on
+        // the arguments (because the called method might be generic), so
+        // conservatively assume it does.
+        forceArgumentInference = getExplicitTypeArguments(arguments) == null;
+      }
+    }
     var inferredType = inferrer.inferInvocation(typeContext, typeNeeded,
         fileOffset, calleeType, calleeType.returnType, arguments,
         isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
-        receiverType: receiverType);
+        receiverType: receiverType,
+        forceArgumentInference: forceArgumentInference);
     inferrer.listener.methodInvocationExit(this, inferredType);
     return inferredType;
   }
@@ -1328,6 +1418,36 @@
   }
 }
 
+/// Concrete shadow object representing a null-aware read from a property.
+///
+/// A null-aware property get of the form `a?.b` is represented as the kernel
+/// expression:
+///
+///     let v = a in v == null ? null : v.b
+class KernelNullAwarePropertyGet extends Let implements KernelExpression {
+  KernelNullAwarePropertyGet(
+      VariableDeclaration variable, ConditionalExpression body)
+      : super(variable, body);
+
+  @override
+  ConditionalExpression get body => super.body;
+
+  PropertyGet get _desugaredGet => body.otherwise;
+
+  @override
+  void _collectDependencies(KernelDependencyCollector collector) {
+    // Null aware expressions are not immediately evident.
+    collector.recordNotImmediatelyEvident(fileOffset);
+  }
+
+  @override
+  DartType _inferExpression(
+      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+    return inferrer.inferPropertyGet(this, variable.initializer, fileOffset,
+        _desugaredGet, typeContext, typeNeeded);
+  }
+}
+
 /// Concrete shadow object representing a null literal in kernel form.
 class KernelNullLiteral extends NullLiteral implements KernelExpression {
   @override
@@ -1346,6 +1466,39 @@
   }
 }
 
+/// Concrete shadow object representing a procedure in kernel form.
+class KernelProcedure extends Procedure implements KernelMember {
+  @override
+  FieldNode _fieldNode;
+
+  @override
+  KernelTypeInferrer _typeInferrer;
+
+  KernelProcedure(Name name, ProcedureKind kind, FunctionNode function,
+      {String fileUri})
+      : super(name, kind, function, fileUri: fileUri);
+
+  @override
+  void setInferredType(
+      TypeInferenceEngineImpl engine, String uri, DartType inferredType) {
+    if (isSetter) {
+      if (function.positionalParameters.length > 0) {
+        var parameter = function.positionalParameters[0];
+        engine.instrumentation?.record(Uri.parse(uri), parameter.fileOffset,
+            'topType', new InstrumentationValueForType(inferredType));
+        parameter.type = inferredType;
+      }
+    } else if (isGetter) {
+      engine.instrumentation?.record(Uri.parse(uri), fileOffset, 'topType',
+          new InstrumentationValueForType(inferredType));
+      function.returnType = inferredType;
+    } else {
+      internalError(
+          'setInferredType called on a procedure that is not an accessor');
+    }
+  }
+}
+
 /// Concrete shadow object representing an assignment to a property.
 class KernelPropertyAssign extends KernelComplexAssignmentWithReceiver {
   /// If this assignment uses null-aware access (`?.`), the conditional
@@ -1378,6 +1531,21 @@
     Member writeMember;
     if (write != null) {
       writeMember = inferrer.findPropertySetMember(receiverType, write);
+      if (inferrer.isTopLevel &&
+          ((writeMember is Procedure &&
+                  writeMember.kind == ProcedureKind.Setter) ||
+              writeMember is Field)) {
+        if (TypeInferenceEngineImpl.fullTopLevelInference) {
+          if (writeMember is KernelField && writeMember._fieldNode != null) {
+            inferrer.engine
+                .inferFieldFused(writeMember._fieldNode, inferrer.fieldNode);
+          }
+        } else {
+          // References to fields and setters can't be relied upon for top level
+          // inference.
+          inferrer.recordNotImmediatelyEvident(fileOffset);
+        }
+      }
     }
     // To replicate analyzer behavior, we base type inference on the write
     // member.  TODO(paulberry): would it be better to use the read member when
@@ -1420,59 +1588,8 @@
   @override
   DartType _inferExpression(
       KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    typeNeeded =
-        inferrer.listener.propertyGetEnter(this, typeContext) || typeNeeded;
-    // First infer the receiver so we can look up the getter that was invoked.
-    var receiverType = inferrer.inferExpression(receiver, null, true);
-    Member interfaceMember =
-        inferrer.findInterfaceMember(receiverType, name, fileOffset);
-    if (inferrer.isTopLevel &&
-        ((interfaceMember is Procedure &&
-                interfaceMember.kind == ProcedureKind.Getter) ||
-            interfaceMember is Field)) {
-      // References to fields and getters can't be relied upon for top level
-      // inference.
-      inferrer.recordNotImmediatelyEvident(fileOffset);
-    }
-    interfaceTarget = interfaceMember;
-    var inferredType =
-        inferrer.getCalleeType(interfaceMember, receiverType, name);
-    // TODO(paulberry): Infer tear-off type arguments if appropriate.
-    inferrer.listener.propertyGetExit(this, inferredType);
-    return typeNeeded ? inferredType : null;
-  }
-}
-
-/// Shadow object for [PropertyGet].
-class KernelPropertySet extends PropertySet implements KernelExpression {
-  KernelPropertySet(Expression receiver, Name name, Expression value,
-      [Member interfaceTarget])
-      : super(receiver, name, value, interfaceTarget);
-
-  KernelPropertySet.byReference(Expression receiver, Name name,
-      Expression value, Reference interfaceTargetReference)
-      : super.byReference(receiver, name, value, interfaceTargetReference);
-
-  @override
-  void _collectDependencies(KernelDependencyCollector collector) {
-    // Assignment expressions are not immediately evident expressions.
-    collector.recordNotImmediatelyEvident(fileOffset);
-  }
-
-  @override
-  DartType _inferExpression(
-      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    typeNeeded =
-        inferrer.listener.propertySetEnter(this, typeContext) || typeNeeded;
-    // First infer the receiver so we can look up the setter that was invoked.
-    var receiverType = inferrer.inferExpression(receiver, null, true);
-    Member interfaceMember = inferrer
-        .findInterfaceMember(receiverType, name, fileOffset, setter: true);
-    interfaceTarget = interfaceMember;
-    var setterType = inferrer.getSetterType(interfaceMember, receiverType);
-    var inferredType = inferrer.inferExpression(value, setterType, typeNeeded);
-    inferrer.listener.propertySetExit(this, inferredType);
-    return typeNeeded ? inferredType : null;
+    return inferrer.inferPropertyGet(
+        this, receiver, fileOffset, this, typeContext, typeNeeded);
   }
 }
 
@@ -1554,6 +1671,17 @@
     var write = this.write;
     if (write is StaticSet) {
       writeContext = write.target.setterType;
+      var target = write.target;
+      if (target is KernelField && target._fieldNode != null) {
+        if (inferrer.isDryRun) {
+          inferrer.recordDryRunDependency(target._fieldNode);
+        }
+        if (TypeInferenceEngineImpl.fusedTopLevelInference &&
+            inferrer.isTopLevel) {
+          inferrer.engine
+              .inferFieldFused(target._fieldNode, inferrer.fieldNode);
+        }
+      }
     }
     var inferredType = _inferRhs(inferrer, writeContext);
     inferrer.listener.staticAssignExit(desugared, inferredType);
@@ -1590,6 +1718,16 @@
       KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
     typeNeeded =
         inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded;
+    var target = this.target;
+    if (target is KernelField && target._fieldNode != null) {
+      if (inferrer.isDryRun) {
+        inferrer.recordDryRunDependency(target._fieldNode);
+      }
+      if (TypeInferenceEngineImpl.fusedTopLevelInference &&
+          inferrer.isTopLevel) {
+        inferrer.engine.inferFieldFused(target._fieldNode, inferrer.fieldNode);
+      }
+    }
     var inferredType = typeNeeded ? target.getterType : null;
     inferrer.listener.staticGetExit(this, inferredType);
     return inferredType;
@@ -1625,27 +1763,6 @@
   }
 }
 
-/// Shadow object for [StaticSet].
-class KernelStaticSet extends StaticSet implements KernelExpression {
-  KernelStaticSet(Member target, Expression value) : super(target, value);
-
-  KernelStaticSet.byReference(Reference targetReference, Expression value)
-      : super.byReference(targetReference, value);
-
-  @override
-  void _collectDependencies(KernelDependencyCollector collector) {
-    // Assignment expressions are not immediately evident expressions.
-    collector.recordNotImmediatelyEvident(fileOffset);
-  }
-
-  @override
-  DartType _inferExpression(
-      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    // TODO(scheglov): implement.
-    return typeNeeded ? const DynamicType() : null;
-  }
-}
-
 /// Concrete shadow object representing a string concatenation in kernel form.
 class KernelStringConcatenation extends StringConcatenation
     implements KernelExpression {
@@ -1746,30 +1863,6 @@
   }
 }
 
-/// Shadow object for [SuperPropertySet].
-class KernelSuperPropertySet extends SuperPropertySet
-    implements KernelExpression {
-  KernelSuperPropertySet(Name name, Expression value, Member interfaceTarget)
-      : super(name, value, interfaceTarget);
-
-  KernelSuperPropertySet.byReference(
-      Name name, Expression value, Reference interfaceTargetReference)
-      : super.byReference(name, value, interfaceTargetReference);
-
-  @override
-  void _collectDependencies(KernelDependencyCollector collector) {
-    // Assignment expressions are not immediately evident expressions.
-    collector.recordNotImmediatelyEvident(fileOffset);
-  }
-
-  @override
-  DartType _inferExpression(
-      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    // TODO(scheglov): implement.
-    return typeNeeded ? const DynamicType() : null;
-  }
-}
-
 /// Shadow object for [SymbolLiteral].
 class KernelSymbolLiteral extends SymbolLiteral implements KernelExpression {
   KernelSymbolLiteral(String value) : super(value);
@@ -1827,14 +1920,9 @@
       : super(instrumentation, strongMode);
 
   @override
-  void clearFieldInitializer(KernelField field) {
-    field.initializer = null;
-  }
-
-  @override
-  FieldNode createFieldNode(KernelField field) {
-    FieldNode fieldNode = new FieldNode(this, field);
-    field._fieldNode = fieldNode;
+  FieldNode createFieldNode(KernelMember member) {
+    FieldNode fieldNode = new FieldNode(this, member);
+    member._fieldNode = fieldNode;
     return fieldNode;
   }
 
@@ -1842,44 +1930,19 @@
   KernelTypeInferrer createLocalTypeInferrer(
       Uri uri, TypeInferenceListener listener, InterfaceType thisType) {
     return new KernelTypeInferrer._(
-        this, uri.toString(), listener, false, thisType);
+        this, uri.toString(), listener, false, thisType, null);
   }
 
   @override
   KernelTypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener,
-      InterfaceType thisType, KernelField field) {
-    return field._typeInferrer =
-        new KernelTypeInferrer._(this, field.fileUri, listener, true, thisType);
+      InterfaceType thisType, KernelMember member) {
+    return member._typeInferrer = new KernelTypeInferrer._(
+        this, member.fileUri, listener, true, thisType, member._fieldNode);
   }
 
   @override
-  bool fieldHasInitializer(KernelField field) {
-    return field.initializer != null;
-  }
-
-  @override
-  DartType getFieldDeclaredType(KernelField field) {
-    return field._implicitlyTyped ? null : field.type;
-  }
-
-  @override
-  int getFieldOffset(KernelField field) {
-    return field.fileOffset;
-  }
-
-  @override
-  KernelTypeInferrer getFieldTypeInferrer(KernelField field) {
-    return field._typeInferrer;
-  }
-
-  @override
-  bool isFieldInferred(KernelField field) {
-    return field._isInferred;
-  }
-
-  @override
-  void setFieldInferredType(KernelField field, DartType inferredType) {
-    field._setInferredType(inferredType);
+  KernelTypeInferrer getFieldTypeInferrer(KernelMember member) {
+    return member._typeInferrer;
   }
 }
 
@@ -1889,9 +1952,14 @@
   @override
   final typePromoter = new KernelTypePromoter();
 
-  KernelTypeInferrer._(KernelTypeInferenceEngine engine, String uri,
-      TypeInferenceListener listener, bool topLevel, InterfaceType thisType)
-      : super(engine, uri, listener, topLevel, thisType);
+  KernelTypeInferrer._(
+      KernelTypeInferenceEngine engine,
+      String uri,
+      TypeInferenceListener listener,
+      bool topLevel,
+      InterfaceType thisType,
+      FieldNode fieldNode)
+      : super(engine, uri, listener, topLevel, thisType, fieldNode);
 
   @override
   Expression getFieldInitializer(KernelField field) {
@@ -1901,6 +1969,11 @@
   @override
   DartType inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded) {
+    // When doing top level inference, we skip subexpressions whose type isn't
+    // needed so that we don't induce bogus dependencies on fields mentioned in
+    // those subexpressions.
+    if (!typeNeeded && isTopLevel) return null;
+
     if (expression is KernelExpression) {
       // Use polymorphic dispatch on [KernelExpression] to perform whatever kind
       // of type inference is correct for this kind of statement.
@@ -2164,30 +2237,6 @@
   }
 }
 
-/// Concrete shadow object representing a write to a variable in kernel form.
-class KernelVariableSet extends VariableSet implements KernelExpression {
-  KernelVariableSet(VariableDeclaration variable, Expression value)
-      : super(variable, value);
-
-  @override
-  void _collectDependencies(KernelDependencyCollector collector) {
-    // Assignment expressions are not immediately evident expressions.
-    collector.recordNotImmediatelyEvident(fileOffset);
-  }
-
-  @override
-  DartType _inferExpression(
-      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
-    var variable = this.variable as KernelVariableDeclaration;
-    typeNeeded =
-        inferrer.listener.variableSetEnter(this, typeContext) || typeNeeded;
-    var inferredType =
-        inferrer.inferExpression(value, variable.type, typeNeeded);
-    inferrer.listener.variableSetExit(this, inferredType);
-    return inferredType;
-  }
-}
-
 /// Concrete shadow object representing a yield statement in kernel form.
 class KernelYieldStatement extends YieldStatement implements KernelStatement {
   KernelYieldStatement(Expression expression, {bool isYieldStar: false})
@@ -2206,8 +2255,7 @@
               ? inferrer.coreTypes.streamClass
               : inferrer.coreTypes.iterableClass);
     }
-    var inferredType = inferrer.inferExpression(
-        expression, typeContext, closureContext != null);
+    var inferredType = inferrer.inferExpression(expression, typeContext, true);
     closureContext.handleYield(inferrer, isYieldStar, inferredType);
     inferrer.listener.yieldStatementExit(this);
   }
diff --git a/pkg/front_end/lib/src/fasta/scanner/recover.dart b/pkg/front_end/lib/src/fasta/scanner/recover.dart
index e14fd23..70484c4 100644
--- a/pkg/front_end/lib/src/fasta/scanner/recover.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/recover.dart
@@ -137,7 +137,7 @@
   }
 
   recoverHexDigit() {
-    return synthesizeToken(errorTail.charOffset, "-1", TokenType.INT)
+    return synthesizeToken(errorTail.charOffset, "0", TokenType.INT)
       ..next = errorTail.next;
   }
 
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 2fa7259..1993816 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -50,6 +50,12 @@
 
   final bool enableNative;
 
+  /// When true, recoverable parser errors are silently ignored. This is
+  /// because they will be reported by the BodyBuilder later. However, typedefs
+  /// are fully compiled by the outline builder, so parser errors are turned on
+  /// when parsing typedefs.
+  bool silenceParserErrors = true;
+
   String nativeMethodName;
 
   OutlineBuilder(SourceLibraryBuilder library)
@@ -597,6 +603,7 @@
   @override
   void beginFunctionTypeAlias(Token token) {
     library.beginNestedDeclaration(null, hasMembers: false);
+    silenceParserErrors = false;
   }
 
   @override
@@ -649,6 +656,7 @@
     library.addFunctionTypeAlias(
         metadata, returnType, name, typeVariables, formals, charOffset);
     checkEmpty(typedefKeyword.charOffset);
+    silenceParserErrors = true;
   }
 
   @override
@@ -815,6 +823,15 @@
   }
 
   @override
+  void handleRecoverableError(Token token, FastaMessage message) {
+    if (silenceParserErrors) {
+      debugEvent("RecoverableError");
+    } else {
+      super.handleRecoverableError(token, message);
+    }
+  }
+
+  @override
   Token handleUnrecoverableError(Token token, FastaMessage message) {
     if (enableNative && message.code == codeExpectedBlockToSkip) {
       var target = library.loader.target;
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 f7d8952..7e992bc 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
@@ -188,20 +188,29 @@
       List<T> interfaces,
       int charOffset);
 
-  void addField(List<MetadataBuilder> metadata, int modifiers, T type,
-      String name, int charOffset, Token initializer);
+  void addField(
+      List<MetadataBuilder> metadata,
+      int modifiers,
+      T type,
+      String name,
+      int charOffset,
+      Token initializerTokenForInference,
+      bool hasInitializer);
 
   void addFields(List<MetadataBuilder> metadata, int modifiers, T type,
       List<Object> fieldsInfo) {
     for (int i = 0; i < fieldsInfo.length; i += 4) {
       String name = fieldsInfo[i];
       int charOffset = fieldsInfo[i + 1];
-      Token initializer = fieldsInfo[i + 2];
-      if (initializer != null) {
+      bool hasInitializer = fieldsInfo[i + 2] != null;
+      Token initializerTokenForInference =
+          type == null ? fieldsInfo[i + 2] : null;
+      if (initializerTokenForInference != null) {
         Token beforeLast = fieldsInfo[i + 3];
         beforeLast.setNext(new Token.eof(beforeLast.next.offset));
       }
-      addField(metadata, modifiers, type, name, charOffset, initializer);
+      addField(metadata, modifiers, type, name, charOffset,
+          initializerTokenForInference, hasInitializer);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 15e7bc9..ee41662 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -4,17 +4,19 @@
 
 import 'package:front_end/src/base/instrumentation.dart';
 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker;
+import 'package:front_end/src/fasta/errors.dart';
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart';
 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
 import 'package:kernel/ast.dart'
-    show Class, DartType, DynamicType, InterfaceType;
+    show Class, DartType, DynamicType, Field, InterfaceType, Member, Procedure;
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
+import 'package:kernel/type_algebra.dart';
 
-/// Data structure for tracking dependencies between fields that require type
-/// inference.
+/// Data structure for tracking dependencies among fields, getters, and setters
+/// that require type inference.
 ///
 /// TODO(paulberry): see if it's possible to make this class more lightweight
 /// by changing the API so that the walker is passed to computeDependencies().
@@ -22,19 +24,48 @@
 class FieldNode extends dependencyWalker.Node<FieldNode> {
   final TypeInferenceEngineImpl _typeInferenceEngine;
 
-  final KernelField _field;
+  final KernelMember member;
 
   bool isImmediatelyEvident = false;
 
-  FieldNode(this._typeInferenceEngine, this._field);
+  FieldState state = FieldState.NotInferredYet;
+
+  /// If [state] is [FieldState.Inferring], and type inference for this field
+  /// is waiting on type inference of some other field, the field that is being
+  /// waited on.
+  ///
+  /// Otherwise `null`.
+  FieldNode currentDependency;
+
+  final overrides = <Member>[];
+
+  FieldNode(this._typeInferenceEngine, this.member);
 
   @override
-  bool get isEvaluated => _typeInferenceEngine.isFieldInferred(_field);
+  bool get isEvaluated => state == FieldState.Inferred;
 
   @override
   List<FieldNode> computeDependencies() {
     return _typeInferenceEngine.computeFieldDependencies(this);
   }
+
+  @override
+  String toString() => member.toString();
+}
+
+/// Enum tracking the type inference state of a field.
+enum FieldState {
+  /// The field's type has not been inferred yet.
+  NotInferredYet,
+
+  /// Type inference is in progress for the field.
+  ///
+  /// This means that code is currently on the stack which is attempting to
+  /// determine the type of the field.
+  Inferring,
+
+  /// The field's type has been inferred.
+  Inferred
 }
 
 /// Keeps track of the global state for the type inference that occurs outside
@@ -56,7 +87,7 @@
   /// Creates a [TypeInferrer] object which is ready to perform type inference
   /// on the given [field].
   TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener,
-      InterfaceType thisType, KernelField field);
+      InterfaceType thisType, KernelMember member);
 
   /// Performs the second phase of top level initializer inference, which is to
   /// visit all fields and top level variables that were passed to [recordField]
@@ -67,12 +98,12 @@
   /// [hierarchy], using the given [coreTypes].
   void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy);
 
-  /// Records that the given [field] will need top level type inference.
-  void recordField(KernelField field);
-
   /// Records that the given initializing [formal] will need top level type
   /// inference.
   void recordInitializingFormal(KernelVariableDeclaration formal);
+
+  /// Records that the given [member] will need top level type inference.
+  void recordMember(KernelMember member);
 }
 
 /// Derived class containing generic implementations of
@@ -82,6 +113,29 @@
 /// possible without knowing the identity of the type parameter.  It defers to
 /// abstract methods for everything else.
 abstract class TypeInferenceEngineImpl extends TypeInferenceEngine {
+  /// Enables "expanded top level inference", which allows top level inference
+  /// to support all expressions, not just those defined as "immediately
+  /// evident" by https://github.com/dart-lang/sdk/pull/28218.
+  static const bool expandedTopLevelInference = true;
+
+  /// Enables "fused top level inference", which fuses dependency collection and
+  /// type inference of a field into a single step (a dependency is detected at
+  /// the time type inference attempts to read the depended-upon type, and this
+  /// triggers a recursive evaluation of the depended-upon type).
+  ///
+  /// This avoids some unnecessary dependencies, since we now know for sure
+  /// whether a dependency will be needed at the time we evaluate it.
+  ///
+  /// Requires [expandedTopLevelInference] to be `true`.
+  static const bool fusedTopLevelInference = true;
+
+  /// Enables "full top level inference", which allows a top level or static
+  /// field's inferred type to depend on the type of an instance field (provided
+  /// there are no circular dependencies).
+  ///
+  /// Requires [fusedTopLevelInference] to be `true`.
+  static const bool fullTopLevelInference = true;
+
   final Instrumentation instrumentation;
 
   final bool strongMode;
@@ -100,18 +154,54 @@
 
   TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
 
-  /// Clears the initializer of [field].
-  void clearFieldInitializer(KernelField field);
-
   /// Computes type inference dependencies for the given [field].
   List<FieldNode> computeFieldDependencies(FieldNode fieldNode) {
-    // TODO(paulberry): add logic to infer field types by inheritance.
-    if (fieldHasInitializer(fieldNode._field)) {
-      var collector = new KernelDependencyCollector();
-      collector.collectDependencies(fieldNode._field.initializer);
-      fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident;
-      return collector.dependencies;
+    // If the field's type is going to be determined by inheritance, then its
+    // dependencies are determined by inheritance too.
+    if (fieldNode.overrides.isNotEmpty) {
+      var dependencies = <FieldNode>[];
+      for (var override in fieldNode.overrides) {
+        // TODO(paulberry): support dependencies on getters/setters too.
+        var dep = KernelMember.getFieldNode(override);
+        if (dep != null) dependencies.add(dep);
+      }
+      fieldNode.isImmediatelyEvident = true;
+      return dependencies;
+    }
+
+    // Otherwise its dependencies are based on the initializer expression.
+    var member = fieldNode.member;
+    if (member is KernelField) {
+      if (expandedTopLevelInference) {
+        // In expanded top level inference, we determine the dependencies by
+        // doing a "dry run" of top level inference and recording which static
+        // fields were accessed.
+        var typeInferrer = getFieldTypeInferrer(member);
+        if (typeInferrer == null) {
+          // This can happen when there are errors in the field declaration.
+          return const [];
+        } else {
+          typeInferrer.startDryRun();
+          typeInferrer.listener.dryRunEnter(member.initializer);
+          typeInferrer.inferFieldTopLevel(member, null, true);
+          typeInferrer.listener.dryRunExit(member.initializer);
+          fieldNode.isImmediatelyEvident = true;
+          return typeInferrer.finishDryRun();
+        }
+      } else {
+        // In non-expanded top level inference, we determine the dependencies by
+        // calling `collectDependencies`; as a side effect this flags any
+        // expressions that are not "immediately evident".
+        // TODO(paulberry): get rid of this mode once we are sure we no longer
+        // need it.
+        var collector = new KernelDependencyCollector();
+        collector.collectDependencies(member.initializer);
+        fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident;
+        return collector.dependencies;
+      }
     } else {
+      // Member is a getter/setter that doesn't override anything, so we can't
+      // infer a type for it; therefore it has no dependencies.
       return const [];
     }
   }
@@ -119,78 +209,111 @@
   /// Creates a [FieldNode] to track dependencies of the given [field].
   FieldNode createFieldNode(KernelField field);
 
-  /// Queries whether the given [field] has an initializer.
-  bool fieldHasInitializer(KernelField field);
-
   @override
   void finishTopLevel() {
     for (var fieldNode in fieldNodes) {
-      if (fieldNode.isEvaluated) continue;
-      new _FieldWalker().walk(fieldNode);
+      if (fusedTopLevelInference) {
+        assert(expandedTopLevelInference);
+        inferFieldFused(fieldNode, null);
+      } else {
+        if (fieldNode.isEvaluated) continue;
+        new _FieldWalker().walk(fieldNode);
+      }
     }
     for (var formal in initializingFormals) {
       formal.type = _inferInitializingFormalType(formal);
     }
   }
 
-  /// Gets the declared type of the given [field], or `null` if the type is
-  /// implicit.
-  DartType getFieldDeclaredType(KernelField field);
-
-  /// Gets the character offset of the declaration of [field] within its
-  /// compilation unit.
-  int getFieldOffset(KernelField field);
-
-  /// Retrieve the [TypeInferrer] for the given [field], which was created by
+  /// Retrieve the [TypeInferrer] for the given [member], which was created by
   /// a previous call to [createTopLevelTypeInferrer].
-  TypeInferrerImpl getFieldTypeInferrer(KernelField field);
+  TypeInferrerImpl getFieldTypeInferrer(KernelMember member);
 
   /// Performs type inference on the given [field].
   void inferField(FieldNode fieldNode) {
-    var field = fieldNode._field;
-    if (fieldHasInitializer(field)) {
-      var typeInferrer = getFieldTypeInferrer(field);
-      var type = getFieldDeclaredType(field);
-      if (type == null && strongMode) {
-        typeInferrer.isImmediatelyEvident = true;
-        var inferredType = fieldNode.isImmediatelyEvident
-            ? typeInferrer.inferDeclarationType(
-                typeInferrer.inferFieldTopLevel(field, type, true))
-            : const DynamicType();
-        if (!typeInferrer.isImmediatelyEvident) {
+    assert(fieldNode.state == FieldState.NotInferredYet);
+    fieldNode.state = FieldState.Inferring;
+    var member = fieldNode.member;
+    if (strongMode) {
+      var inferredType = tryInferFieldByInheritance(fieldNode);
+      var typeInferrer = getFieldTypeInferrer(member);
+      if (inferredType == null) {
+        if (member is KernelField) {
+          typeInferrer.isImmediatelyEvident = true;
+          inferredType = fieldNode.isImmediatelyEvident
+              ? typeInferrer.inferDeclarationType(
+                  typeInferrer.inferFieldTopLevel(member, null, true))
+              : const DynamicType();
+          if (!typeInferrer.isImmediatelyEvident) {
+            inferredType = const DynamicType();
+          }
+        } else {
           inferredType = const DynamicType();
         }
-        instrumentation?.record(
-            Uri.parse(typeInferrer.uri),
-            getFieldOffset(field),
-            'topType',
-            new InstrumentationValueForType(inferredType));
-        setFieldInferredType(field, inferredType);
       }
-      // TODO(paulberry): if type != null, then check that the type of the
-      // initializer is assignable to it.
-      // TODO(paulberry): the following is a hack so that outlines don't contain
-      // initializers.  But it means that we rebuild the initializers when doing
-      // a full compile.  There should be a better way.
-      clearFieldInitializer(field);
+      if (fieldNode.state == FieldState.Inferred) {
+        // A circularity must have been detected; at the time it was detected,
+        // inference for this node was completed.
+        return;
+      }
+      member.setInferredType(this, typeInferrer.uri, inferredType);
+    }
+    fieldNode.state = FieldState.Inferred;
+    // TODO(paulberry): if type != null, then check that the type of the
+    // initializer is assignable to it.
+    // TODO(paulberry): the following is a hack so that outlines don't contain
+    // initializers.  But it means that we rebuild the initializers when doing
+    // a full compile.  There should be a better way.
+    if (member is KernelField) {
+      member.initializer = null;
     }
   }
 
   /// Makes a note that the given [field] is part of a circularity, so its type
   /// can't be inferred.
-  void inferFieldCircular(KernelField field) {
+  void inferFieldCircular(FieldNode fieldNode) {
+    var member = fieldNode.member;
     // TODO(paulberry): report the appropriate error.
-    if (getFieldDeclaredType(field) == null) {
-      var uri = getFieldTypeInferrer(field).uri;
-      var inferredType = const DynamicType();
-      instrumentation?.record(Uri.parse(uri), getFieldOffset(field), 'topType',
-          new InstrumentationValueForType(inferredType));
-      setFieldInferredType(field, inferredType);
+    var uri = getFieldTypeInferrer(member).uri;
+    fieldNode.state = FieldState.Inferred;
+    member.setInferredType(this, uri, const DynamicType());
+    // TODO(paulberry): the following is a hack so that outlines don't contain
+    // initializers.  But it means that we rebuild the initializers when doing
+    // a full compile.  There should be a better way.
+    if (member is KernelField) {
+      member.initializer = null;
     }
   }
 
-  /// Determines if top level type inference has been completed for [field].
-  bool isFieldInferred(KernelField field);
+  /// Performs fused type inference on the given [field].
+  void inferFieldFused(FieldNode fieldNode, FieldNode dependant) {
+    switch (fieldNode.state) {
+      case FieldState.Inferred:
+        // Already inferred.  Nothing to do.
+        break;
+      case FieldState.Inferring:
+        // A field depends on itself (possibly by way of intermediate fields).
+        // Mark all fields involved as circular and infer a type of `dynamic`
+        // for them.
+        var node = fieldNode;
+        while (node != null) {
+          var nextNode = node.currentDependency;
+          inferFieldCircular(node);
+          node.currentDependency = null;
+          node = nextNode;
+        }
+        break;
+      case FieldState.NotInferredYet:
+        // Mark the "dependant" field (if any) as depending on this one, and
+        // invoke field inference for this node.
+        dependant?.currentDependency = fieldNode;
+        // All fields are "immediately evident" when doing fused inference.
+        fieldNode.isImmediatelyEvident = true;
+        inferField(fieldNode);
+        dependant?.currentDependency = null;
+        break;
+    }
+  }
 
   @override
   void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
@@ -201,17 +324,62 @@
   }
 
   @override
-  void recordField(KernelField field) {
-    fieldNodes.add(createFieldNode(field));
-  }
-
-  @override
   void recordInitializingFormal(KernelVariableDeclaration formal) {
     initializingFormals.add(formal);
   }
 
-  /// Stores [inferredType] as the inferred type of [field].
-  void setFieldInferredType(KernelField field, DartType inferredType);
+  @override
+  void recordMember(KernelMember member) {
+    fieldNodes.add(createFieldNode(member));
+  }
+
+  DartType tryInferFieldByInheritance(FieldNode fieldNode) {
+    DartType inferredType;
+    for (var override in fieldNode.overrides) {
+      var nextInferredType = _computeOverriddenFieldType(override, fieldNode);
+      if (inferredType == null) {
+        inferredType = nextInferredType;
+      } else if (inferredType != nextInferredType) {
+        // Overrides don't have matching types.
+        // TODO(paulberry): report an error
+        return const DynamicType();
+      }
+    }
+    return inferredType;
+  }
+
+  DartType _computeOverriddenFieldType(Member override, FieldNode fieldNode) {
+    if (fusedTopLevelInference) {
+      FieldNode dependency = KernelMember.getFieldNode(override);
+      if (dependency != null) {
+        inferFieldFused(dependency, fieldNode);
+      }
+    }
+    DartType overriddenType;
+    if (override is Field) {
+      overriddenType = override.type;
+    } else if (override is Procedure) {
+      // TODO(paulberry): handle the case where override needs its type
+      // inferred first.
+      if (override.isGetter) {
+        overriddenType = override.getterType;
+      } else {
+        overriddenType = override.setterType;
+      }
+    } else {
+      throw internalError(
+          'Unexpected overridden member type: ${override.runtimeType}');
+    }
+    var superclass = override.enclosingClass;
+    if (superclass.typeParameters.isEmpty) return overriddenType;
+    var thisClass = fieldNode.member.enclosingClass;
+    var superclassInstantiation = classHierarchy
+        .getClassAsInstanceOf(thisClass, superclass)
+        .asInterfaceType;
+    return Substitution
+        .fromInterfaceType(superclassInstantiation)
+        .substituteType(overriddenType);
+  }
 
   DartType _inferInitializingFormalType(KernelVariableDeclaration formal) {
     assert(KernelVariableDeclaration.isImplicitlyTyped(formal));
@@ -240,7 +408,7 @@
   void evaluateScc(List<FieldNode> scc) {
     // Mark every field as part of a circularity.
     for (var f in scc) {
-      f._typeInferenceEngine.inferFieldCircular(f._field);
+      f._typeInferenceEngine.inferFieldCircular(f);
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
index 190652e..4341ba1 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.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.md file.
 
+import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:kernel/ast.dart';
 
 /// Base class for [TypeInferenceListener] that defines the API for debugging.
@@ -9,6 +10,8 @@
 /// By default no debug info is printed.  To enable debug printing, mix in
 /// [TypeInferenceDebugging].
 class TypeInferenceBase {
+  void debugDependency(FieldNode fieldNode) {}
+
   bool debugExpressionEnter(
       String expressionType, Expression expression, DartType typeContext) {
     return false;
@@ -29,6 +32,10 @@
 /// Mixin which can be applied to [TypeInferenceListener] to cause debug info to
 /// be printed.
 class TypeInferenceDebugging implements TypeInferenceBase {
+  void debugDependency(FieldNode fieldNode) {
+    print('Dependency $fieldNode');
+  }
+
   bool debugExpressionEnter(
       String expressionType, Expression expression, DartType typeContext) {
     print('Enter $expressionType($expression) (context=$typeContext)');
@@ -124,6 +131,12 @@
   void doubleLiteralExit(DoubleLiteral expression, DartType inferredType) =>
       debugExpressionExit("doubleLiteral", expression, inferredType);
 
+  void dryRunEnter(Expression expression) =>
+      debugExpressionEnter("dryRun", expression, null);
+
+  void dryRunExit(Expression expression) =>
+      debugExpressionExit("dryRun", expression, null);
+
   void expressionStatementEnter(ExpressionStatement statement) =>
       debugStatementEnter('expressionStatement', statement);
 
@@ -150,6 +163,12 @@
           FunctionExpression expression, DartType inferredType) =>
       debugExpressionExit("functionExpression", expression, inferredType);
 
+  bool ifNullEnter(Expression expression, DartType typeContext) =>
+      debugExpressionEnter('ifNull', expression, typeContext);
+
+  void ifNullExit(Expression expression, DartType inferredType) =>
+      debugExpressionExit('ifNull', expression, inferredType);
+
   void ifStatementEnter(IfStatement statement) =>
       debugStatementEnter('ifStatement', statement);
 
@@ -218,10 +237,10 @@
   void propertyAssignExit(Expression expression, DartType inferredType) =>
       debugExpressionExit("propertyAssign", expression, inferredType);
 
-  bool propertyGetEnter(PropertyGet expression, DartType typeContext) =>
+  bool propertyGetEnter(Expression expression, DartType typeContext) =>
       debugExpressionEnter("propertyGet", expression, typeContext);
 
-  void propertyGetExit(PropertyGet expression, DartType inferredType) =>
+  void propertyGetExit(Expression expression, DartType inferredType) =>
       debugExpressionExit("propertyGet", expression, inferredType);
 
   bool propertySetEnter(PropertySet expression, DartType typeContext) =>
@@ -230,6 +249,8 @@
   void propertySetExit(PropertySet expression, DartType inferredType) =>
       debugExpressionExit("propertySet", expression, inferredType);
 
+  void recordDependency(FieldNode fieldNode) => debugDependency(fieldNode);
+
   void redirectingInitializerEnter(RedirectingInitializer initializer) =>
       debugInitializerEnter("redirectingInitializer", initializer);
 
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 f51ba65..11e8bb3 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
@@ -199,6 +199,8 @@
   static final FunctionType _functionReturningDynamic =
       new FunctionType(const [], const DynamicType());
 
+  final TypeInferenceEngineImpl engine;
+
   @override
   final String uri;
 
@@ -221,6 +223,11 @@
 
   final InterfaceType thisType;
 
+  /// The [FieldNode] whose initializer will be type inferred using this
+  /// [TypeInferrerImpl], or `null` if this [TypeInferrerImpl] will be used to
+  /// infer types outside the scope of a field initializer.
+  final FieldNode fieldNode;
+
   /// Context information for the current closure, or `null` if we are not
   /// inside a closure.
   ClosureContext closureContext;
@@ -231,8 +238,10 @@
   /// Not used when performing local inference.
   bool isImmediatelyEvident = true;
 
-  TypeInferrerImpl(TypeInferenceEngineImpl engine, this.uri, this.listener,
-      bool topLevel, this.thisType)
+  List<FieldNode> _dryRunDependencies;
+
+  TypeInferrerImpl(this.engine, this.uri, this.listener, bool topLevel,
+      this.thisType, this.fieldNode)
       : coreTypes = engine.coreTypes,
         strongMode = engine.strongMode,
         classHierarchy = engine.classHierarchy,
@@ -240,6 +249,10 @@
         typeSchemaEnvironment = engine.typeSchemaEnvironment,
         isTopLevel = topLevel;
 
+  /// Indicates whether we are currently doing a "dry run" in order to collect
+  /// type inference dependencies.
+  bool get isDryRun => _dryRunDependencies != null;
+
   /// Gets the type promoter that should be used to promote types during
   /// inference.
   TypePromoter get typePromoter;
@@ -336,6 +349,14 @@
     }
   }
 
+  /// Ends a dry run started by [startDryRun] and returns the collected
+  /// dependencies.
+  List<FieldNode> finishDryRun() {
+    var dryRunDependencies = _dryRunDependencies;
+    _dryRunDependencies = null;
+    return dryRunDependencies;
+  }
+
   FunctionType getCalleeFunctionType(Member interfaceMember,
       DartType receiverType, Name methodName, bool followCall) {
     var type = getCalleeType(interfaceMember, receiverType, methodName);
@@ -517,7 +538,8 @@
       FunctionType calleeType, DartType returnType, Arguments arguments,
       {bool isOverloadedArithmeticOperator: false,
       DartType receiverType,
-      bool skipTypeArgumentInference: false}) {
+      bool skipTypeArgumentInference: false,
+      bool forceArgumentInference: false}) {
     var calleeTypeParameters = calleeType.typeParameters;
     List<DartType> explicitTypeArguments = getExplicitTypeArguments(arguments);
     bool inferenceNeeded = !skipTypeArgumentInference &&
@@ -558,8 +580,12 @@
         DartType inferredFormalType = substitution != null
             ? substitution.substituteType(formalType)
             : formalType;
-        var expressionType = inferExpression(expression, inferredFormalType,
-            inferenceNeeded || isOverloadedArithmeticOperator);
+        var expressionType = inferExpression(
+            expression,
+            inferredFormalType,
+            inferenceNeeded ||
+                isOverloadedArithmeticOperator ||
+                forceArgumentInference);
         if (inferenceNeeded) {
           formalTypes.add(formalType);
           actualTypes.add(expressionType);
@@ -601,6 +627,46 @@
     inferExpression(initializer, declaredType, false);
   }
 
+  /// Performs the core type inference algorithm for property gets (this handles
+  /// both null-aware and non-null-aware property gets).
+  DartType inferPropertyGet(
+      Expression expression,
+      Expression receiver,
+      int fileOffset,
+      PropertyGet desugaredGet,
+      DartType typeContext,
+      bool typeNeeded) {
+    typeNeeded =
+        listener.propertyGetEnter(expression, typeContext) || typeNeeded;
+    // First infer the receiver so we can look up the getter that was invoked.
+    var receiverType = inferExpression(receiver, null, true);
+    Member interfaceMember =
+        findInterfaceMember(receiverType, desugaredGet.name, fileOffset);
+    if (isTopLevel &&
+        ((interfaceMember is Procedure &&
+                interfaceMember.kind == ProcedureKind.Getter) ||
+            interfaceMember is Field)) {
+      if (TypeInferenceEngineImpl.fullTopLevelInference) {
+        if (interfaceMember is KernelField) {
+          var fieldNode = KernelMember.getFieldNode(interfaceMember);
+          if (fieldNode != null) {
+            engine.inferFieldFused(fieldNode, this.fieldNode);
+          }
+        }
+      } else {
+        // References to fields and getters can't be relied upon for top level
+        // inference.
+        recordNotImmediatelyEvident(fileOffset);
+      }
+    }
+    desugaredGet.interfaceTarget = interfaceMember;
+    var inferredType =
+        getCalleeType(interfaceMember, receiverType, desugaredGet.name);
+    // TODO(paulberry): Infer tear-off type arguments if appropriate.
+    listener.propertyGetExit(expression, inferredType);
+    return typeNeeded ? inferredType : null;
+  }
+
   /// Modifies a type as appropriate when inferring a closure return type.
   DartType inferReturnType(DartType returnType, bool isExpressionFunction) {
     if (returnType == null) {
@@ -624,12 +690,28 @@
   /// the statement type and calls the appropriate specialized "infer" method.
   void inferStatement(Statement statement);
 
+  /// Records that the field represented by [fieldNode] is a dependency of the
+  /// static field for which we are currently doing a dry run of type inference.
+  ///
+  /// May only be called if a dry run is in progress.
+  void recordDryRunDependency(FieldNode fieldNode) {
+    listener.recordDependency(fieldNode);
+    _dryRunDependencies.add(fieldNode);
+  }
+
   void recordNotImmediatelyEvident(int fileOffset) {
     assert(isTopLevel);
     isImmediatelyEvident = false;
     // TODO(paulberry): report an error.
   }
 
+  /// Begins a dry run of type inference, in which the goal is to collect the
+  /// dependencies of a given field.
+  void startDryRun() {
+    assert(_dryRunDependencies == null);
+    _dryRunDependencies = <FieldNode>[];
+  }
+
   DartType wrapFutureOrType(DartType type) {
     if (type is InterfaceType &&
         identical(type.classNode, coreTypes.futureOrClass)) {
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 4c3d53a..4336d91 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
@@ -402,14 +402,22 @@
   /// True if [member] is a binary operator that returns an `int` if both
   /// operands are `int`, and otherwise returns `double`.
   ///
+  /// Note that this behavior depends on the receiver type, so we can only make
+  /// this determination if we know the type of the receiver.
+  ///
   /// This is a case of type-based overloading, which in Dart is only supported
   /// by giving special treatment to certain arithmetic operators.
-  bool isOverloadedArithmeticOperator(Procedure member) {
+  bool isOverloadedArithmeticOperatorAndType(
+      Procedure member, DartType receiverType) {
     // 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 (member.name.name == 'remainder') return false;
-    return super.isOverloadedArithmeticOperator(member);
+    if (!(receiverType is InterfaceType &&
+        identical(receiverType.classNode, coreTypes.intClass))) {
+      return false;
+    }
+    return isOverloadedArithmeticOperator(member);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/incremental/file_state.dart b/pkg/front_end/lib/src/incremental/file_state.dart
index c4882b5..2751942 100644
--- a/pkg/front_end/lib/src/incremental/file_state.dart
+++ b/pkg/front_end/lib/src/incremental/file_state.dart
@@ -5,20 +5,15 @@
 import 'dart:async';
 import 'dart:typed_data';
 
+import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:front_end/file_system.dart';
-import 'package:front_end/src/base/api_signature.dart';
 import 'package:front_end/src/base/resolve_relative_uri.dart';
 import 'package:front_end/src/dependency_walker.dart' as graph;
-import 'package:front_end/src/fasta/parser/dart_vm_native.dart';
-import 'package:front_end/src/fasta/parser/listener.dart' show Listener;
-import 'package:front_end/src/fasta/parser/parser.dart' show Parser, optional;
-import 'package:front_end/src/fasta/parser/top_level_parser.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/scanner/token_constants.dart'
-    show STRING_TOKEN;
-import 'package:front_end/src/fasta/source/directive_listener.dart';
 import 'package:front_end/src/fasta/translate_uri.dart';
+import 'package:front_end/src/incremental/byte_store.dart';
+import 'package:front_end/src/incremental/format.dart';
+import 'package:front_end/src/incremental/unlinked_unit.dart';
 import 'package:kernel/target/vm.dart';
 
 /// This function is called for each newly discovered file, and the returned
@@ -54,6 +49,7 @@
 
   Set<FileState> _directReferencedFiles = new Set<FileState>();
   List<FileState> _directReferencedLibraries = <FileState>[];
+  Set<FileState> _transitiveFiles;
 
   /// This flag is set to `true` during the mark phase of garbage collection
   /// and set back to `false` for survived instances.
@@ -111,17 +107,18 @@
   /// Return the set of transitive files - the file itself and all of the
   /// directly or indirectly referenced files.
   Set<FileState> get transitiveFiles {
-    // TODO(scheglov) add caching.
-    var transitiveFiles = new Set<FileState>();
+    if (_transitiveFiles == null) {
+      _transitiveFiles = new Set<FileState>();
 
-    void appendReferenced(FileState file) {
-      if (transitiveFiles.add(file)) {
-        file._directReferencedFiles.forEach(appendReferenced);
+      void appendReferenced(FileState file) {
+        if (_transitiveFiles.add(file)) {
+          file._directReferencedFiles.forEach(appendReferenced);
+        }
       }
-    }
 
-    appendReferenced(this);
-    return transitiveFiles;
+      appendReferenced(this);
+    }
+    return _transitiveFiles;
   }
 
   @override
@@ -145,15 +142,22 @@
     // Compute the content hash.
     _contentHash = md5.convert(_content).bytes;
 
-    // Scan the content.
-    ScannerResult scanResult = _scan();
+    // Prepare bytes of the unlinked unit - existing or new.
+    List<int> unlinkedBytes;
+    {
+      String unlinkedKey = hex.encode(_contentHash) + '.unlinked';
+      unlinkedBytes = _fsState._byteStore.get(unlinkedKey);
+      if (unlinkedBytes == null) {
+        var builder = computeUnlinkedUnit(_fsState._salt, _content);
+        unlinkedBytes = builder.toBytes();
+        _fsState._byteStore.put(unlinkedKey, unlinkedBytes);
+      }
+    }
 
-    // Compute syntactic properties.
-    _computeSyntacticProperties(scanResult.tokens);
-
-    // Parse directives.
-    var listener = new _DirectiveListenerWithNative();
-    new TopLevelParser(listener).parseUnit(scanResult.tokens);
+    // Read the unlinked unit.
+    UnlinkedUnit unlinkedUnit = new UnlinkedUnit(unlinkedBytes);
+    _apiSignature = unlinkedUnit.apiSignature;
+    _hasMixinApplication = unlinkedUnit.hasMixinApplication;
 
     // Build the graph.
     _importedLibraries = <FileState>[];
@@ -167,28 +171,29 @@
         _importedLibraries.add(coreFile);
       }
     }
-    for (NamespaceDirective import_ in listener.imports) {
+    for (var import_ in unlinkedUnit.imports) {
       FileState file = await _getFileForRelativeUri(import_.uri);
       if (file != null) {
         _importedLibraries.add(file);
       }
     }
     await _addVmTargetImportsForCore();
-    for (NamespaceDirective export_ in listener.exports) {
+    for (var export_ in unlinkedUnit.exports) {
       FileState file = await _getFileForRelativeUri(export_.uri);
       if (file != null) {
         _exportedLibraries.add(file);
         _exports.add(new NamespaceExport(file, export_.combinators));
       }
     }
-    for (String uri in listener.parts) {
-      FileState file = await _getFileForRelativeUri(uri);
+    for (var part_ in unlinkedUnit.parts) {
+      FileState file = await _getFileForRelativeUri(part_);
       if (file != null) {
         _partFiles.add(file);
       }
     }
 
     // Compute referenced files.
+    var oldDirectReferencedFiles = _directReferencedFiles;
     _directReferencedFiles = new Set<FileState>()
       ..addAll(_importedLibraries)
       ..addAll(_exportedLibraries)
@@ -197,6 +202,19 @@
           ..addAll(_importedLibraries)
           ..addAll(_exportedLibraries))
         .toList();
+
+    // If the set of directly referenced files of this file is changed,
+    // then the transitive sets of files that include this file are also
+    // changed. Reset these transitive sets.
+    if (_directReferencedFiles.length != oldDirectReferencedFiles.length ||
+        !_directReferencedFiles.containsAll(oldDirectReferencedFiles)) {
+      for (var file in _fsState._uriToFile.values) {
+        if (file._transitiveFiles != null &&
+            file._transitiveFiles.contains(this)) {
+          file._transitiveFiles = null;
+        }
+      }
+    }
   }
 
   @override
@@ -220,52 +238,6 @@
     }
   }
 
-  /// Compute syntactic properties of the file: [_apiSignature] and [_hasMixinApplication].
-  ///
-  /// The signature is based on non-comment tokens of the file outside
-  /// of function bodies.
-  void _computeSyntacticProperties(Token token) {
-    var parser = new _BodySkippingParser();
-    parser.parseUnit(token);
-
-    _hasMixinApplication = parser.hasMixin;
-
-    ApiSignature apiSignature = new ApiSignature();
-    apiSignature.addBytes(_fsState._salt);
-
-    // Iterate over tokens and skip bodies.
-    Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator;
-    bodyIterator.moveNext();
-    for (; token.kind != EOF_TOKEN; token = token.next) {
-      // Move to the body range that ends after the token.
-      while (bodyIterator.current != null &&
-          bodyIterator.current.last < token.charOffset) {
-        bodyIterator.moveNext();
-      }
-      // If the current body range starts before or at the token, skip it.
-      if (bodyIterator.current != null &&
-          bodyIterator.current.first <= token.charOffset) {
-        continue;
-      }
-      // The token is outside of a function body, add it.
-      apiSignature.addString(token.lexeme);
-    }
-
-    // Store the API signature.
-    _apiSignature = apiSignature.toByteList();
-  }
-
-  /// Exclude all `native 'xyz';` token sequences.
-  void _excludeNativeClauses(Token token) {
-    for (; token.kind != EOF_TOKEN; token = token.next) {
-      if (optional('native', token) &&
-          token.next.kind == STRING_TOKEN &&
-          optional(';', token.next.next)) {
-        token.previous.next = token.next.next;
-      }
-    }
-  }
-
   /// Return the [FileState] for the given [relativeUri] or `null` if the URI
   /// cannot be parsed, cannot correspond any file, etc.
   Future<FileState> _getFileForRelativeUri(String relativeUri) async {
@@ -284,19 +256,11 @@
 
     return await _fsState.getFile(absoluteUri);
   }
-
-  /// Scan the content of the file.
-  ScannerResult _scan() {
-    var zeroTerminatedBytes = new Uint8List(_content.length + 1);
-    zeroTerminatedBytes.setRange(0, _content.length, _content);
-    ScannerResult result = scan(zeroTerminatedBytes);
-    _excludeNativeClauses(result.tokens);
-    return result;
-  }
 }
 
 /// Information about known file system state.
 class FileSystemState {
+  final ByteStore _byteStore;
   final FileSystem fileSystem;
   final TranslateUri uriTranslator;
   final List<int> _salt;
@@ -312,8 +276,8 @@
   /// contain `file:*` URIs as keys.
   final Map<Uri, FileState> _fileUriToFile = {};
 
-  FileSystemState(
-      this.fileSystem, this.uriTranslator, this._salt, this._newFileFn);
+  FileSystemState(this._byteStore, this.fileSystem, this.uriTranslator,
+      this._salt, this._newFileFn);
 
   /// Return the [FileSystem] that is backed by this [FileSystemState].  The
   /// files in this [FileSystem] always have the same content as the
@@ -419,13 +383,13 @@
 /// Information about a single `export` directive.
 class NamespaceExport {
   final FileState library;
-  final List<NamespaceCombinator> combinators;
+  final List<UnlinkedCombinator> combinators;
 
   NamespaceExport(this.library, this.combinators);
 
   /// Return `true` if the [name] satisfies the sequence of the [combinators].
   bool isExposed(String name) {
-    for (NamespaceCombinator combinator in combinators) {
+    for (var combinator in combinators) {
       if (combinator.isShow) {
         if (!combinator.names.contains(name)) {
           return false;
@@ -440,49 +404,6 @@
   }
 }
 
-/// The char range of a function body.
-class _BodyRange {
-  /// The char offset of the first token in the range.
-  final int first;
-
-  /// The char offset of the last token in the range.
-  final int last;
-
-  _BodyRange(this.first, this.last);
-
-  @override
-  String toString() => '[$first, $last]';
-}
-
-/// The [Parser] that skips function bodies and remembers their token ranges.
-class _BodySkippingParser extends Parser {
-  bool hasMixin = false;
-  final List<_BodyRange> bodyRanges = [];
-
-  _BodySkippingParser() : super(new Listener());
-
-  @override
-  Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
-    if (identical('{', token.lexeme)) {
-      Token close = skipBlock(token);
-      bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset));
-      return close;
-    }
-    return super.parseFunctionBody(token, isExpression, allowAbstract);
-  }
-
-  Token parseMixinApplication(Token token) {
-    hasMixin = true;
-    return super.parseMixinApplication(token);
-  }
-}
-
-/// [DirectiveListener] that skips native clauses.
-class _DirectiveListenerWithNative extends DirectiveListener {
-  @override
-  Token handleNativeClause(Token token) => skipNativeClause(token);
-}
-
 /// [FileSystemState] based implementation of [FileSystem].
 /// It provides a consistent view on the known file system state.
 class _FileSystemView implements FileSystem {
diff --git a/pkg/front_end/lib/src/incremental/unlinked_unit.dart b/pkg/front_end/lib/src/incremental/unlinked_unit.dart
new file mode 100644
index 0000000..f657b5d
--- /dev/null
+++ b/pkg/front_end/lib/src/incremental/unlinked_unit.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:typed_data';
+
+import 'package:front_end/src/base/api_signature.dart';
+import 'package:front_end/src/fasta/parser/listener.dart' show Listener;
+import 'package:front_end/src/fasta/parser/parser.dart' show Parser, optional;
+import 'package:front_end/src/fasta/parser/top_level_parser.dart';
+import 'package:front_end/src/fasta/scanner.dart';
+import 'package:front_end/src/fasta/scanner/token_constants.dart'
+    show STRING_TOKEN;
+import 'package:front_end/src/fasta/source/directive_listener.dart';
+import 'package:front_end/src/incremental/format.dart';
+
+/// Compute the [UnlinkedUnitBuilder] for the [content].
+UnlinkedUnitBuilder computeUnlinkedUnit(List<int> salt, List<int> content) {
+  // Scan the content.
+  ScannerResult scanResult = _scan(content);
+  Token token = scanResult.tokens;
+
+  // Parse directives.
+  var listener = new DirectiveListener();
+  new TopLevelParser(listener).parseUnit(token);
+
+  // Parse to record function bodies.
+  var parser = new _BodySkippingParser();
+  parser.parseUnit(token);
+
+  ApiSignature apiSignature = new ApiSignature();
+  apiSignature.addBytes(salt);
+
+  // Iterate over tokens and skip bodies.
+  Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator;
+  bodyIterator.moveNext();
+  for (; token.kind != EOF_TOKEN; token = token.next) {
+    // Move to the body range that ends after the token.
+    while (bodyIterator.current != null &&
+        bodyIterator.current.last < token.charOffset) {
+      bodyIterator.moveNext();
+    }
+    // If the current body range starts before or at the token, skip it.
+    if (bodyIterator.current != null &&
+        bodyIterator.current.first <= token.charOffset) {
+      continue;
+    }
+    // The token is outside of a function body, add it.
+    apiSignature.addString(token.lexeme);
+  }
+
+  return new UnlinkedUnitBuilder(
+      apiSignature: apiSignature.toByteList(),
+      imports: listener.imports.map(_toUnlinkedNamespaceDirective).toList(),
+      exports: listener.exports.map(_toUnlinkedNamespaceDirective).toList(),
+      parts: listener.parts.toList(),
+      hasMixinApplication: parser.hasMixin);
+}
+
+/// Exclude all `native 'xyz';` token sequences.
+void _excludeNativeClauses(Token token) {
+  for (; token.kind != EOF_TOKEN; token = token.next) {
+    if (optional('native', token) &&
+        token.next.kind == STRING_TOKEN &&
+        optional(';', token.next.next)) {
+      token.previous.next = token.next.next;
+    }
+  }
+}
+
+/// Scan the content of the file.
+ScannerResult _scan(List<int> content) {
+  var zeroTerminatedBytes = new Uint8List(content.length + 1);
+  zeroTerminatedBytes.setRange(0, content.length, content);
+  ScannerResult result = scan(zeroTerminatedBytes);
+  _excludeNativeClauses(result.tokens);
+  return result;
+}
+
+/// Convert [NamespaceCombinator] into [UnlinkedCombinatorBuilder].
+UnlinkedCombinatorBuilder _toUnlinkedCombinator(NamespaceCombinator c) =>
+    new UnlinkedCombinatorBuilder(isShow: c.isShow, names: c.names.toList());
+
+/// Convert [NamespaceDirective] into [UnlinkedNamespaceDirectiveBuilder].
+UnlinkedNamespaceDirectiveBuilder _toUnlinkedNamespaceDirective(
+        NamespaceDirective directive) =>
+    new UnlinkedNamespaceDirectiveBuilder(
+        uri: directive.uri,
+        combinators: directive.combinators.map(_toUnlinkedCombinator).toList());
+
+/// The char range of a function body.
+class _BodyRange {
+  /// The char offset of the first token in the range.
+  final int first;
+
+  /// The char offset of the last token in the range.
+  final int last;
+
+  _BodyRange(this.first, this.last);
+
+  @override
+  String toString() => '[$first, $last]';
+}
+
+/// The [Parser] that skips function bodies and remembers their token ranges.
+class _BodySkippingParser extends Parser {
+  bool hasMixin = false;
+  final List<_BodyRange> bodyRanges = [];
+
+  _BodySkippingParser() : super(new Listener());
+
+  @override
+  Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
+    if (identical('{', token.lexeme)) {
+      Token close = skipBlock(token);
+      bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset));
+      return close;
+    }
+    return super.parseFunctionBody(token, isExpression, allowAbstract);
+  }
+
+  Token parseMixinApplication(Token token) {
+    hasMixin = true;
+    return super.parseMixinApplication(token);
+  }
+}
diff --git a/pkg/front_end/lib/src/incremental_kernel_generator_impl.dart b/pkg/front_end/lib/src/incremental_kernel_generator_impl.dart
index 164b589..b78ac35 100644
--- a/pkg/front_end/lib/src/incremental_kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/incremental_kernel_generator_impl.dart
@@ -95,8 +95,8 @@
       return new Future.value();
     }
 
-    _fsState = new FileSystemState(
-        _options.fileSystem, _uriTranslator, _salt, onFileAdded);
+    _fsState = new FileSystemState(_options.byteStore, _options.fileSystem,
+        _uriTranslator, _salt, onFileAdded);
   }
 
   /// Return the object that provides additional information for tests.
@@ -329,7 +329,8 @@
     for (var file in transitiveFiles) {
       signatureBuilder.addString(file.uri.toString());
       // TODO(scheglov): Stop using content hashes here, when Kernel stops
-      // copying methods of mixed-in classes,
+      // copying methods of mixed-in classes.
+      // https://github.com/dart-lang/sdk/issues/29881
       if (hasMixinApplication) {
         signatureBuilder.addBytes(file.contentHash);
       } else {
diff --git a/pkg/front_end/lib/src/libraries_reader.dart b/pkg/front_end/lib/src/libraries_reader.dart
deleted file mode 100644
index ded5d9f..0000000
--- a/pkg/front_end/lib/src/libraries_reader.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:front_end/src/base/library_info.dart';
-
-/// Decodes the contents of the SDK's "libraries.dart" file.
-///
-/// Caller should pass in the unlinked summary of the libraries.dart file.  This
-/// function will materialize the "libraries" constant based on information in
-/// the summary.
-///
-/// Note that this code is not intended to be fully general; it makes some
-/// assumptions about the structure of the "libraries.dart" file (such as what
-/// declarations are expected to be present in it, and the types of those
-/// declarations).
-Map<String, LibraryInfo> readLibraries(UnlinkedUnit librariesUnit) {
-  var constContext = new _ConstContext(librariesUnit.references);
-  for (var variable in librariesUnit.variables) {
-    if (!variable.isConst) continue;
-    constContext.topLevelConstants[variable.name] =
-        new _ConstVariable(variable.initializer.bodyExpr, constContext);
-  }
-  for (var cls in librariesUnit.classes) {
-    if (cls.name == 'Maturity') {
-      for (var field in cls.fields) {
-        if (!field.isConst) continue;
-        constContext.maturityConstants[field.name] =
-            new _ConstVariable(field.initializer.bodyExpr, constContext);
-      }
-    }
-  }
-  return constContext.topLevelConstants['libraries'].value;
-}
-
-/// Function type used to invoke a constructor based on dynamic information.
-///
-/// Caller supplies two callbacks ([positional] and [named]) which can be used
-/// to query the arguments passed to the constructor.  These callbacks will
-/// return the requested argument if it was provided; otherwise they will return
-/// the supplied default value.
-typedef dynamic _Constructor(dynamic positional(int i, [dynamic defaultValue]),
-    dynamic named(String name, [dynamic defaultValue]));
-
-/// Contextual information used to evaluate constants in the "libraries.dart"
-/// file.
-class _ConstContext {
-  /// Top level constants in the "libraries.dart" file.
-  final topLevelConstants = <String, _ConstVariable>{};
-
-  /// Static constants in "libraries.dart"'s "Maturity" class.
-  final maturityConstants = <String, _ConstVariable>{};
-
-  /// References from the unlinked summary of the "libraries.dart" file.
-  final List<UnlinkedReference> references;
-
-  _ConstContext(this.references);
-}
-
-/// Information necessary to evaluate a single constant from the
-/// "libraries.dart" file.
-class _ConstVariable {
-  /// The constant expression from the unlinked summary.
-  final UnlinkedExpr expr;
-
-  /// Contextual information necessary to evaluate the constant.
-  final _ConstContext context;
-
-  /// The evaluated value, or `null` if it hasn't been evaluated yet.
-  dynamic _value;
-
-  _ConstVariable(this.expr, this.context);
-
-  /// Evaluate the constant (if necessary) and return it.
-  dynamic get value => _value ??= _materialize();
-
-  /// Find the constructor referred to by [entityRef] and return a function
-  /// which may be used to invoke it.
-  _Constructor _findConstructor(EntityRef entityRef) {
-    // This method is not fully general; we only support the constructor
-    // invocations that we expect to find in LibraryInfo.
-    assert(entityRef.implicitFunctionTypeIndices.isEmpty);
-    assert(entityRef.paramReference == 0);
-    assert(entityRef.syntheticParams.isEmpty);
-    assert(entityRef.syntheticReturnType == null);
-    assert(entityRef.typeArguments.isEmpty);
-    var reference = context.references[entityRef.reference];
-    assert(reference.prefixReference == 0);
-    switch (reference.name) {
-      case 'LibraryInfo':
-        return (dynamic positional(int i, [dynamic defaultValue]),
-                dynamic named(String name, [dynamic defaultValue])) =>
-            new LibraryInfo(positional(0),
-                categories: named('categories', ''),
-                dart2jsPath: named('dart2jsPath'),
-                dart2jsPatchPath: named('dart2jsPatchPath'),
-                implementation: named('implementation', false),
-                documented: named('documented', true),
-                maturity: named('maturity', Maturity.UNSPECIFIED),
-                platforms: named('platforms', DART2JS_PLATFORM | VM_PLATFORM));
-      case 'Maturity':
-        return (dynamic positional(int i, [dynamic defaultValue]),
-                dynamic named(String name, [dynamic defaultValue])) =>
-            new Maturity(positional(0), positional(1), positional(2));
-      default:
-        throw new UnimplementedError(
-            'Unexpected constructor reference: ${reference.name}');
-    }
-  }
-
-  /// Compute the value referred to by [entityRef].
-  dynamic _findReference(EntityRef entityRef) {
-    // This method is not fully general; we only support the references that we
-    // expect to find in LibraryInfo.
-    assert(entityRef.implicitFunctionTypeIndices.isEmpty);
-    assert(entityRef.paramReference == 0);
-    assert(entityRef.syntheticParams.isEmpty);
-    assert(entityRef.syntheticReturnType == null);
-    assert(entityRef.typeArguments.isEmpty);
-    var reference = context.references[entityRef.reference];
-    if (reference.prefixReference == 0) {
-      return context.topLevelConstants[reference.name].value;
-    } else {
-      assert(reference.prefixReference != 0);
-      var prefixReference = context.references[reference.prefixReference];
-      assert(prefixReference.name == 'Maturity');
-      assert(prefixReference.prefixReference == 0);
-      return context.maturityConstants[reference.name].value;
-    }
-  }
-
-  /// Compute the value of the constant.
-  dynamic _materialize() {
-    var stack = [];
-    var stringIndex = 0;
-    var intIndex = 0;
-    var referenceIndex = 0;
-    List popItems(int count) {
-      var items = stack.sublist(stack.length - count, stack.length);
-      stack.length -= count;
-      return items;
-    }
-
-    for (var operation in expr.operations) {
-      switch (operation) {
-        case UnlinkedExprOperation.pushString:
-          stack.add(expr.strings[stringIndex++]);
-          break;
-        case UnlinkedExprOperation.invokeConstructor:
-          var namedArgumentList = popItems(expr.ints[intIndex++]);
-          var namedArguments = <String, dynamic>{};
-          for (var namedArgument in namedArgumentList) {
-            namedArguments[expr.strings[stringIndex++]] = namedArgument;
-          }
-          var positionalArguments = popItems(expr.ints[intIndex++]);
-          stack.add(_findConstructor(expr.references[referenceIndex++])(
-              (i, [defaultValue]) => i < positionalArguments.length
-                  ? positionalArguments[i]
-                  : defaultValue,
-              (name, [defaultValue]) => namedArguments.containsKey(name)
-                  ? namedArguments[name]
-                  : defaultValue));
-          break;
-        case UnlinkedExprOperation.makeUntypedMap:
-          var map = {};
-          var numKeyValuePairs = expr.ints[intIndex++];
-          var keyValueList = popItems(numKeyValuePairs * 2);
-          for (var i = 0; i < numKeyValuePairs; i++) {
-            map[keyValueList[2 * i]] = keyValueList[2 * i + 1];
-          }
-          stack.add(map);
-          break;
-        case UnlinkedExprOperation.pushReference:
-          stack.add(_findReference(expr.references[referenceIndex++]));
-          break;
-        case UnlinkedExprOperation.pushInt:
-          stack.add(expr.ints[intIndex++]);
-          break;
-        case UnlinkedExprOperation.pushFalse:
-          stack.add(false);
-          break;
-        case UnlinkedExprOperation.pushTrue:
-          stack.add(true);
-          break;
-        case UnlinkedExprOperation.bitOr:
-          var y = stack.removeLast();
-          var x = stack.removeLast();
-          stack.add(x | y);
-          break;
-        default:
-          throw new UnimplementedError(
-              'Unexpected expression in libraries.dart: $operation');
-      }
-    }
-    assert(stringIndex == expr.strings.length);
-    assert(intIndex == expr.ints.length);
-    assert(referenceIndex == expr.references.length);
-    assert(stack.length == 1);
-    if (stack[0] == null) {
-      throw new StateError('Unexpected null constant in libraries.dart');
-    }
-    return stack[0];
-  }
-}
diff --git a/pkg/front_end/lib/src/vm/reload.dart b/pkg/front_end/lib/src/vm/reload.dart
deleted file mode 100644
index 806ef59..0000000
--- a/pkg/front_end/lib/src/vm/reload.dart
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// A helper library to connect to an existing VM and trigger a hot-reload via
-/// its service protocol.
-///
-/// Usage:
-///
-/// ```
-///     var reloader = new VmReloader();
-///     await reloader.reload(uriToEntryScript);
-///     ...
-///     await reloader.disconnect();
-/// ```
-library front_end.src.vm.reload;
-
-import 'dart:async';
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:stream_channel/stream_channel.dart';
-import 'package:web_socket_channel/io.dart';
-
-/// A user API to trigger hot reloads on a running VM via the VM's service
-/// protocol.
-class VmReloader {
-  /// Port used to connect to the vm service protocol, typically 8181.
-  final int port;
-
-  /// An peer point used to send service protocol messages. The service
-  /// protocol uses JSON rpc on top of web-sockets.
-  json_rpc.Peer get rpc => _rpc ??= _createPeer();
-  json_rpc.Peer _rpc;
-
-  /// The main isolate ID of the running VM. Needed to indicate to the VM which
-  /// isolate to reload.
-  FutureOr<String> get mainId async => _mainId ??= await _computeMainId();
-  String _mainId;
-
-  VmReloader([this.port = 8181]);
-
-  /// Establishes the JSON rpc connection.
-  json_rpc.Peer _createPeer() {
-    StreamChannel socket =
-        new IOWebSocketChannel.connect('ws://127.0.0.1:$port/ws');
-    var peer = new json_rpc.Peer(socket);
-    peer.listen().then((_) {
-      if (VERBOSE_DEBUG) print('connection to vm-service closed');
-      return disconnect();
-    }).catchError((e) {
-      if (VERBOSE_DEBUG) print('error connecting to the vm-service');
-      return disconnect();
-    });
-    return peer;
-  }
-
-  /// Retrieves the ID of the main isolate using the service protocol.
-  Future<String> _computeMainId() async {
-    var vm = await rpc.sendRequest('getVM');
-    var isolates = vm['isolates'];
-    for (var isolate in isolates) {
-      if (isolate['name'].contains(r'$main')) {
-        return isolate['id'];
-      }
-    }
-    return isolates.first['id'];
-  }
-
-  /// Send a request to the VM to reload sources from [entryUri].
-  ///
-  /// This will establish a connection with the VM assuming it is running on the
-  /// local machine and listening on [port] for service protocol requests.
-  ///
-  /// The result is the JSON map received from the reload request.
-  Future<Map> reload(Uri entryUri) async {
-    var id = await mainId;
-    var result = await rpc.sendRequest('reloadSources', {
-      'isolateId': id,
-      'rootLibUri': entryUri.path,
-    });
-    return result;
-  }
-
-  /// Close any connections used to communicate with the VM.
-  Future disconnect() async {
-    if (_rpc == null) return null;
-    this._mainId = null;
-    if (!_rpc.isClosed) {
-      var future = _rpc.close();
-      _rpc = null;
-      return future;
-    }
-    return null;
-  }
-}
-
-const VERBOSE_DEBUG = false;
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index c8e2642..815b300 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -6,7 +6,6 @@
 environment:
   sdk: '>=1.12.0 <2.0.0'
 dependencies:
-  analyzer: ^0.30.0
   kernel: 0.3.0-alpha.1
   path: '^1.3.9'
   source_span: '^1.2.3'
@@ -14,3 +13,6 @@
   package_config: '^1.0.0'
   test: ^0.12.0
   test_reflective_loader: ^0.1.0
+  json_rpc_2: ^2.0.4
+  stream_channel: ^1.6.1
+  web_socket_channel: ^1.0.4
diff --git a/pkg/front_end/test/fasta/kompile.status b/pkg/front_end/test/fasta/kompile.status
index d88e72a..3d0782e 100644
--- a/pkg/front_end/test/fasta/kompile.status
+++ b/pkg/front_end/test/fasta/kompile.status
@@ -175,6 +175,7 @@
 inference/generic_methods_iterable_and_future: Crash
 inference/generic_methods_nested_generic_instantiation: Crash
 inference/generic_methods_uses_greatest_lower_bound: Crash
+inference/infer_accessor_from_later_inferred_field: Crash
 inference/infer_assign_to_implicit_this: Crash
 inference/infer_assign_to_implicit_this_upwards: Crash
 inference/infer_assign_to_index: Crash
@@ -209,6 +210,21 @@
 inference/infer_consts_transitively_2_b: Crash
 inference/infer_consts_transitively_b: Crash
 inference/infer_correctly_on_multiple_variables_declared_together: Crash
+inference/infer_field_from_later_inferred_field: Crash
+inference/infer_field_from_later_inferred_getter: Crash
+inference/infer_field_from_later_inferred_setter: Crash
+inference/infer_field_getter_setter_mismatch: Crash
+inference/infer_field_override_getter_overrides_setter: Crash
+inference/infer_field_override_multiple: Crash
+inference/infer_field_override_of_override: Crash
+inference/infer_field_override_setter_overrides_getter: Crash
+inference/infer_field_override_with_substitution: Crash
+inference/infer_field_overrides_getter: Crash
+inference/infer_field_overrides_setter: Crash
+inference/infer_field_static: Crash
+inference/infer_final_field_getter_and_setter: Crash
+inference/infer_final_field_getter_only: Crash
+inference/infer_final_field_setter_only: Crash
 inference/infer_from_complex_expressions_if_outer_most_value_is_precise: Crash
 inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: Crash
 inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: Crash
@@ -224,6 +240,7 @@
 inference/infer_generic_method_type_positional2: Crash
 inference/infer_generic_method_type_positional: Crash
 inference/infer_generic_method_type_required: Crash
+inference/infer_getter_from_later_inferred_getter: Crash
 inference/infer_list_literal_nested_in_map_literal: Crash
 inference/infer_local_function_return_type: Crash
 inference/infer_parameter_type_setter_from_field: Crash
@@ -231,6 +248,8 @@
 inference/infer_prefix_expression: Crash
 inference/infer_prefix_expression_custom: Crash
 inference/infer_return_of_statement_lambda: Crash
+inference/infer_setter_from_later_inferred_setter: Crash
+inference/infer_setter_function_typed: Crash
 inference/infer_statics_transitively2: Crash
 inference/infer_statics_transitively3: Crash
 inference/infer_statics_transitively3_a: Crash
@@ -311,6 +330,8 @@
 inference/method_call_with_type_arguments_instance_method_identifier_sequence: Crash
 inference/method_call_with_type_arguments_static_method: Crash
 inference/method_call_with_type_arguments_top_level_function: Crash
+inference/non_inferrable_getter_setter: Crash
+inference/null_aware_property_get: Crash
 inference/null_literal_should_not_infer_as_bottom: Crash
 inference/parameter_defaults_downwards: Crash
 inference/parameter_defaults_upwards: Crash
@@ -362,6 +383,18 @@
 inference/unsafe_block_closure_inference_method_call_implicit_type_param: Crash
 inference/unsafe_block_closure_inference_method_call_no_type_param: Crash
 inference/void_return_type_subtypes_dynamic: Crash
+inference_new/dependency_only_if_generic_method: Crash
+inference_new/dependency_only_if_overloaded: Crash
+inference_new/field_inference_circularity: Crash
+inference_new/infer_assign_to_index: Crash
+inference_new/infer_assign_to_property: Crash
+inference_new/infer_assign_to_property_custom: Crash
+inference_new/infer_assign_to_ref: Crash
+inference_new/infer_instance_accessor_ref: Crash
+inference_new/infer_instance_field_ref: Crash
+inference_new/infer_instance_field_ref_circular: Crash
+inference_new/property_get_toplevel: Crash
+inference_new/strongly_connected_component: Crash
 
 rasta/abstract_constructor: Fail
 rasta/bad_constructor_redirection: Crash
diff --git a/pkg/front_end/test/fasta/strong.status b/pkg/front_end/test/fasta/strong.status
index 2efb4bf..c699095 100644
--- a/pkg/front_end/test/fasta/strong.status
+++ b/pkg/front_end/test/fasta/strong.status
@@ -59,20 +59,14 @@
 inference/future_then_explicit_future: Fail
 inference/generic_functions_return_typedef: Fail
 inference/generic_methods_infer_js_builtin: Fail
-inference/infer_correctly_on_multiple_variables_declared_together: Fail
-inference/infer_from_complex_expressions_if_outer_most_value_is_precise: Fail
-inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: Fail
-inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: Fail
+inference/infer_final_field_setter_only: Fail
 inference/infer_local_function_return_type: Fail
 inference/infer_types_on_generic_instantiations_in_library_cycle: Fail
 inference/infer_types_on_loop_indices_for_each_loop: Fail
 inference/infer_types_on_loop_indices_for_loop_with_inference: Fail
-inference/inferred_type_cascade: Fail
 inference/lambda_does_not_have_propagated_type_hint: Fail
 inference/list_literals_can_infer_null_top_level: Fail
 inference/map_literals_can_infer_null_top_level: Fail
-inference/null_coalescing_operator: Fail
-inference/null_coalescing_operator_2: Fail
 inference/property_set: Fail
 inference/property_set_bad_setter: Crash
 inference/reference_to_typedef: Fail
diff --git a/pkg/front_end/test/fasta/testing.json b/pkg/front_end/test/fasta/testing.json
index 8cdaaee..1a241f7 100644
--- a/pkg/front_end/test/fasta/testing.json
+++ b/pkg/front_end/test/fasta/testing.json
@@ -214,27 +214,7 @@
     },
 
     "exclude": [
-      "^pkg/analysis_server/lib/src/analysis_server\\.dart",
-      "^pkg/compiler/lib/src/closure\\.dart",
-      "^pkg/compiler/lib/src/elements/elements\\.dart",
-      "^pkg/compiler/lib/src/elements/modelx\\.dart",
-      "^pkg/compiler/lib/src/inferrer/inferrer_engine\\.dart",
-      "^pkg/compiler/lib/src/js_backend/namer\\.dart",
-      "^pkg/compiler/lib/src/kernel/kernel_visitor\\.dart",
-      "^pkg/compiler/lib/src/resolution/members\\.dart",
-      "^pkg/compiler/lib/src/resolution/resolution\\.dart",
-      "^pkg/compiler/lib/src/resolution/resolution_strategy\\.dart",
-      "^pkg/compiler/lib/src/serialization/equivalence\\.dart",
-      "^pkg/compiler/lib/src/serialization/resolved_ast_serialization\\.dart",
-      "^pkg/compiler/lib/src/ssa/builder_kernel\\.dart",
-      "^tests/compiler/dart2js/inference/enumerator\\.dart",
-      "^tests/compiler/dart2js/inference/id_equivalence_test\\.dart",
-      "^tests/compiler/dart2js/kernel/class_hierarchy_test\\.dart",
-      "^tests/compiler/dart2js/kernel/impact_test\\.dart",
-      "^tests/compiler/dart2js/kernel/visitor_test\\.dart",
-      "^tests/compiler/dart2js/location_collector_test\\.dart",
-      "^tests/compiler/dart2js/source_map_validator_helper\\.dart",
-      "^tests/compiler/dart2js/sourcemaps/sourcemap_helper\\.dart"
+      "^pkg/analysis_server/lib/src/analysis_server\\.dart"
     ]
   }
 }
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 1303ae9..ed6c64d 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -192,8 +192,12 @@
     File generated = new File.fromUri(uri);
     StdioProcess process;
     try {
-      var platformDill = context.platformUri.toFilePath();
-      var args = ['--platform=$platformDill', generated.path, "Hello, World!"];
+      var sdkPath = context.sdk.toFilePath();
+      var args = [
+        '--kernel-binaries=$sdkPath',
+        generated.path,
+        "Hello, World!"
+      ];
       process = await StdioProcess.run(context.vm.toFilePath(), args);
       print(process.output);
     } finally {
diff --git a/pkg/front_end/test/incremental_kernel_generator_test.dart b/pkg/front_end/test/incremental_kernel_generator_test.dart
index 5253494..878a2a4 100644
--- a/pkg/front_end/test/incremental_kernel_generator_test.dart
+++ b/pkg/front_end/test/incremental_kernel_generator_test.dart
@@ -368,15 +368,6 @@
     }
   }
 
-  void _assertCompiledUris(Iterable<Uri> expected) {
-    var compiledCycles = incrementalKernelGenerator.test.compiledCycles;
-    Set<Uri> compiledUris = compiledCycles
-        .map((cycle) => cycle.libraries.map((file) => file.uri))
-        .expand((uris) => uris)
-        .toSet();
-    expect(compiledUris, unorderedEquals(expected));
-  }
-
   test_compile_typedef() async {
     writeFile('/test/.packages', 'test:lib/');
     String aPath = '/test/lib/a.dart';
@@ -822,6 +813,26 @@
     }
   }
 
+  test_watch_null() async {
+    writeFile('/test/.packages', 'test:lib/');
+    String aPath = '/test/lib/a.dart';
+    String bPath = '/test/lib/b.dart';
+    writeFile(aPath, "");
+    Uri bUri = writeFile(bPath, "");
+
+    // Set null, as if the watch function is not provided.
+    watchFn = null;
+
+    await getInitialState(bUri);
+
+    // Update b.dart to import a.dart file.
+    writeFile(bPath, "import 'a.dart';");
+    incrementalKernelGenerator.invalidate(bUri);
+    await incrementalKernelGenerator.computeDelta();
+
+    // No exception even though the watcher function is null.
+  }
+
   /// Write the given [text] of the file with the given [path] into the
   /// virtual filesystem.  Return the URI of the file.
   Uri writeFile(String path, String text) {
@@ -835,6 +846,15 @@
     contents.forEach(writeFile);
   }
 
+  void _assertCompiledUris(Iterable<Uri> expected) {
+    var compiledCycles = incrementalKernelGenerator.test.compiledCycles;
+    Set<Uri> compiledUris = compiledCycles
+        .map((cycle) => cycle.libraries.map((file) => file.uri))
+        .expand((uris) => uris)
+        .toSet();
+    expect(compiledUris, unorderedEquals(expected));
+  }
+
   void _assertLibraryUris(Program program,
       {List<Uri> includes: const [], List<Uri> excludes: const []}) {
     List<Uri> libraryUris =
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index 9cba6ce..4a60cc7 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -1043,7 +1043,7 @@
   void test_string_multi_unterminated() {
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "'''string'''", 0, 9),
       ]);
@@ -1064,7 +1064,7 @@
       new TestError(8, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null),
     ];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 9),
         new SyntheticStringToken(TokenType.STRING, "'''", 9, 0),
@@ -1090,7 +1090,7 @@
       new StringToken(TokenType.IDENTIFIER, "name", 4),
     ];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "'''", 8, 0),
       ]);
@@ -1115,7 +1115,7 @@
     String source = "r'''string";
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "r'''string'''", 0, 10),
       ]);
@@ -1140,7 +1140,7 @@
     String source = "r'string";
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "r'string'", 0, 8),
       ]);
@@ -1157,7 +1157,7 @@
     String source = "r'string\n";
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "r'string'", 0, 8),
       ]);
@@ -1298,7 +1298,7 @@
     String source = "'string";
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "'string'", 0, 7),
       ]);
@@ -1315,7 +1315,7 @@
     String source = "'string\r";
     List<Token> expectedTokens = [];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "'string'", 0, 7),
       ]);
@@ -1338,7 +1338,7 @@
       new TestError(6, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null),
     ];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 7),
         new SyntheticStringToken(TokenType.STRING, "'", 7, 0),
@@ -1364,7 +1364,7 @@
       new StringToken(TokenType.IDENTIFIER, "name", 2),
     ];
     if (usingFasta) {
-      // fasta inserts synthetic closers
+      // Fasta inserts synthetic closers.
       expectedTokens.addAll([
         new SyntheticStringToken(TokenType.STRING, "'", 6, 0),
       ]);
diff --git a/pkg/front_end/test/src/base/libraries_reader_test.dart b/pkg/front_end/test/src/base/libraries_reader_test.dart
deleted file mode 100644
index 548fea0..0000000
--- a/pkg/front_end/test/src/base/libraries_reader_test.dart
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
-import 'package:front_end/src/base/library_info.dart';
-import 'package:front_end/src/libraries_reader.dart';
-import 'package:front_end/src/scanner/errors.dart';
-import 'package:front_end/src/scanner/reader.dart';
-import 'package:front_end/src/scanner/scanner.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(LibrariesReaderTest);
-  });
-}
-
-/// Generic URI resolver tests which do not depend on the particular path
-/// context in use.
-@reflectiveTest
-class LibrariesReaderTest {
-  test_categoriesClient() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", categories: "Client")');
-    expect(info.categories, [Category.client]);
-    expect(info.categoriesString, 'Client');
-  }
-
-  test_categoriesDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.categories, isEmpty);
-    expect(info.categoriesString, '');
-  }
-
-  test_categoriesMultiple() {
-    var info = _computeSingleInfo(
-        'const LibraryInfo("", categories: "Client,Server")');
-    expect(
-        info.categories, unorderedEquals([Category.client, Category.server]));
-    expect(info.categoriesString, 'Client,Server');
-  }
-
-  test_categoriesNone() {
-    var info = _computeSingleInfo('const LibraryInfo("", categories: "")');
-    expect(info.categories, isEmpty);
-    expect(info.categoriesString, '');
-  }
-
-  test_categoriesSingle() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", categories: "Client")');
-    expect(info.categories, [Category.client]);
-    expect(info.categoriesString, 'Client');
-  }
-
-  test_complex() {
-    var info = _computeSingleInfo(
-        '''
-const LibraryInfo(
-    "async/async.dart",
-    categories: "Client,Server",
-    maturity: Maturity.STABLE,
-    dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"))
-''',
-        additionalDeclarations: '''
-class Maturity {
-  final int level;
-  final String name;
-  final String description;
-
-  const Maturity(this.level, this.name, this.description);
-
-  static const Maturity STABLE = const Maturity(4, "Stable", "Stable description");
-}
-''');
-    expect(info.path, 'async/async.dart');
-    expect(
-        info.categories, unorderedEquals([Category.client, Category.server]));
-    expect(info.maturity.name, 'Stable');
-    expect(info.dart2jsPatchPath, '_internal/js_runtime/lib/async_patch.dart');
-  }
-
-  test_dart2jsPatchPathDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.dart2jsPatchPath, null);
-  }
-
-  test_dart2jsPatchPathString() {
-    var info = _computeSingleInfo('''
-const LibraryInfo(
-    "",
-    dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart")
-''');
-    expect(info.dart2jsPatchPath, '_internal/js_runtime/lib/async_patch.dart');
-  }
-
-  test_dart2jsPathDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.dart2jsPath, null);
-  }
-
-  test_dart2jsPathString() {
-    var info = _computeSingleInfo(
-        'const LibraryInfo("", dart2jsPath: "html/dart2js/html_dart2js.dart"');
-    expect(info.dart2jsPath, 'html/dart2js/html_dart2js.dart');
-  }
-
-  test_documentedDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.documented, true);
-  }
-
-  test_documentedFalse() {
-    var info = _computeSingleInfo('const LibraryInfo("", documented: false)');
-    expect(info.documented, false);
-  }
-
-  test_documentedTrue() {
-    var info = _computeSingleInfo('const LibraryInfo("", documented: true)');
-    expect(info.documented, true);
-  }
-
-  test_implementationDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.implementation, false);
-  }
-
-  test_implementationFalse() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", implementation: false)');
-    expect(info.implementation, false);
-  }
-
-  test_implementationTrue() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", implementation: true)');
-    expect(info.implementation, true);
-  }
-
-  test_maturityDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.maturity, Maturity.UNSPECIFIED);
-  }
-
-  test_maturityStable() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", maturity: Maturity.FOO)',
-            additionalDeclarations: '''
-class Maturity {
-  final int level;
-  final String name;
-  final String description;
-
-  const Maturity(this.level, this.name, this.description);
-
-  static const Maturity FOO = const Maturity(10, "Foo", "Foo description");
-}
-''');
-    expect(info.maturity.level, 10);
-    expect(info.maturity.name, 'Foo');
-    expect(info.maturity.description, 'Foo description');
-  }
-
-  test_multipleLibraries() {
-    var info = _computeLibraries('''
-const Map<String, LibraryInfo> libraries = const {
-  "async": const LibraryInfo("async/async.dart"),
-  "core": const LibraryInfo("core/core.dart")
-}
-''');
-    expect(info.keys, unorderedEquals(['async', 'core']));
-    expect(info['async'].path, 'async/async.dart');
-    expect(info['core'].path, 'core/core.dart');
-  }
-
-  test_path() {
-    var info = _computeSingleInfo('const LibraryInfo("core/core.dart")');
-    expect(info.path, 'core/core.dart');
-  }
-
-  test_platformsDefault() {
-    var info = _computeSingleInfo('const LibraryInfo("")');
-    expect(info.platforms, DART2JS_PLATFORM | VM_PLATFORM);
-  }
-
-  test_platformsMultiple() {
-    var info = _computeSingleInfo(
-        'const LibraryInfo("", platforms: VM_PLATFORM | DART2JS_PLATFORM)',
-        additionalDeclarations: '''
-const int DART2JS_PLATFORM = 1;
-const int VM_PLATFORM = 2;
-''');
-    expect(info.platforms, 1 | 2);
-  }
-
-  test_platformsSingle() {
-    var info =
-        _computeSingleInfo('const LibraryInfo("", platforms: VM_PLATFORM)',
-            additionalDeclarations: '''
-const int VM_PLATFORM = 2;
-''');
-    expect(info.platforms, 2);
-  }
-
-  Map<String, LibraryInfo> _computeLibraries(String text,
-      {String additionalDeclarations: ''}) {
-    var fullText = '$text\n$additionalDeclarations';
-    var scanner = new _Scanner(fullText);
-    var token = scanner.tokenize();
-    var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
-    var compilationUnit = parser.parseCompilationUnit(token);
-    var unlinkedUnit = serializeAstUnlinked(compilationUnit);
-    return readLibraries(unlinkedUnit);
-  }
-
-  LibraryInfo _computeSingleInfo(String text,
-      {String additionalDeclarations: ''}) {
-    var libraries = _computeLibraries(
-        'const Map<String, LibraryInfo> libraries = const { "x": $text };',
-        additionalDeclarations: additionalDeclarations);
-    return libraries['x'];
-  }
-}
-
-class _Scanner extends Scanner {
-  _Scanner(String contents) : super.create(new CharSequenceReader(contents)) {
-    preserveComments = false;
-  }
-
-  @override
-  void reportError(
-      ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-    fail('Unexpected error($errorCode, $offset, $arguments)');
-  }
-}
diff --git a/pkg/front_end/test/src/base/test_all.dart b/pkg/front_end/test/src/base/test_all.dart
index a28fa7f..81c8ea8 100644
--- a/pkg/front_end/test/src/base/test_all.dart
+++ b/pkg/front_end/test/src/base/test_all.dart
@@ -7,7 +7,6 @@
 import 'api_signature_test.dart' as api_signature;
 import 'file_repository_test.dart' as file_repository;
 import 'flat_buffers_test.dart' as flat_buffers;
-import 'libraries_reader_test.dart' as libraries_reader;
 import 'processed_options_test.dart' as processed_options;
 import 'uri_resolver_test.dart' as uri_resolver;
 
@@ -17,7 +16,6 @@
     api_signature.main();
     file_repository.main();
     flat_buffers.main();
-    libraries_reader.main();
     processed_options.main();
     uri_resolver.main();
   }, name: 'incremental');
diff --git a/pkg/front_end/test/src/incremental/file_state_test.dart b/pkg/front_end/test/src/incremental/file_state_test.dart
index e3e3dc8..b195da4 100644
--- a/pkg/front_end/test/src/incremental/file_state_test.dart
+++ b/pkg/front_end/test/src/incremental/file_state_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:front_end/memory_file_system.dart';
 import 'package:front_end/src/fasta/translate_uri.dart';
+import 'package:front_end/src/incremental/byte_store.dart';
 import 'package:front_end/src/incremental/file_state.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -20,6 +21,7 @@
 
 @reflectiveTest
 class FileSystemStateTest {
+  final byteStore = new MemoryByteStore();
   final fileSystem = new MemoryFileSystem(Uri.parse('file:///'));
   final TranslateUri uriTranslator = new TranslateUri({}, {}, {});
   FileSystemState fsState;
@@ -32,7 +34,8 @@
     uriTranslator.dartLibraries.addAll(dartLibraries);
     _coreUri = Uri.parse('dart:core');
     expect(_coreUri, isNotNull);
-    fsState = new FileSystemState(fileSystem, uriTranslator, <int>[], (uri) {
+    fsState = new FileSystemState(byteStore, fileSystem, uriTranslator, <int>[],
+        (uri) {
       _newFileUris.add(uri);
       return new Future.value();
     });
@@ -488,6 +491,38 @@
     expect(order[2].libraries, unorderedEquals([b, c]));
   }
 
+  test_transitiveFiles() async {
+    var a = writeFile('/a.dart', "");
+    var b = writeFile('/b.dart', "");
+    var c = writeFile('/c.dart', "import 'b.dart';");
+
+    FileState aFile = await fsState.getFile(a);
+    FileState bFile = await fsState.getFile(b);
+    FileState cFile = await fsState.getFile(c);
+
+    // Only c.dart and b.dart are in the transitive closure.
+    expect(cFile.transitiveFiles, contains(cFile));
+    expect(cFile.transitiveFiles, contains(bFile));
+    expect(cFile.transitiveFiles, isNot(contains(aFile)));
+    expect(bFile.transitiveFiles, isNot(contains(aFile)));
+
+    // Import a.dart into b.dart, changes c.dart transitive closure.
+    writeFile('/b.dart', "import 'a.dart';");
+    await bFile.refresh();
+    expect(cFile.transitiveFiles, contains(cFile));
+    expect(cFile.transitiveFiles, contains(bFile));
+    expect(cFile.transitiveFiles, contains(aFile));
+    expect(bFile.transitiveFiles, contains(aFile));
+
+    // Stop importing a.dart into b.dart, changes c.dart transitive closure.
+    writeFile('/b.dart', "");
+    await bFile.refresh();
+    expect(cFile.transitiveFiles, contains(cFile));
+    expect(cFile.transitiveFiles, contains(bFile));
+    expect(cFile.transitiveFiles, isNot(contains(aFile)));
+    expect(bFile.transitiveFiles, isNot(contains(aFile)));
+  }
+
   /// Write the given [text] of the file with the given [path] into the
   /// virtual filesystem.  Return the URI of the file.
   Uri writeFile(String path, String text) {
diff --git a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
index 728087c..6c512e6 100644
--- a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
@@ -17,11 +17,12 @@
 import 'package:front_end/memory_file_system.dart';
 import 'package:front_end/src/incremental/byte_store.dart';
 import 'package:front_end/src/testing/hybrid_file_system.dart';
-import 'package:front_end/src/vm/reload.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/binary/limited_ast_to_binary.dart';
 import 'package:test/test.dart';
 
+import '../../../tool/vm/reload.dart';
+
 main() {
   IncrementalKernelGenerator compiler;
   MemoryFileSystem fs;
diff --git a/pkg/front_end/test/subpackage_relationships_test.dart b/pkg/front_end/test/subpackage_relationships_test.dart
index 72d5b6b..43a664c 100644
--- a/pkg/front_end/test/subpackage_relationships_test.dart
+++ b/pkg/front_end/test/subpackage_relationships_test.dart
@@ -13,6 +13,22 @@
   exit(await new _SubpackageRelationshipsTest().run());
 }
 
+/// List of packages that front_end is allowed to directly depend on.
+///
+/// Note that this script only checks files in pkg/front_end/lib, so this list
+/// excludes dev dependencies.
+final allowedPackageDependencies = [
+  'charcode',
+  'convert',
+  'crypto',
+  'kernel',
+  'meta',
+  'package_config',
+  'path',
+  'source_span',
+  'testing',
+];
+
 /// Map from subpackage name to the rules for what the subpackage is allowed to
 /// depend directly on.
 ///
@@ -21,9 +37,8 @@
 ///
 /// TODO(paulberry): stuff in lib/src shouldn't depend on lib; lib should just
 /// re-export stuff in lib/src.
-/// TODO(paulberry): remove dependencies on analyzer.
 final subpackageRules = {
-  'lib': new SubpackageRules(mayImportAnalyzer: true, allowedDependencies: [
+  'lib': new SubpackageRules(allowedDependencies: [
     'lib/src',
     'lib/src/base',
     'lib/src/fasta',
@@ -31,7 +46,7 @@
     'lib/src/fasta/kernel',
     'lib/src/incremental'
   ]),
-  'lib/src': new SubpackageRules(mayImportAnalyzer: true, allowedDependencies: [
+  'lib/src': new SubpackageRules(allowedDependencies: [
     'lib',
     'lib/src/base',
     'lib/src/fasta',
@@ -139,14 +154,10 @@
   'lib/src/testing': new SubpackageRules(allowedDependencies: [
     'lib',
   ]),
-  'lib/src/vm': new SubpackageRules(allowedDependencies: []),
 };
 
 /// Rules for what a subpackage may depend directly on.
 class SubpackageRules {
-  /// Indicates whether the subpackage may directly depend on analyzer.
-  final bool mayImportAnalyzer;
-
   /// Indicates whether dart files may exist in subdirectories of this
   /// subpackage.
   ///
@@ -160,16 +171,12 @@
 
   var actuallyContainsFiles = false;
 
-  var actuallyImportsAnalyzer = false;
-
   var actuallyHasSubdirs = false;
 
   var actualDependencies = new Set<String>();
 
   SubpackageRules(
-      {this.mayImportAnalyzer: false,
-      this.allowSubdirs: false,
-      this.allowedDependencies: const []});
+      {this.allowSubdirs: false, this.allowedDependencies: const []});
 }
 
 class _SubpackageRelationshipsTest {
@@ -179,6 +186,9 @@
   /// Indicates whether any problems have been reported yet.
   bool problemsReported = false;
 
+  /// Package dependencies that were actually discovered
+  final actualPackageDependencies = <String>[];
+
   /// Check for problems resulting from URI [src] having a direct dependency on
   /// URI [dst].
   void checkDependency(Uri src, Uri dst) {
@@ -187,6 +197,17 @@
       problem('$src depends on $dst, which is neither a package: or dart: URI');
       return;
     }
+    if (src.scheme == 'package' &&
+        src.pathSegments[0] == 'front_end' &&
+        dst.scheme == 'package' &&
+        dst.pathSegments[0] != 'front_end') {
+      if (allowedPackageDependencies.contains(dst.pathSegments[0])) {
+        actualPackageDependencies.add(dst.pathSegments[0]);
+      } else {
+        problem('$src depends on package "${dst.pathSegments[0]}", which is '
+            'not found in allowedPackageDependencies');
+      }
+    }
     var srcSubpackage = subpackageForUri(src);
     if (srcSubpackage == null) return;
     var srcSubpackageRules = subpackageRules[srcSubpackage];
@@ -196,14 +217,6 @@
       return;
     }
     srcSubpackageRules.actuallyContainsFiles = true;
-    if (dst.pathSegments[0] == 'analyzer') {
-      if (srcSubpackageRules.mayImportAnalyzer) {
-        srcSubpackageRules.actuallyImportsAnalyzer = true;
-      } else {
-        problem('$src depends on $dst, but subpackage "$srcSubpackage" may not '
-            'import analyzer');
-      }
-    }
     var dstSubPackage = subpackageForUri(dst);
     if (dstSubPackage == null) return;
     if (dstSubPackage == srcSubpackage) return;
@@ -254,13 +267,16 @@
         }
       }
     }
+    for (var package in allowedPackageDependencies) {
+      if (!actualPackageDependencies.contains(package)) {
+        problem('$package is listed in allowedPackageDependencies, '
+            'but is not used');
+      }
+    }
     subpackageRules.forEach((subpackage, rule) {
       if (!rule.actuallyContainsFiles) {
         problem("$subpackage contains no files");
       }
-      if (rule.mayImportAnalyzer && !rule.actuallyImportsAnalyzer) {
-        problem("$subpackage is allowed to import analyzer, but doesn't");
-      }
       if (rule.allowSubdirs && !rule.actuallyHasSubdirs) {
         problem("$subpackage is allowed to have subdirectories, but doesn't");
       }
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart b/pkg/front_end/testcases/inference/conflicts_can_happen.dart
index e4ef920..8e72908 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart
@@ -22,12 +22,12 @@
 }
 
 class C1 implements A, B {
-  /*error:INVALID_METHOD_OVERRIDE*/ get a => null;
+  /*error:INVALID_METHOD_OVERRIDE*/ get /*@topType=dynamic*/ a => null;
 }
 
 // Still ambiguous
 class C2 implements B, A {
-  /*error:INVALID_METHOD_OVERRIDE*/ get a => null;
+  /*error:INVALID_METHOD_OVERRIDE*/ get /*@topType=dynamic*/ a => null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart
index 1f98b23..61b622a 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart
@@ -31,7 +31,7 @@
 }
 
 class C2 implements A, B {
-  /*error:INVALID_METHOD_OVERRIDE*/ get a => null;
+  /*error:INVALID_METHOD_OVERRIDE*/ get /*@topType=dynamic*/ a => null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart
similarity index 62%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart
index 7ea82f7..0d751d9 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart
@@ -5,8 +5,15 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class A implements B {
+  get /*@topType=int*/ x => f();
+  void set x(/*@topType=int*/ value) {}
+}
+
+class B {
+  var /*@topType=int*/ x = 0;
+}
+
+dynamic f() => null;
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.expect
new file mode 100644
index 0000000..a7caf13
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return self::f();
+  set x(dynamic value) → void {}
+}
+class B extends core::Object {
+  field dynamic x = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.outline.expect b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.outline.expect
new file mode 100644
index 0000000..b0e345a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    ;
+  get x() → dynamic
+    ;
+  set x(dynamic value) → void
+    ;
+}
+class B extends core::Object {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method f() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.strong.expect b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.strong.expect
new file mode 100644
index 0000000..7133d76
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.strong.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return self::f();
+  set x(core::int value) → void {}
+}
+class B extends core::Object {
+  field core::int x = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart
index 8b765d6..a2d7ab6 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart
@@ -10,8 +10,11 @@
 double getDouble() => 0.0;
 
 abstract class Base<T, U> {
-  T operator [](String s);
-  void operator []=(String s, U v);
+  T operator [](String s) => /*@target=Base::getValue*/ getValue(s);
+  void operator []=(String s, U v) => /*@target=Base::setValue*/ setValue(s, v);
+
+  T getValue(String s);
+  void setValue(String s, U v);
 }
 
 abstract class Test1 extends Base<int, int> {
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.direct.expect
index 9cc8d87..7132a5c 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.direct.expect
@@ -6,8 +6,12 @@
   constructor •() → void
     : super core::Object::•()
     ;
-  abstract operator [](core::String s) → self::Base::T;
-  abstract operator []=(core::String s, self::Base::U v) → void;
+  operator [](core::String s) → self::Base::T
+    return this.getValue(s);
+  operator []=(core::String s, self::Base::U v) → void
+    return this.setValue(s, v);
+  abstract method getValue(core::String s) → self::Base::T;
+  abstract method setValue(core::String s, self::Base::U v) → void;
 }
 abstract class Test1 extends self::Base<core::int, core::int> {
   constructor •() → void
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.outline.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.outline.expect
index 9dd5ea6..15c3a88 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.outline.expect
@@ -5,8 +5,12 @@
 abstract class Base<T extends core::Object, U extends core::Object> extends core::Object {
   constructor •() → void
     ;
-  abstract operator [](core::String s) → self::Base::T;
-  abstract operator []=(core::String s, self::Base::U v) → void;
+  operator [](core::String s) → self::Base::T
+    ;
+  operator []=(core::String s, self::Base::U v) → void
+    ;
+  abstract method getValue(core::String s) → self::Base::T;
+  abstract method setValue(core::String s, self::Base::U v) → void;
 }
 abstract class Test1 extends self::Base<core::int, core::int> {
   constructor •() → void
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.strong.expect
index 0b50ad1..d6c2a82 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_super_upwards.dart.strong.expect
@@ -6,8 +6,12 @@
   constructor •() → void
     : super core::Object::•()
     ;
-  abstract operator [](core::String s) → self::Base::T;
-  abstract operator []=(core::String s, self::Base::U v) → void;
+  operator [](core::String s) → self::Base::T
+    return this.{self::Base::getValue}(s);
+  operator []=(core::String s, self::Base::U v) → void
+    return this.{self::Base::setValue}(s, v);
+  abstract method getValue(core::String s) → self::Base::T;
+  abstract method setValue(core::String s, self::Base::U v) → void;
 }
 abstract class Test1 extends self::Base<core::int, core::int> {
   constructor •() → void
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property.dart b/pkg/front_end/testcases/inference/infer_assign_to_property.dart
deleted file mode 100644
index a3777f5..0000000
--- a/pkg/front_end/testcases/inference/infer_assign_to_property.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*@testedFeatures=inference*/
-library test;
-
-class A {
-  int f;
-}
-
-var /*@topType=dynamic*/ v_assign =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ new A(). /*@target=A::f*/ f = 1);
-var /*@topType=dynamic*/ v_plus =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ new A(). /*@target=A::f*/ f += 1);
-var /*@topType=dynamic*/ v_minus =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ new A(). /*@target=A::f*/ f -= 1);
-var /*@topType=dynamic*/ v_multiply =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ new A(). /*@target=A::f*/ f *= 1);
-var /*@topType=dynamic*/ v_prefix_pp =
-    (++new A(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=A::f*/ f);
-var /*@topType=dynamic*/ v_prefix_mm =
-    (--new A(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=A::f*/ f);
-var /*@topType=dynamic*/ v_postfix_pp =
-    (new A(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=A::f*/ f++);
-var /*@topType=dynamic*/ v_postfix_mm =
-    (new A(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=A::f*/ f--);
-
-main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_custom.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_custom.dart
deleted file mode 100644
index 1009aa2..0000000
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_custom.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*@testedFeatures=inference*/
-library test;
-
-class A {
-  int operator +(other) => 1;
-  double operator -(other) => 2.0;
-}
-
-class B {
-  A a;
-}
-
-var /*@topType=dynamic*/ v_prefix_pp =
-    (++new B(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=B::a*/ a);
-var /*@topType=dynamic*/ v_prefix_mm =
-    (--new B(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=B::a*/ a);
-var /*@topType=dynamic*/ v_postfix_pp =
-    (new B(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=B::a*/ a++);
-var /*@topType=dynamic*/ v_postfix_mm =
-    (new B(). /*error:TOP_LEVEL_INSTANCE_GETTER*/ /*@target=B::a*/ a--);
-
-main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart
index 1a958bc..ac6e633 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart
@@ -10,14 +10,9 @@
 }
 
 A a = new A();
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a. /*@target=A::f*/ f = 1);
 var /*@topType=int*/ c = 0;
-var /*@topType=dynamic*/ d = (/*error:TOP_LEVEL_UNSUPPORTED*/ c = 1);
 
 main() {
   a;
-  b;
   c;
-  d;
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.strong.expect
index a97346c..87ca7ea 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.strong.expect
@@ -9,12 +9,8 @@
     ;
 }
 static field self::A a = new self::A::•();
-static field dynamic b = self::a.{self::A::f} = 1;
 static field core::int c = 0;
-static field dynamic d = self::c = 1;
 static method main() → dynamic {
   self::a;
-  self::b;
   self::c;
-  self::d;
 }
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart
index 0de2d26..690be00 100644
--- a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart
+++ b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart
@@ -32,3 +32,5 @@
   i = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::z*/ z;
   i = new B(). /*@target=B::w*/ w;
 }
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.strong.expect b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.strong.expect
new file mode 100644
index 0000000..14bf512
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic x = null;
+  field core::int y = 2;
+  field core::String z = "hi";
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field dynamic x = 2;
+  field core::int y = 3;
+  field core::String z = null;
+  field core::int w = 2;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  core::String s;
+  core::int i;
+  s = new self::B::•().{self::B::x};
+  s = new self::B::•().{self::B::y};
+  s = new self::B::•().{self::B::z};
+  s = new self::B::•().{self::B::w};
+  i = new self::B::•().{self::B::x};
+  i = new self::B::•().{self::B::y};
+  i = new self::B::•().{self::B::z};
+  i = new self::B::•().{self::B::w};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart
index 7ea82f7..b2c29f6 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart
@@ -5,8 +5,12 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class A implements B {
+  var /*@topType=int*/ x;
+}
+
+class B {
+  var /*@topType=int*/ x = 0;
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.expect
new file mode 100644
index 0000000..d466b25
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  field dynamic x = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.outline.expect
new file mode 100644
index 0000000..89e0553
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.outline.expect
@@ -0,0 +1,16 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class B extends core::Object {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.strong.expect
new file mode 100644
index 0000000..b3b358e
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.strong.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  field core::int x = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart
similarity index 64%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart
index 7ea82f7..680a38b 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart
@@ -5,8 +5,16 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class A implements B {
+  var /*@topType=int*/ x;
+}
+
+abstract class B implements C {
+  get /*@topType=int*/ x;
+}
+
+abstract class C {
+  int get x;
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.expect
new file mode 100644
index 0000000..b359bd3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → dynamic;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.outline.expect
new file mode 100644
index 0000000..d3b9d4d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    ;
+  abstract get x() → dynamic;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.strong.expect
new file mode 100644
index 0000000..556a143
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart
similarity index 61%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart
index 7ea82f7..25960b5 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart
@@ -5,8 +5,16 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class A implements B {
+  var /*@topType=int*/ x;
+}
+
+abstract class B implements C {
+  void set x(/*@topType=int*/ value);
+}
+
+abstract class C {
+  void set x(int value);
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.expect
new file mode 100644
index 0000000..09f014a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(dynamic value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.outline.expect
new file mode 100644
index 0000000..4ba0fda
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    ;
+  abstract set x(dynamic value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.strong.expect
new file mode 100644
index 0000000..907a620
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart
new file mode 100644
index 0000000..a54cb11
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  int get x;
+  void set x(double value);
+}
+
+// Type inference should fail here since the getter and setter for x don't
+// match.
+class B extends A {
+  var /*@topType=dynamic*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.direct.expect
new file mode 100644
index 0000000..843617d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.direct.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.outline.expect
new file mode 100644
index 0000000..90cca38
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.outline.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.strong.expect
new file mode 100644
index 0000000..843617d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart
new file mode 100644
index 0000000..bde28bd
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  void set x(num value);
+}
+
+abstract class B extends A {
+  int get x;
+}
+
+// The getter in B doesn't screen the setter in A, so inference sees two
+// different types and gives an error.
+class C extends B {
+  var /*@topType=dynamic*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.direct.expect
new file mode 100644
index 0000000..a0482c0
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::num value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.outline.expect
new file mode 100644
index 0000000..c66baee
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(core::num value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.strong.expect
new file mode 100644
index 0000000..a0482c0
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::num value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart
new file mode 100644
index 0000000..4003e8c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  int get x;
+}
+
+abstract class B {
+  int get x;
+}
+
+abstract class C {
+  num get x;
+}
+
+abstract class D {
+  double get x;
+}
+
+// Superclasses have a consistent type for `x` so inferrence succeeds.
+class E extends A implements B {
+  var /*@topType=int*/ x;
+}
+
+// Superclasses don't have a consistent type for `x` so inference fails, even if
+// the types are related.
+class F extends A implements C {
+  var /*@topType=dynamic*/ x;
+}
+
+class G extends A implements D {
+  var /*@topType=dynamic*/ x;
+}
+
+class H extends C implements D {
+  var /*@topType=dynamic*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.expect
new file mode 100644
index 0000000..27bcb1e
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.expect
@@ -0,0 +1,53 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class D extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::double;
+}
+class E extends self::A implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class F extends self::A implements self::C {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class G extends self::A implements self::D {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class H extends self::C implements self::D {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
new file mode 100644
index 0000000..39afce3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
@@ -0,0 +1,46 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+abstract class B extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::num;
+}
+abstract class D extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::double;
+}
+class E extends self::A implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class F extends self::A implements self::C {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class G extends self::A implements self::D {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class H extends self::C implements self::D {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
new file mode 100644
index 0000000..38e3cdc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -0,0 +1,53 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class D extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::double;
+}
+class E extends self::A implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class F extends self::A implements self::C {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class G extends self::A implements self::D {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class H extends self::C implements self::D {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_field_override_of_override.dart
index 7ea82f7..c1438e7 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart
@@ -5,8 +5,16 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+abstract class A {
+  num get x;
+}
+
+abstract class B extends A {
+  int get x;
+}
+
+class C extends B {
+  var /*@topType=int*/ x;
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.expect
new file mode 100644
index 0000000..a805ae9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.outline.expect
new file mode 100644
index 0000000..46a8ec1
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.strong.expect
new file mode 100644
index 0000000..1362ead
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract get x() → core::int;
+}
+class C extends self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart
new file mode 100644
index 0000000..63a37fa
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  num get x;
+}
+
+abstract class B extends A {
+  void set x(int value);
+}
+
+// The getter in B doesn't screen the setter in A, so inference sees two
+// different types and gives an error.
+class C extends B {
+  var /*@topType=dynamic*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.direct.expect
new file mode 100644
index 0000000..28c4753
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+class C extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.outline.expect
new file mode 100644
index 0000000..584e4e9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    ;
+  abstract set x(core::int value) → void;
+}
+class C extends self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.strong.expect
new file mode 100644
index 0000000..28c4753
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_setter_overrides_getter.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+class C extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart
new file mode 100644
index 0000000..966ead8
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart
@@ -0,0 +1,20 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A<T> {
+  List<T> get x;
+  void set y(List<T> value);
+  List<T> z;
+}
+
+class B extends A<int> {
+  var /*@topType=List<int>*/ x;
+  var /*@topType=List<int>*/ y;
+  var /*@topType=List<int>*/ z;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.expect
new file mode 100644
index 0000000..b2139ce
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  field core::List<self::A::T> z = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::List<self::A::T>;
+  abstract set y(core::List<self::A::T> value) → void;
+}
+class B extends self::A<core::int> {
+  field dynamic x = null;
+  field dynamic y = null;
+  field dynamic z = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.outline.expect
new file mode 100644
index 0000000..a2e78d4a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.outline.expect
@@ -0,0 +1,20 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  field core::List<self::A::T> z;
+  constructor •() → void
+    ;
+  abstract get x() → core::List<self::A::T>;
+  abstract set y(core::List<self::A::T> value) → void;
+}
+class B extends self::A<core::int> {
+  field dynamic x;
+  field dynamic y;
+  field dynamic z;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.strong.expect
new file mode 100644
index 0000000..8a200d7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.strong.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  field core::List<self::A::T> z = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::List<self::A::T>;
+  abstract set y(core::List<self::A::T> value) → void;
+}
+class B extends self::A<core::int> {
+  field core::List<core::int> x = null;
+  field core::List<core::int> y = null;
+  field core::List<core::int> z = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart
new file mode 100644
index 0000000..753c60d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart
@@ -0,0 +1,36 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  int get x;
+}
+
+class B {
+  int get x => 0;
+}
+
+class C extends A {
+  var /*@topType=int*/ x;
+}
+
+class D extends B {
+  var /*@topType=int*/ x;
+}
+
+class E implements A {
+  var /*@topType=int*/ x;
+}
+
+class F implements B {
+  var /*@topType=int*/ x;
+}
+
+class G extends Object with B {
+  var /*@topType=int*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.expect
new file mode 100644
index 0000000..d92f7e2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.expect
@@ -0,0 +1,50 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return 0;
+}
+class C extends self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class D extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+class E extends core::Object implements self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class F extends core::Object implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
new file mode 100644
index 0000000..1263a6a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
@@ -0,0 +1,44 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+class B extends core::Object {
+  constructor •() → void
+    ;
+  get x() → core::int
+    ;
+}
+class C extends self::A {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class D extends self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class E extends core::Object implements self::A {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class F extends core::Object implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
new file mode 100644
index 0000000..4648fde
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
@@ -0,0 +1,50 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return 0;
+}
+class C extends self::A {
+  field core::int x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class D extends self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+class E extends core::Object implements self::A {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class F extends core::Object implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart
new file mode 100644
index 0000000..6b58152
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart
@@ -0,0 +1,36 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+abstract class A {
+  void set x(int value);
+}
+
+class B {
+  void set x(int value) {}
+}
+
+class C extends A {
+  var /*@topType=int*/ x;
+}
+
+class D extends B {
+  var /*@topType=int*/ x;
+}
+
+class E implements A {
+  var /*@topType=int*/ x;
+}
+
+class F implements B {
+  var /*@topType=int*/ x;
+}
+
+class G extends Object with B {
+  var /*@topType=int*/ x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.expect
new file mode 100644
index 0000000..aa153ad
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.expect
@@ -0,0 +1,49 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  set x(core::int value) → void {}
+}
+class C extends self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class D extends self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+class E extends core::Object implements self::A {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class F extends core::Object implements self::B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
new file mode 100644
index 0000000..e20e3ac
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
@@ -0,0 +1,44 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(core::int value) → void;
+}
+class B extends core::Object {
+  constructor •() → void
+    ;
+  set x(core::int value) → void
+    ;
+}
+class C extends self::A {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class D extends self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class E extends core::Object implements self::A {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+class F extends core::Object implements self::B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field dynamic x;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
new file mode 100644
index 0000000..ad8c22fe
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
@@ -0,0 +1,49 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  set x(core::int value) → void {}
+}
+class C extends self::A {
+  field core::int x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class D extends self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super self::B::•()
+    ;
+}
+class E extends core::Object implements self::A {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class F extends core::Object implements self::B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class Object&B = core::Object with self::B {
+}
+class G extends self::Object&B {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart b/pkg/front_end/testcases/inference/infer_field_static.dart
new file mode 100644
index 0000000..d5ddfbc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_static.dart
@@ -0,0 +1,28 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+dynamic f() => null;
+
+abstract class A {
+  static int get x => 0;
+}
+
+// Even though B extends A, A.x and B.x are unrelated because they're static.
+// So B.x doesn't inherit A.x's type.
+
+class B extends A {
+  static var /*@topType=dynamic*/ x = f();
+}
+
+// Similar with C.x.  It is not even eligible for inference since it's static
+// and has no initializer.
+
+class C extends A {
+  static var x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_static.dart.direct.expect
new file mode 100644
index 0000000..a5654ab
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_static.dart.direct.expect
@@ -0,0 +1,26 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  static get x() → core::int
+    return 0;
+}
+class B extends self::A {
+  static field dynamic x = self::f();
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class C extends self::A {
+  static field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_static.dart.outline.expect
new file mode 100644
index 0000000..7972953
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_static.dart.outline.expect
@@ -0,0 +1,24 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  static get x() → core::int
+    ;
+}
+class B extends self::A {
+  static field dynamic x;
+  constructor •() → void
+    ;
+}
+class C extends self::A {
+  static field dynamic x;
+  constructor •() → void
+    ;
+}
+static method f() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_static.dart.strong.expect
new file mode 100644
index 0000000..a5654ab
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_static.dart.strong.expect
@@ -0,0 +1,26 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  static get x() → core::int
+    return 0;
+}
+class B extends self::A {
+  static field dynamic x = self::f();
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+class C extends self::A {
+  static field dynamic x = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
index 7ea82f7..1cd1300 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
@@ -5,8 +5,15 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+abstract class A {
+  int get x;
+  void set x(double value);
+}
+
+class B extends A {
+  final /*@topType=int*/ x;
+
+  B(this.x);
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
new file mode 100644
index 0000000..217045b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    : self::B::x = x, super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
new file mode 100644
index 0000000..4d15c82
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
new file mode 100644
index 0000000..5aa8d73
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  final field core::int x;
+  constructor •(core::int x) → void
+    : self::B::x = x, super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_final_field_getter_only.dart
index 7ea82f7..fc4531b3 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart
@@ -5,8 +5,14 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+abstract class A {
+  int get x;
+}
+
+class B extends A {
+  final /*@topType=int*/ x;
+
+  B(this.x);
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.expect
new file mode 100644
index 0000000..26feec5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    : self::B::x = x, super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.outline.expect
new file mode 100644
index 0000000..94417e6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.outline.expect
@@ -0,0 +1,16 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.strong.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.strong.expect
new file mode 100644
index 0000000..11d45a4
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.strong.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+class B extends self::A {
+  final field core::int x;
+  constructor •(core::int x) → void
+    : self::B::x = x, super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
index 7ea82f7..cf037f2 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
@@ -5,8 +5,14 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+abstract class A {
+  void set x(double value);
+}
+
+class B extends A {
+  final /*@topType=double*/ x;
+
+  B(this.x);
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
new file mode 100644
index 0000000..6dfb8f5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    : self::B::x = x, super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect
new file mode 100644
index 0000000..e61ebe3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect
@@ -0,0 +1,16 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(core::double value) → void;
+}
+class B extends self::A {
+  final field dynamic x;
+  constructor •(dynamic x) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
index 1776f90..6f133e3 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
@@ -58,3 +58,5 @@
   j = /*error:INVALID_ASSIGNMENT*/ false;
   j = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ [];
 }
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
new file mode 100644
index 0000000..b748ab8
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
@@ -0,0 +1,53 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  operator +(dynamic other) → self::B
+    return null;
+}
+class B extends self::A {
+  constructor •(dynamic ignore) → void
+    : super self::A::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field self::B b = new self::B::•(throw new core::NoSuchMethodError::_withType(null, #x, 33, <dynamic>[].toList(growable: false), <dynamic, dynamic>{}, null));
+static field core::List<dynamic> c1 = <dynamic>[throw new core::NoSuchMethodError::_withType(null, #x, 33, <dynamic>[].toList(growable: false), <dynamic, dynamic>{}, null)];
+static field core::List<dynamic> c2 = const <dynamic>[];
+static field core::Map<dynamic, dynamic> d = <dynamic, dynamic>{"a": "b"};
+static field self::A e = let final self::A #t1 = new self::A::•() in let final dynamic #t2 = #t1.{self::A::x} = 3 in #t1;
+static field core::int f = 2.{core::num::+}(3);
+static field core::int g = 3.{core::int::unary-}();
+static field self::B h = new self::A::•().{self::A::+}(3);
+static field dynamic i = new self::A::•().unary-();
+static field self::B j = null as self::B;
+static method test1() → dynamic {
+  self::a = "hi";
+  self::a = new self::B::•(3);
+  self::b = "hi";
+  self::b = new self::B::•(3);
+  self::c1 = <dynamic>[];
+  self::c1 = <dynamic, dynamic>{};
+  self::c2 = <dynamic>[];
+  self::c2 = <dynamic, dynamic>{};
+  self::d = <dynamic, dynamic>{};
+  self::d = 3;
+  self::e = new self::A::•();
+  self::e = <dynamic, dynamic>{};
+  self::f = 3;
+  self::f = false;
+  self::g = 1;
+  self::g = false;
+  self::h = false;
+  self::h = new self::B::•("b");
+  self::i = false;
+  self::j = new self::B::•("b");
+  self::j = false;
+  self::j = <dynamic>[];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart
index c8bf6f9..3c9c3ef 100644
--- a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart
+++ b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart
@@ -17,3 +17,5 @@
   String y = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
   int z = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
 }
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.strong.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.strong.expect
new file mode 100644
index 0000000..a78fd93
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.strong.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field dynamic x = 2;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  core::String y = new self::B::•().{self::B::x};
+  core::int z = new self::B::•().{self::B::x};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart
index 08c7473..fd0a94b 100644
--- a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart
+++ b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart
@@ -17,3 +17,5 @@
   String y = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
   int z = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
 }
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.strong.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.strong.expect
new file mode 100644
index 0000000..345752b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.strong.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field dynamic x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  final field dynamic x = 2;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  core::String y = new self::B::•().{self::B::x};
+  core::int z = new self::B::•().{self::B::x};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart
similarity index 60%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart
index 7ea82f7..ff91432 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart
@@ -5,8 +5,18 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class A implements B {
+  get /*@topType=int*/ x => f();
+}
+
+abstract class B implements C {
+  get /*@topType=int*/ x;
+}
+
+abstract class C {
+  int get x;
+}
+
+dynamic f() => null;
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.expect
new file mode 100644
index 0000000..4a214be
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.expect
@@ -0,0 +1,26 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return self::f();
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → dynamic;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.outline.expect
new file mode 100644
index 0000000..04a7939
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.outline.expect
@@ -0,0 +1,24 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    ;
+  get x() → dynamic
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    ;
+  abstract get x() → dynamic;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    ;
+  abstract get x() → core::int;
+}
+static method f() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.strong.expect
new file mode 100644
index 0000000..e62a20f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.strong.expect
@@ -0,0 +1,26 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return self::f();
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int;
+}
+static method f() → dynamic
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart
index 2374e76..649101a 100644
--- a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart
+++ b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart
@@ -6,7 +6,7 @@
 library test;
 
 class C extends D {
-  set foo(x) {}
+  set foo(/*@topType=int*/ x) {}
 }
 
 class D {
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.strong.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.strong.expect
index 3fbebe6..9f70cb47 100644
--- a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.strong.expect
@@ -6,7 +6,7 @@
   constructor •() → void
     : super self::D::•()
     ;
-  set foo(dynamic x) → dynamic {}
+  set foo(core::int x) → dynamic {}
 }
 class D extends core::Object {
   field core::int foo = null;
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart
index bee5d20..4c6b671 100644
--- a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart
+++ b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart
@@ -6,7 +6,7 @@
 library test;
 
 class C extends D {
-  set foo(x) {}
+  set foo(/*@topType=int*/ x) {}
 }
 
 class D {
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.strong.expect
index 1594427..8234103 100644
--- a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.strong.expect
@@ -6,7 +6,7 @@
   constructor •() → void
     : super self::D::•()
     ;
-  set foo(dynamic x) → dynamic {}
+  set foo(core::int x) → dynamic {}
 }
 class D extends core::Object {
   constructor •() → void
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart
new file mode 100644
index 0000000..2a4141b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart
@@ -0,0 +1,20 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A implements B {
+  void set x(/*@topType=int*/ value) {}
+}
+
+abstract class B implements C {
+  void set x(/*@topType=int*/ value);
+}
+
+abstract class C {
+  void set x(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.expect
new file mode 100644
index 0000000..b91acff
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  set x(dynamic value) → void {}
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(dynamic value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.outline.expect
new file mode 100644
index 0000000..1647891
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.outline.expect
@@ -0,0 +1,22 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    ;
+  set x(dynamic value) → void
+    ;
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    ;
+  abstract set x(dynamic value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.strong.expect
new file mode 100644
index 0000000..bb6ff75
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object implements self::B {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  set x(core::int value) → void {}
+}
+abstract class B extends core::Object implements self::C {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+abstract class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart
new file mode 100644
index 0000000..3737022
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart
@@ -0,0 +1,27 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+// The `value` parameter for `B::x=` has a type, so it should not be inferred
+// based on `A::x=`.
+
+typedef int F();
+
+abstract class A {
+  void set x(F value);
+}
+
+abstract class B extends A {
+  void set x(value());
+}
+
+T f<T>() => null;
+
+g(B b) {
+  b. /*@target=B::x*/ x = /*@typeArgs=() -> dynamic*/ f();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.expect
new file mode 100644
index 0000000..d604051
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → core::int;
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(() → core::int value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract set x(() → dynamic value) → void;
+}
+static method f<T extends core::Object>() → self::f::T
+  return null;
+static method g(self::B b) → dynamic {
+  b.x = self::f<dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.outline.expect b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.outline.expect
new file mode 100644
index 0000000..b0b9adb
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.outline.expect
@@ -0,0 +1,21 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → core::int;
+abstract class A extends core::Object {
+  constructor •() → void
+    ;
+  abstract set x(() → core::int value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    ;
+  abstract set x(() → dynamic value) → void;
+}
+static method f<T extends core::Object>() → self::f::T
+  ;
+static method g(self::B b) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.strong.expect b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.strong.expect
new file mode 100644
index 0000000..718f8f8
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.strong.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → core::int;
+abstract class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract set x(() → core::int value) → void;
+}
+abstract class B extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+  abstract set x(() → dynamic value) → void;
+}
+static method f<T extends core::Object>() → self::f::T
+  return null;
+static method g(self::B b) → dynamic {
+  b.{self::B::x} = self::f<() → dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart
index 2edf9383..dc7828f 100644
--- a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart
+++ b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart
@@ -10,7 +10,7 @@
 }
 
 class B extends A {
-  get x => 3;
+  get /*@topType=int*/ x => 3;
 }
 
 foo() {
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.strong.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.strong.expect
index 4a0fb39..49cf586 100644
--- a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.strong.expect
@@ -12,7 +12,7 @@
   constructor •() → void
     : super self::A::•()
     ;
-  get x() → dynamic
+  get x() → core::int
     return 3;
 }
 static method foo() → dynamic {
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart
index 51442bf..188fe28 100644
--- a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart
+++ b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart
@@ -10,7 +10,7 @@
 }
 
 class B implements A {
-  get x => 3;
+  get /*@topType=int*/ x => 3;
 }
 
 foo() {
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.strong.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.strong.expect
index 7a44500..88f4e65 100644
--- a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.strong.expect
@@ -12,7 +12,7 @@
   constructor •() → void
     : super core::Object::•()
     ;
-  get x() → dynamic
+  get x() → core::int
     return 3;
 }
 static method foo() → dynamic {
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart
index 6a235ad..8f61c86 100644
--- a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart
+++ b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart
@@ -8,7 +8,7 @@
 import 'infer_type_regardless_of_declaration_order_or_cycles_b.dart';
 
 class C extends B {
-  get x => null;
+  get /*@topType=int*/ x => null;
 }
 
 class A {
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.strong.expect b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.strong.expect
index 0919a21..4a9dd95 100644
--- a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.strong.expect
@@ -7,7 +7,7 @@
   constructor •() → void
     : super inf::B::•()
     ;
-  get x() → dynamic
+  get x() → core::int
     return null;
 }
 class A extends core::Object {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart
index 389f9f4..3467d75 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart
@@ -11,8 +11,8 @@
 }
 
 class B implements A<int> {
-  get x => 3;
-  get w => /*error:RETURN_OF_INVALID_TYPE*/ "hello";
+  get /*@topType=int*/ x => 3;
+  get /*@topType=int*/ w => /*error:RETURN_OF_INVALID_TYPE*/ "hello";
 }
 
 foo() {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.strong.expect
index 2d63a49..7b39f1e 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.strong.expect
@@ -13,9 +13,9 @@
   constructor •() → void
     : super core::Object::•()
     ;
-  get x() → dynamic
+  get x() → core::int
     return 3;
-  get w() → dynamic
+  get w() → core::int
     return "hello";
 }
 static method foo() → dynamic {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart
index 957177a..d3bf9ef 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart
@@ -11,7 +11,7 @@
 
 class B<E> extends A<E> {
   E y;
-  get x => /*@target=B::y*/ y;
+  get /*@topType=B::E*/ x => /*@target=B::y*/ y;
 }
 
 foo() {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.strong.expect
index bc82bff..a5cf0b0 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.strong.expect
@@ -13,7 +13,7 @@
   constructor •() → void
     : super self::A::•()
     ;
-  get x() → dynamic
+  get x() → self::B::E
     return this.{self::B::y};
 }
 static method foo() → dynamic {
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart b/pkg/front_end/testcases/inference/inferred_type_cascade.dart
index 61b5338..a6308da 100644
--- a/pkg/front_end/testcases/inference/inferred_type_cascade.dart
+++ b/pkg/front_end/testcases/inference/inferred_type_cascade.dart
@@ -15,3 +15,5 @@
   .. /*@target=A::a*/ a = 1
   .. /*@target=A::b*/ b. /*@target=List::add*/ add(2)
   .. /*@target=A::m*/ m();
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect
new file mode 100644
index 0000000..c4e6526
--- /dev/null
+++ b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  field core::List<core::int> b = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  method m() → void {}
+}
+static field self::A v = let final self::A #t1 = new self::A::•() in let final dynamic #t2 = #t1.{self::A::a} = 1 in let final dynamic #t3 = #t1.{self::A::b}.{core::List::add}(2) in let final dynamic #t4 = #t1.{self::A::m}() in #t1;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart
index 7ea82f7..919883c 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart
@@ -5,8 +5,9 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class C {
+  get /*@topType=dynamic*/ x => null;
+  void set x(/*@topType=dynamic*/ value) {}
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.expect b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.expect
new file mode 100644
index 0000000..4d7ac20
--- /dev/null
+++ b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.expect
@@ -0,0 +1,13 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return null;
+  set x(dynamic value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.outline.expect b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.outline.expect
new file mode 100644
index 0000000..4ab42f1
--- /dev/null
+++ b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.outline.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → void
+    ;
+  get x() → dynamic
+    ;
+  set x(dynamic value) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.strong.expect b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.strong.expect
new file mode 100644
index 0000000..4d7ac20
--- /dev/null
+++ b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.strong.expect
@@ -0,0 +1,13 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return null;
+  set x(dynamic value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference/null_aware_property_get.dart
similarity index 67%
copy from pkg/front_end/testcases/inference/infer_assign_to_index.dart
copy to pkg/front_end/testcases/inference/null_aware_property_get.dart
index 7ea82f7..ed919ef 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart
@@ -5,8 +5,12 @@
 /*@testedFeatures=inference*/
 library test;
 
-List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+class C {
+  int x;
+}
+
+void f(C c) {
+  var /*@type=int*/ x = c?. /*@target=C::x*/ x;
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.expect
new file mode 100644
index 0000000..375ea20
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method f(self::C c) → void {
+  dynamic x = let final dynamic #t1 = c in #t1.==(null) ? null : #t1.x;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.outline.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.outline.expect
new file mode 100644
index 0000000..24136b1
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart.outline.expect
@@ -0,0 +1,13 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int x;
+  constructor •() → void
+    ;
+}
+static method f(self::C c) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect
new file mode 100644
index 0000000..5310c46
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int x = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method f(self::C c) → void {
+  core::int x = let final dynamic #t1 = c in #t1.==(null) ? null : #t1.{self::C::x};
+}
+static method main() → dynamic {}
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
new file mode 100644
index 0000000..33cc7954
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.expect
@@ -0,0 +1,9 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+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::int>[] : #t1;
+  core::List<core::int> z = y;
+}
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
new file mode 100644
index 0000000..b81c0b5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.expect
@@ -0,0 +1,8 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+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::num>[] : #t1;
+}
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart b/pkg/front_end/testcases/inference/property_get_toplevel.dart
index d9a8347..745394e 100644
--- a/pkg/front_end/testcases/inference/property_get_toplevel.dart
+++ b/pkg/front_end/testcases/inference/property_get_toplevel.dart
@@ -12,15 +12,7 @@
 }
 
 C c = new C();
-var /*@topType=dynamic*/ field_ref = c. /*@target=C::field*/ field;
-var /*@topType=dynamic*/ getter_ref = c. /*@target=C::getter*/ getter;
 var /*@topType=() -> int*/ function_ref = c. /*@target=C::function*/ function;
-var /*@topType=dynamic*/ field_ref_list = /*@typeArgs=int*/ [
-  c. /*@target=C::field*/ field
-];
-var /*@topType=dynamic*/ getter_ref_list = /*@typeArgs=int*/ [
-  c. /*@target=C::getter*/ getter
-];
 var /*@topType=List<() -> int>*/ function_ref_list = /*@typeArgs=() -> int*/ [
   c. /*@target=C::function*/ function
 ];
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect
index 403c6de..a383f81 100644
--- a/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect
@@ -13,10 +13,6 @@
     return 0;
 }
 static field self::C c = new self::C::•();
-static field dynamic field_ref = self::c.field;
-static field dynamic getter_ref = self::c.getter;
 static field dynamic function_ref = self::c.function;
-static field dynamic field_ref_list = <dynamic>[self::c.field];
-static field dynamic getter_ref_list = <dynamic>[self::c.getter];
 static field dynamic function_ref_list = <dynamic>[self::c.function];
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.outline.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.outline.expect
index 77bcf2a..87e635a 100644
--- a/pkg/front_end/testcases/inference/property_get_toplevel.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/property_get_toplevel.dart.outline.expect
@@ -12,11 +12,7 @@
     ;
 }
 static field self::C c;
-static field dynamic field_ref;
-static field dynamic getter_ref;
 static field dynamic function_ref;
-static field dynamic field_ref_list;
-static field dynamic getter_ref_list;
 static field dynamic function_ref_list;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.expect
index 3cd111a..35e4377 100644
--- a/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.expect
@@ -13,10 +13,6 @@
     return 0;
 }
 static field self::C c = new self::C::•();
-static field dynamic field_ref = self::c.{self::C::field};
-static field dynamic getter_ref = self::c.{self::C::getter};
 static field () → core::int function_ref = self::c.{self::C::function};
-static field dynamic field_ref_list = <core::int>[self::c.{self::C::field}];
-static field dynamic getter_ref_list = <core::int>[self::c.{self::C::getter}];
 static field core::List<() → core::int> function_ref_list = <() → core::int>[self::c.{self::C::function}];
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart
new file mode 100644
index 0000000..c9b1ad2
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart
@@ -0,0 +1,31 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  T f<T>(T t) => t;
+  int g(dynamic i) => 0;
+}
+
+var /*@topType=A*/ a = new A();
+
+// There's a circularity between b and c because a.f is generic, so the type of
+// c is required to infer b, and vice versa.
+
+var /*@topType=() -> dynamic*/ b = /*@returnType=() -> dynamic*/ () =>
+    a. /*@typeArgs=() -> dynamic*/ /*@target=A::f*/ f(c);
+var /*@topType=() -> dynamic*/ c = /*@returnType=() -> dynamic*/ () =>
+    a. /*@typeArgs=() -> dynamic*/ /*@target=A::f*/ f(b);
+
+// e's use of a.g breaks the circularity, because a.g is not generic, therefore
+// the type of e does not depend on the type of d.
+
+var /*@topType=() -> dynamic*/ d = /*@returnType=() -> int*/ () =>
+    a. /*@typeArgs=() -> int*/ /*@target=A::f*/ f(e);
+var /*@topType=() -> int*/ e = /*@returnType=int*/ () =>
+    a. /*@target=A::g*/ g(d);
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.expect
new file mode 100644
index 0000000..9868cfc
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  method f<T extends core::Object>(self::A::f::T t) → self::A::f::T
+    return t;
+  method g(dynamic i) → core::int
+    return 0;
+}
+static field dynamic a = new self::A::•();
+static field dynamic b = () → dynamic => self::a.f(self::c);
+static field dynamic c = () → dynamic => self::a.f(self::b);
+static field dynamic d = () → dynamic => self::a.f(self::e);
+static field dynamic e = () → dynamic => self::a.g(self::d);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.outline.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.outline.expect
new file mode 100644
index 0000000..89b02cd
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.outline.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    ;
+  method f<T extends core::Object>(self::A::f::T t) → self::A::f::T
+    ;
+  method g(dynamic i) → core::int
+    ;
+}
+static field dynamic a;
+static field dynamic b;
+static field dynamic c;
+static field dynamic d;
+static field dynamic e;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect
new file mode 100644
index 0000000..aad70d3
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  method f<T extends core::Object>(self::A::f::T t) → self::A::f::T
+    return t;
+  method g(dynamic i) → core::int
+    return 0;
+}
+static field self::A a = new self::A::•();
+static field () → dynamic b = () → () → dynamic => self::a.{self::A::f}<() → dynamic>(self::c);
+static field () → dynamic c = () → () → dynamic => self::a.{self::A::f}<() → dynamic>(self::b);
+static field () → dynamic d = () → () → core::int => self::a.{self::A::f}<() → core::int>(self::e);
+static field () → core::int e = () → core::int => self::a.{self::A::g}(self::d);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart
new file mode 100644
index 0000000..eb8d3d9
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart
@@ -0,0 +1,32 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+int intValue = 0;
+num numValue = 0;
+double doubleValue = 0.0;
+
+// There's a circularity between a and b because the type of `int + x` depends
+// on the type of x.
+
+var /*@topType=dynamic*/ a = /*@returnType=num*/ () =>
+    intValue /*@target=num::+*/ + b;
+var /*@topType=dynamic*/ b = a();
+
+// But there's no circularity between c and d because the type of `num + x` is
+// always num.
+
+var /*@topType=() -> num*/ c = /*@returnType=num*/ () =>
+    numValue /*@target=num::+*/ + d;
+var /*@topType=num*/ d = c();
+
+// Similar for double.
+
+var /*@topType=() -> double*/ e = /*@returnType=double*/ () =>
+    doubleValue /*@target=double::+*/ + f;
+var /*@topType=double*/ f = e();
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.expect
new file mode 100644
index 0000000..24f6d1b
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field core::int intValue = 0;
+static field core::num numValue = 0;
+static field core::double doubleValue = 0.0;
+static field dynamic a = () → dynamic => self::intValue.+(self::b);
+static field dynamic b = self::a.call();
+static field dynamic c = () → dynamic => self::numValue.+(self::d);
+static field dynamic d = self::c.call();
+static field dynamic e = () → dynamic => self::doubleValue.+(self::f);
+static field dynamic f = self::e.call();
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.outline.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.outline.expect
new file mode 100644
index 0000000..0f10321
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.outline.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field core::int intValue;
+static field core::num numValue;
+static field core::double doubleValue;
+static field dynamic a;
+static field dynamic b;
+static field dynamic c;
+static field dynamic d;
+static field dynamic e;
+static field dynamic f;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
new file mode 100644
index 0000000..edfeb83
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field core::int intValue = 0;
+static field core::num numValue = 0;
+static field core::double doubleValue = 0.0;
+static field dynamic a = () → core::num => self::intValue.{core::num::+}(self::b);
+static field dynamic b = self::a.call();
+static field () → core::num c = () → core::num => self::numValue.{core::num::+}(self::d);
+static field core::num d = self::c.call();
+static field () → core::double e = () → core::double => self::doubleValue.{core::double::+}(self::f);
+static field core::double f = self::e.call();
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart
new file mode 100644
index 0000000..5cef25d
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart
@@ -0,0 +1,23 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+// A.x depends on B.x which depends on A.x, so no type is inferred.  But types
+// can be inferred for A.y and B.y.
+
+class A {
+  var /*@topType=dynamic*/ x = /*@returnType=dynamic*/ () =>
+      new B(). /*@target=B::x*/ x;
+  var /*@topType=() -> dynamic*/ y = /*@returnType=dynamic*/ () =>
+      new B(). /*@target=B::x*/ x;
+}
+
+class B extends A {
+  var /*@topType=dynamic*/ x;
+  var /*@topType=() -> dynamic*/ y;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.expect
new file mode 100644
index 0000000..88b72a5
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic x = () → dynamic => new self::B::•().x;
+  field dynamic y = () → dynamic => new self::B::•().x;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  field dynamic x = null;
+  field dynamic y = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.outline.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.outline.expect
new file mode 100644
index 0000000..a922435
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.outline.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic x;
+  field dynamic y;
+  constructor •() → void
+    ;
+}
+class B extends self::A {
+  field dynamic x;
+  field dynamic y;
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect
new file mode 100644
index 0000000..9454b58
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic x = () → dynamic => new self::B::•().{self::B::x};
+  field () → dynamic y = () → dynamic => new self::B::•().{self::B::x};
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  field dynamic x = null;
+  field () → dynamic y = null;
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart
similarity index 74%
rename from pkg/front_end/testcases/inference/infer_assign_to_index.dart
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index.dart
index 7ea82f7..f08da41 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart
@@ -6,7 +6,6 @@
 library test;
 
 List<double> a = <double>[];
-var /*@topType=dynamic*/ b =
-    (/*error:TOP_LEVEL_UNSUPPORTED*/ a /*@target=List::[]=*/ [0] = 1.0);
+var /*@topType=double*/ b = (a /*@target=List::[]=*/ [0] = 1.0);
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.expect
similarity index 83%
rename from pkg/front_end/testcases/inference/infer_assign_to_index.dart.strong.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.expect
index 8f67e1a..650665c 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.expect
@@ -3,5 +3,5 @@
 import "dart:core" as core;
 
 static field core::List<core::double> a = <core::double>[];
-static field dynamic b = let final dynamic #t1 = self::a in let final dynamic #t2 = 0 in let final dynamic #t3 = 1.0 in let final dynamic #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
+static field dynamic b = let final dynamic #t1 = self::a in let final dynamic #t2 = 0 in let final dynamic #t3 = 1.0 in let final dynamic #t4 = #t1.[]=(#t2, #t3) in #t3;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.outline.expect
new file mode 100644
index 0000000..951b046
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.outline.expect
@@ -0,0 +1,8 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field core::List<core::double> a;
+static field dynamic b;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.expect
new file mode 100644
index 0000000..f22db7f
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.expect
@@ -0,0 +1,7 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field core::List<core::double> a = <core::double>[];
+static field core::double b = let final dynamic #t1 = self::a in let final dynamic #t2 = 0 in let final dynamic #t3 = 1.0 in let final dynamic #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart
new file mode 100644
index 0000000..eb39317
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  int f;
+}
+
+var /*@topType=int*/ v_assign = (new A(). /*@target=A::f*/ f = 1);
+var /*@topType=int*/ v_plus = (new A(). /*@target=A::f*/ f += 1);
+var /*@topType=int*/ v_minus = (new A(). /*@target=A::f*/ f -= 1);
+var /*@topType=int*/ v_multiply = (new A(). /*@target=A::f*/ f *= 1);
+var /*@topType=int*/ v_prefix_pp = (++new A(). /*@target=A::f*/ f);
+var /*@topType=int*/ v_prefix_mm = (--new A(). /*@target=A::f*/ f);
+var /*@topType=int*/ v_postfix_pp = (new A(). /*@target=A::f*/ f++);
+var /*@topType=int*/ v_postfix_mm = (new A(). /*@target=A::f*/ f--);
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.expect
new file mode 100644
index 0000000..49cb344
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field dynamic v_assign = new self::A::•().f = 1;
+static field dynamic v_plus = let final dynamic #t1 = new self::A::•() in #t1.f = #t1.f.+(1);
+static field dynamic v_minus = let final dynamic #t2 = new self::A::•() in #t2.f = #t2.f.-(1);
+static field dynamic v_multiply = let final dynamic #t3 = new self::A::•() in #t3.f = #t3.f.*(1);
+static field dynamic v_prefix_pp = let final dynamic #t4 = new self::A::•() in #t4.f = #t4.f.+(1);
+static field dynamic v_prefix_mm = let final dynamic #t5 = new self::A::•() in #t5.f = #t5.f.-(1);
+static field dynamic v_postfix_pp = let final dynamic #t6 = new self::A::•() in let final dynamic #t7 = #t6.f in let final dynamic #t8 = #t6.f = #t7.+(1) in #t7;
+static field dynamic v_postfix_mm = let final dynamic #t9 = new self::A::•() in let final dynamic #t10 = #t9.f in let final dynamic #t11 = #t9.f = #t10.-(1) in #t10;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.outline.expect
new file mode 100644
index 0000000..b08e8cd
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.outline.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f;
+  constructor •() → void
+    ;
+}
+static field dynamic v_assign;
+static field dynamic v_plus;
+static field dynamic v_minus;
+static field dynamic v_multiply;
+static field dynamic v_prefix_pp;
+static field dynamic v_prefix_mm;
+static field dynamic v_postfix_pp;
+static field dynamic v_postfix_mm;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.strong.expect
new file mode 100644
index 0000000..7278b8b
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.strong.expect
@@ -0,0 +1,19 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field core::int v_assign = new self::A::•().{self::A::f} = 1;
+static field core::int v_plus = let final dynamic #t1 = new self::A::•() in #t1.{self::A::f} = #t1.{self::A::f}.{core::num::+}(1);
+static field core::int v_minus = let final dynamic #t2 = new self::A::•() in #t2.{self::A::f} = #t2.{self::A::f}.{core::num::-}(1);
+static field core::int v_multiply = let final dynamic #t3 = new self::A::•() in #t3.{self::A::f} = #t3.{self::A::f}.{core::num::*}(1);
+static field core::int v_prefix_pp = let final dynamic #t4 = new self::A::•() in #t4.{self::A::f} = #t4.{self::A::f}.{core::num::+}(1);
+static field core::int v_prefix_mm = let final dynamic #t5 = new self::A::•() in #t5.{self::A::f} = #t5.{self::A::f}.{core::num::-}(1);
+static field core::int v_postfix_pp = let final dynamic #t6 = new self::A::•() in let final dynamic #t7 = #t6.{self::A::f} in let final dynamic #t8 = #t6.{self::A::f} = #t7.{core::num::+}(1) in #t7;
+static field core::int v_postfix_mm = let final dynamic #t9 = new self::A::•() in let final dynamic #t10 = #t9.{self::A::f} in let final dynamic #t11 = #t9.{self::A::f} = #t10.{core::num::-}(1) in #t10;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart
new file mode 100644
index 0000000..c014ab6
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  int operator +(other) => 1;
+  double operator -(other) => 2.0;
+}
+
+class B {
+  A a;
+}
+
+var /*@topType=int*/ v_prefix_pp = (++new B(). /*@target=B::a*/ a);
+var /*@topType=double*/ v_prefix_mm = (--new B(). /*@target=B::a*/ a);
+var /*@topType=A*/ v_postfix_pp = (new B(). /*@target=B::a*/ a++);
+var /*@topType=A*/ v_postfix_mm = (new B(). /*@target=B::a*/ a--);
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.expect
new file mode 100644
index 0000000..5591bc4
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.expect
@@ -0,0 +1,24 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  operator +(dynamic other) → core::int
+    return 1;
+  operator -(dynamic other) → core::double
+    return 2.0;
+}
+class B extends core::Object {
+  field self::A a = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field dynamic v_prefix_pp = let final dynamic #t1 = new self::B::•() in #t1.a = #t1.a.+(1);
+static field dynamic v_prefix_mm = let final dynamic #t2 = new self::B::•() in #t2.a = #t2.a.-(1);
+static field dynamic v_postfix_pp = let final dynamic #t3 = new self::B::•() in let final dynamic #t4 = #t3.a in let final dynamic #t5 = #t3.a = #t4.+(1) in #t4;
+static field dynamic v_postfix_mm = let final dynamic #t6 = new self::B::•() in let final dynamic #t7 = #t6.a in let final dynamic #t8 = #t6.a = #t7.-(1) in #t7;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.outline.expect
new file mode 100644
index 0000000..a2273ac
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    ;
+  operator +(dynamic other) → core::int
+    ;
+  operator -(dynamic other) → core::double
+    ;
+}
+class B extends core::Object {
+  field self::A a;
+  constructor •() → void
+    ;
+}
+static field dynamic v_prefix_pp;
+static field dynamic v_prefix_mm;
+static field dynamic v_postfix_pp;
+static field dynamic v_postfix_mm;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect
new file mode 100644
index 0000000..09ebbe6
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect
@@ -0,0 +1,24 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  operator +(dynamic other) → core::int
+    return 1;
+  operator -(dynamic other) → core::double
+    return 2.0;
+}
+class B extends core::Object {
+  field self::A a = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field core::int v_prefix_pp = let final dynamic #t1 = new self::B::•() in #t1.{self::B::a} = #t1.{self::B::a}.{self::A::+}(1);
+static field core::double v_prefix_mm = let final dynamic #t2 = new self::B::•() in #t2.{self::B::a} = #t2.{self::B::a}.{self::A::-}(1);
+static field self::A v_postfix_pp = let final dynamic #t3 = new self::B::•() in let final dynamic #t4 = #t3.{self::B::a} in let final dynamic #t5 = #t3.{self::B::a} = #t4.{self::A::+}(1) in #t4;
+static field self::A v_postfix_mm = let final dynamic #t6 = new self::B::•() in let final dynamic #t7 = #t6.{self::B::a} in let final dynamic #t8 = #t6.{self::B::a} = #t7.{self::A::-}(1) in #t7;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart
new file mode 100644
index 0000000..4ddb4ed
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  int f;
+}
+
+A a = new A();
+var /*@topType=int*/ b = (a. /*@target=A::f*/ f = 1);
+var /*@topType=int*/ c = 0;
+var /*@topType=int*/ d = (c = 1);
+
+main() {
+  a;
+  b;
+  c;
+  d;
+}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.expect
new file mode 100644
index 0000000..18ae6a7
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.expect
@@ -0,0 +1,20 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field dynamic b = self::a.f = 1;
+static field dynamic c = 0;
+static field dynamic d = self::c = 1;
+static method main() → dynamic {
+  self::a;
+  self::b;
+  self::c;
+  self::d;
+}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.outline.expect
new file mode 100644
index 0000000..a5017b2
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.outline.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f;
+  constructor •() → void
+    ;
+}
+static field self::A a;
+static field dynamic b;
+static field dynamic c;
+static field dynamic d;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.strong.expect
new file mode 100644
index 0000000..4593eca
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.strong.expect
@@ -0,0 +1,20 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int f = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field core::int b = self::a.{self::A::f} = 1;
+static field core::int c = 0;
+static field core::int d = self::c = 1;
+static method main() → dynamic {
+  self::a;
+  self::b;
+  self::c;
+  self::d;
+}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
new file mode 100644
index 0000000..9abb415
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
@@ -0,0 +1,25 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  B b;
+}
+
+class B {
+  C get c => null;
+  void set c(C value) {}
+}
+
+class C {}
+
+class D extends C {}
+
+var /*@topType=A*/ a = new A();
+var /*@topType=C*/ x = a. /*@target=A::b*/ b. /*@target=B::c*/ c;
+var /*@topType=C*/ y = a. /*@target=A::b*/ b. /*@target=B::c*/ c ??= new D();
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.expect
new file mode 100644
index 0000000..183c148
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.expect
@@ -0,0 +1,32 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get c() → self::C
+    return null;
+  set c(self::C value) → void {}
+}
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static field dynamic a = new self::A::•();
+static field dynamic x = self::a.b.c;
+static field dynamic y = let final dynamic #t1 = self::a.b in let final dynamic #t2 = #t1.c in #t2.==(null) ? #t1.c = new self::D::•() : #t2;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.outline.expect
new file mode 100644
index 0000000..51ac9ee
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.outline.expect
@@ -0,0 +1,30 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b;
+  constructor •() → void
+    ;
+}
+class B extends core::Object {
+  constructor •() → void
+    ;
+  get c() → self::C
+    ;
+  set c(self::C value) → void
+    ;
+}
+class C extends core::Object {
+  constructor •() → void
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    ;
+}
+static field dynamic a;
+static field dynamic x;
+static field dynamic y;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.strong.expect
new file mode 100644
index 0000000..1a3ee8a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.strong.expect
@@ -0,0 +1,32 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get c() → self::C
+    return null;
+  set c(self::C value) → void {}
+}
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field self::C x = self::a.{self::A::b}.{self::B::c};
+static field self::C y = let final dynamic #t1 = self::a.{self::A::b} in let final dynamic #t2 = #t1.{self::B::c} in #t2.{core::Object::==}(null) ? #t1.{self::B::c} = new self::D::•() : #t2;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
new file mode 100644
index 0000000..192a93b
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+  B b;
+}
+
+class B {
+  C c;
+}
+
+class C {}
+
+class D extends C {}
+
+var /*@topType=A*/ a = new A();
+var /*@topType=C*/ x = a. /*@target=A::b*/ b. /*@target=B::c*/ c;
+var /*@topType=C*/ y = a. /*@target=A::b*/ b. /*@target=B::c*/ c ??= new D();
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.expect
new file mode 100644
index 0000000..3b8b25e
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.expect
@@ -0,0 +1,30 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  field self::C c = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static field dynamic a = new self::A::•();
+static field dynamic x = self::a.b.c;
+static field dynamic y = let final dynamic #t1 = self::a.b in let final dynamic #t2 = #t1.c in #t2.==(null) ? #t1.c = new self::D::•() : #t2;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.outline.expect
new file mode 100644
index 0000000..d5e50fb
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.outline.expect
@@ -0,0 +1,27 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b;
+  constructor •() → void
+    ;
+}
+class B extends core::Object {
+  field self::C c;
+  constructor •() → void
+    ;
+}
+class C extends core::Object {
+  constructor •() → void
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    ;
+}
+static field dynamic a;
+static field dynamic x;
+static field dynamic y;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.strong.expect
new file mode 100644
index 0000000..e2e3748
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.strong.expect
@@ -0,0 +1,30 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field self::B b = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  field self::C c = null;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  constructor •() → void
+    : super self::C::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field self::C x = self::a.{self::A::b}.{self::B::c};
+static field self::C y = let final dynamic #t1 = self::a.{self::A::b} in let final dynamic #t2 = #t1.{self::B::c} in #t2.{core::Object::==}(null) ? #t1.{self::B::c} = new self::D::•() : #t2;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart
new file mode 100644
index 0000000..b83ee3a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+// In the code below, there is a circularity between A.b and x.
+
+class A {
+  var /*@topType=dynamic*/ b = /*@returnType=dynamic*/ () => x;
+  var /*@topType=() -> dynamic*/ c = /*@returnType=dynamic*/ () => x;
+}
+
+var /*@topType=A*/ a = new A();
+var /*@topType=dynamic*/ x = /*@returnType=dynamic*/ () =>
+    a. /*@target=A::b*/ b;
+var /*@topType=() -> () -> dynamic*/ y = /*@returnType=() -> dynamic*/ () =>
+    a. /*@target=A::c*/ c;
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.expect
new file mode 100644
index 0000000..b21b78b
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic b = () → dynamic => self::x;
+  field dynamic c = () → dynamic => self::x;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field dynamic a = new self::A::•();
+static field dynamic x = () → dynamic => self::a.b;
+static field dynamic y = () → dynamic => self::a.c;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.outline.expect
new file mode 100644
index 0000000..1455ec3
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.outline.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic b;
+  field dynamic c;
+  constructor •() → void
+    ;
+}
+static field dynamic a;
+static field dynamic x;
+static field dynamic y;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect
new file mode 100644
index 0000000..2268a69
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic b = () → dynamic => self::x;
+  field () → dynamic c = () → dynamic => self::x;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static field self::A a = new self::A::•();
+static field dynamic x = () → dynamic => self::a.{self::A::b};
+static field () → () → dynamic y = () → () → dynamic => self::a.{self::A::c};
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart
new file mode 100644
index 0000000..449ec76
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart
@@ -0,0 +1,28 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class C {
+  int field = 0;
+  int get getter => 0;
+  int function() => 0;
+}
+
+C c = new C();
+var /*@topType=int*/ field_ref = c. /*@target=C::field*/ field;
+var /*@topType=int*/ getter_ref = c. /*@target=C::getter*/ getter;
+var /*@topType=() -> int*/ function_ref = c. /*@target=C::function*/ function;
+var /*@topType=List<int>*/ field_ref_list = /*@typeArgs=int*/ [
+  c. /*@target=C::field*/ field
+];
+var /*@topType=List<int>*/ getter_ref_list = /*@typeArgs=int*/ [
+  c. /*@target=C::getter*/ getter
+];
+var /*@topType=List<() -> int>*/ function_ref_list = /*@typeArgs=() -> int*/ [
+  c. /*@target=C::function*/ function
+];
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.expect
new file mode 100644
index 0000000..403c6de
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.expect
@@ -0,0 +1,22 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int field = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get getter() → core::int
+    return 0;
+  method function() → core::int
+    return 0;
+}
+static field self::C c = new self::C::•();
+static field dynamic field_ref = self::c.field;
+static field dynamic getter_ref = self::c.getter;
+static field dynamic function_ref = self::c.function;
+static field dynamic field_ref_list = <dynamic>[self::c.field];
+static field dynamic getter_ref_list = <dynamic>[self::c.getter];
+static field dynamic function_ref_list = <dynamic>[self::c.function];
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.outline.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.outline.expect
new file mode 100644
index 0000000..77bcf2a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.outline.expect
@@ -0,0 +1,22 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int field;
+  constructor •() → void
+    ;
+  get getter() → core::int
+    ;
+  method function() → core::int
+    ;
+}
+static field self::C c;
+static field dynamic field_ref;
+static field dynamic getter_ref;
+static field dynamic function_ref;
+static field dynamic field_ref_list;
+static field dynamic getter_ref_list;
+static field dynamic function_ref_list;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.expect
new file mode 100644
index 0000000..05da232
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.expect
@@ -0,0 +1,22 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int field = 0;
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  get getter() → core::int
+    return 0;
+  method function() → core::int
+    return 0;
+}
+static field self::C c = new self::C::•();
+static field core::int field_ref = self::c.{self::C::field};
+static field core::int getter_ref = self::c.{self::C::getter};
+static field () → core::int function_ref = self::c.{self::C::function};
+static field core::List<core::int> field_ref_list = <core::int>[self::c.{self::C::field}];
+static field core::List<core::int> getter_ref_list = <core::int>[self::c.{self::C::getter}];
+static field core::List<() → core::int> function_ref_list = <() → core::int>[self::c.{self::C::function}];
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart
new file mode 100644
index 0000000..b5f2ef5
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+bool f() => null;
+
+// Even though x, y, and z form a strongly connected component (each depends on
+// all the others), the circularity is calculated based on the first problematic
+// dependency of each field.  So x's first problematic dependency is y, and y's
+// first problematic dependency is x; therefore x and y are considered to have a
+// circularity, and for error recovery their type is set to `dynamic`.
+// Thereafter, z infers without problems.
+
+var /*@topType=dynamic*/ x = /*@returnType=dynamic*/ () => f() ? y : z;
+var /*@topType=dynamic*/ y = /*@returnType=dynamic*/ () => x;
+var /*@topType=() -> dynamic*/ z = /*@returnType=dynamic*/ () => x;
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.expect
new file mode 100644
index 0000000..5124459
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field dynamic x = () → dynamic => self::f() ? self::y : self::z;
+static field dynamic y = () → dynamic => self::x;
+static field dynamic z = () → dynamic => self::x;
+static method f() → core::bool
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.outline.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.outline.expect
new file mode 100644
index 0000000..136f060
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.outline.expect
@@ -0,0 +1,11 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field dynamic x;
+static field dynamic y;
+static field dynamic z;
+static method f() → core::bool
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect
new file mode 100644
index 0000000..94c4bf4
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static field dynamic x = () → dynamic => self::f() ? self::y : self::z;
+static field dynamic y = () → dynamic => self::x;
+static field () → dynamic z = () → dynamic => self::x;
+static method f() → core::bool
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/tool/fasta b/pkg/front_end/tool/fasta
index 5f1f78f..ab51069 100755
--- a/pkg/front_end/tool/fasta
+++ b/pkg/front_end/tool/fasta
@@ -53,7 +53,7 @@
       ls -d {xcodebuild,out}/${DART_CONFIGURATION}/patched_sdk 2>/dev/null \
         | head -1)
     exec "${DART_VM}" -DDFE_VERBOSE=true \
-         --platform=${PATCHED_SDK_DIR}/platform.dill \
+         --kernel-binaries=${PATCHED_SDK_DIR} \
          --dfe="${REPO_DIR}/utils/kernel-service/kernel-service.dart" "$@"
     ;;
   testing)
diff --git a/pkg/front_end/tool/vm/reload.dart b/pkg/front_end/tool/vm/reload.dart
index 95fc784..087a873 100644
--- a/pkg/front_end/tool/vm/reload.dart
+++ b/pkg/front_end/tool/vm/reload.dart
@@ -2,11 +2,102 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/vm/reload.dart';
+/// A helper library to connect to an existing VM and trigger a hot-reload via
+/// its service protocol.
+///
+/// Usage:
+///
+/// ```
+///     var reloader = new VmReloader();
+///     await reloader.reload(uriToEntryScript);
+///     ...
+///     await reloader.disconnect();
+/// ```
+library front_end.src.vm.reload;
 
-/// Connects to an existing VM's service protocol and issues a hot-reload
-/// request. The VM must have been launched with `--observe` to enable the
-/// service protocol.
+import 'dart:async';
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:stream_channel/stream_channel.dart';
+import 'package:web_socket_channel/io.dart';
+
+/// A user API to trigger hot reloads on a running VM via the VM's service
+/// protocol.
+class VmReloader {
+  /// Port used to connect to the vm service protocol, typically 8181.
+  final int port;
+
+  /// An peer point used to send service protocol messages. The service
+  /// protocol uses JSON rpc on top of web-sockets.
+  json_rpc.Peer get rpc => _rpc ??= _createPeer();
+  json_rpc.Peer _rpc;
+
+  /// The main isolate ID of the running VM. Needed to indicate to the VM which
+  /// isolate to reload.
+  FutureOr<String> get mainId async => _mainId ??= await _computeMainId();
+  String _mainId;
+
+  VmReloader([this.port = 8181]);
+
+  /// Establishes the JSON rpc connection.
+  json_rpc.Peer _createPeer() {
+    StreamChannel socket =
+        new IOWebSocketChannel.connect('ws://127.0.0.1:$port/ws');
+    var peer = new json_rpc.Peer(socket);
+    peer.listen().then((_) {
+      if (VERBOSE_DEBUG) print('connection to vm-service closed');
+      return disconnect();
+    }).catchError((e) {
+      if (VERBOSE_DEBUG) print('error connecting to the vm-service');
+      return disconnect();
+    });
+    return peer;
+  }
+
+  /// Retrieves the ID of the main isolate using the service protocol.
+  Future<String> _computeMainId() async {
+    var vm = await rpc.sendRequest('getVM');
+    var isolates = vm['isolates'];
+    for (var isolate in isolates) {
+      if (isolate['name'].contains(r'$main')) {
+        return isolate['id'];
+      }
+    }
+    return isolates.first['id'];
+  }
+
+  /// Send a request to the VM to reload sources from [entryUri].
+  ///
+  /// This will establish a connection with the VM assuming it is running on the
+  /// local machine and listening on [port] for service protocol requests.
+  ///
+  /// The result is the JSON map received from the reload request.
+  Future<Map> reload(Uri entryUri) async {
+    var id = await mainId;
+    var result = await rpc.sendRequest('reloadSources', {
+      'isolateId': id,
+      'rootLibUri': entryUri.path,
+    });
+    return result;
+  }
+
+  /// Close any connections used to communicate with the VM.
+  Future disconnect() async {
+    if (_rpc == null) return null;
+    this._mainId = null;
+    if (!_rpc.isClosed) {
+      var future = _rpc.close();
+      _rpc = null;
+      return future;
+    }
+    return null;
+  }
+}
+
+const VERBOSE_DEBUG = false;
+
+/// This library can be used as a script as well. It connects to an existing
+/// VM's service protocol and issues a hot-reload request. The VM must have been
+/// launched with `--observe` to enable the service protocol.
 ///
 // TODO(sigmund): provide flags to configure the vm-service port.
 main(List<String> args) async {
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 09fc3e6..be97ec1 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -751,6 +751,8 @@
 type AssertStatement extends Statement {
   Byte tag = 64;
   Expression condition;
+  FileOffset conditionStartOffset;
+  FileOffset conditionEndOffset;
   Option<Expression> message;
 }
 
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index eb988a5..dcc0285 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3161,8 +3161,11 @@
 class AssertStatement extends Statement {
   Expression condition;
   Expression message; // May be null.
+  int conditionStartOffset;
+  int conditionEndOffset;
 
-  AssertStatement(this.condition, [this.message]) {
+  AssertStatement(this.condition,
+      {this.message, this.conditionStartOffset, this.conditionEndOffset}) {
     condition?.parent = this;
     message?.parent = this;
   }
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b730dde..dd0a321 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -935,7 +935,10 @@
       case Tag.EmptyStatement:
         return new EmptyStatement();
       case Tag.AssertStatement:
-        return new AssertStatement(readExpression(), readExpressionOption());
+        return new AssertStatement(readExpression(),
+            conditionStartOffset: readOffset(),
+            conditionEndOffset: readOffset(),
+            message: readExpressionOption());
       case Tag.LabeledStatement:
         var label = new LabeledStatement(null);
         labelStack.add(label);
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 80a31bc..b3634ff 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -867,6 +867,8 @@
   visitAssertStatement(AssertStatement node) {
     writeByte(Tag.AssertStatement);
     writeNode(node.condition);
+    writeOffset(node.conditionStartOffset);
+    writeOffset(node.conditionEndOffset);
     writeOptionalNode(node.message);
   }
 
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 5adc277..b756146 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -113,10 +113,15 @@
   ///
   /// It is possible for two methods to override one another in both directions.
   ///
-  /// Getters and setters are overridden separately.  The [isSetter] callback
-  /// parameter determines which type of access is being overridden.
+  /// By default getters and setters are overridden separately.  The [isSetter]
+  /// callback parameter determines which type of access is being overridden.
+  ///
+  /// However if [crossGettersSetters] is set to `true`, getters might be
+  /// reported as overriding setters, and vice versa - setter overriding
+  /// getters.  The callback should check the [Procedure.kind] property.
   void forEachOverridePair(Class class_,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter));
+      callback(Member declaredMember, Member interfaceMember, bool isSetter),
+      {bool crossGettersSetters: false});
 
   /// This method is invoked by the client after it changed the [classes], and
   /// some of the information that this hierarchy might have cached, is not
@@ -377,7 +382,8 @@
 
   @override
   void forEachOverridePair(Class class_,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter)) {
+      callback(Member declaredMember, Member interfaceMember, bool isSetter),
+      {bool crossGettersSetters: false}) {
     _ClassInfo info = _infoFor[class_];
     for (var supertype in class_.supers) {
       var superclass = supertype.classNode;
@@ -390,6 +396,10 @@
           isSetter: true);
       _reportOverrides(info.declaredSetters, superSetters, callback,
           isSetter: true, onlyAbstract: true);
+      if (crossGettersSetters) {
+        _reportOverrides(info.declaredGettersAndCalls, superSetters, callback);
+        _reportOverrides(info.declaredSetters, superGetters, callback);
+      }
     }
     if (!class_.isAbstract) {
       // If a non-abstract class declares an abstract method M whose
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 6ad1936..1e32f92 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -269,8 +269,10 @@
   }
 
   visitAssertStatement(AssertStatement node) {
-    return new AssertStatement(
-        clone(node.condition), cloneOptional(node.message));
+    return new AssertStatement(clone(node.condition),
+        conditionStartOffset: node.conditionStartOffset,
+        conditionEndOffset: node.conditionEndOffset,
+        message: cloneOptional(node.message));
   }
 
   visitLabeledStatement(LabeledStatement node) {
diff --git a/pkg/kernel/lib/src/incremental_class_hierarchy.dart b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
index 3fcf08e..ce13ecf 100644
--- a/pkg/kernel/lib/src/incremental_class_hierarchy.dart
+++ b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
@@ -86,22 +86,29 @@
 
   @override
   void forEachOverridePair(Class node,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter)) {
+      callback(Member declaredMember, Member interfaceMember, bool isSetter),
+      {bool crossGettersSetters: false}) {
     _ClassInfo info = _getInfo(node);
     for (var supertype in node.supers) {
       var superNode = supertype.classNode;
       var superInfo = _getInfo(superNode);
 
       var superGetters = superInfo.interfaceGettersAndCalls;
+      var superSetters = superInfo.interfaceSetters;
+
       _reportOverrides(info.implementedGettersAndCalls, superGetters, callback);
       _reportOverrides(info.declaredGettersAndCalls, superGetters, callback,
           onlyAbstract: true);
 
-      var superSetters = superInfo.interfaceSetters;
       _reportOverrides(info.implementedSetters, superSetters, callback,
           isSetter: true);
       _reportOverrides(info.declaredSetters, superSetters, callback,
           isSetter: true, onlyAbstract: true);
+
+      if (crossGettersSetters) {
+        _reportOverrides(info.declaredGettersAndCalls, superSetters, callback);
+        _reportOverrides(info.declaredSetters, superGetters, callback);
+      }
     }
     if (!node.isAbstract) {
       // If a non-abstract class declares an abstract method M whose
diff --git a/pkg/kernel/lib/target/flutter.dart b/pkg/kernel/lib/target/flutter.dart
index a0038a0..79b3071 100644
--- a/pkg/kernel/lib/target/flutter.dart
+++ b/pkg/kernel/lib/target/flutter.dart
@@ -10,7 +10,6 @@
 import '../transformations/erasure.dart';
 import '../transformations/mixin_full_resolution.dart' as mix;
 import '../transformations/sanitize_for_vm.dart';
-import '../transformations/setup_builtin_library.dart' as setup_builtin_library;
 import 'targets.dart';
 
 class FlutterTarget extends Target {
@@ -41,14 +40,11 @@
 
         'dart:profiler',
         'dart:typed_data',
-        'dart:_vmservice',
-        'dart:_builtin',
         'dart:nativewrappers',
         'dart:io',
 
         // Required for flutter.
         'dart:ui',
-        'dart:vmservice_sky',
       ];
 
   void performModularTransformationsOnLibraries(
@@ -61,10 +57,6 @@
       {void logger(String msg)}) {
     cont.transformProgram(coreTypes, program);
 
-    // Repair `_getMainClosure()` function in dart:{_builtin,ui} libraries.
-    setup_builtin_library.transformProgram(program);
-    setup_builtin_library.transformProgram(program, libraryUri: 'dart:ui');
-
     if (strongMode) {
       new Erasure().transform(program);
     }
diff --git a/pkg/kernel/lib/target/flutter_fasta.dart b/pkg/kernel/lib/target/flutter_fasta.dart
new file mode 100644
index 0000000..2c280d5
--- /dev/null
+++ b/pkg/kernel/lib/target/flutter_fasta.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+library kernel.target.flutter_fasta;
+
+import '../ast.dart' show Program, Library;
+import '../core_types.dart' show CoreTypes;
+import '../class_hierarchy.dart' show ClassHierarchy;
+
+import '../transformations/mixin_full_resolution.dart' as transformMixins
+    show transformLibraries;
+import '../transformations/continuation.dart' as transformAsync
+    show transformLibraries;
+import '../transformations/erasure.dart' as tranformErasure
+    show transformLibraries;
+
+import 'targets.dart' show TargetFlags;
+import 'flutter.dart' as flutter_target;
+
+class FlutterFastaTarget extends flutter_target.FlutterTarget {
+  FlutterFastaTarget(TargetFlags flags) : super(flags);
+
+  String get name => "flutter_fasta";
+
+  void performModularTransformationsOnLibraries(
+      CoreTypes coreTypes, ClassHierarchy hierarchy, List<Library> libraries,
+      {void logger(String msg)}) {
+    transformMixins.transformLibraries(this, coreTypes, hierarchy, libraries);
+    logger?.call("Transformed mixin applications");
+
+    // TODO(ahe): Don't generate type variables in the first place.
+    if (!strongMode) {
+      tranformErasure.transformLibraries(coreTypes, libraries);
+      logger?.call("Erased type variables in generic methods");
+    }
+
+    // TODO(kmillikin): Make this run on a per-method basis.
+    transformAsync.transformLibraries(coreTypes, libraries);
+    logger?.call("Transformed async methods");
+  }
+
+  void performGlobalTransformations(CoreTypes coreTypes, Program program,
+      {void logger(String msg)}) {}
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index ad94b8e..7389dc0 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -8,6 +8,7 @@
 import '../core_types.dart';
 import '../transformations/treeshaker.dart' show ProgramRoot;
 import 'flutter.dart' show FlutterTarget;
+import 'flutter_fasta.dart' show FlutterFastaTarget;
 import 'vm.dart' show VmTarget;
 import 'vm_fasta.dart' show VmFastaTarget;
 import 'vmcc.dart' show VmClosureConvertedTarget;
@@ -37,6 +38,7 @@
   'vmcc': (TargetFlags flags) => new VmClosureConvertedTarget(flags),
   'vmreify': (TargetFlags flags) => new VmGenericTypesReifiedTarget(flags),
   'flutter': (TargetFlags flags) => new FlutterTarget(flags),
+  'flutter_fasta': (TargetFlags flags) => new FlutterFastaTarget(flags),
 };
 
 Target getTarget(String name, TargetFlags flags) {
diff --git a/pkg/kernel/lib/transformations/closure/context.dart b/pkg/kernel/lib/transformations/closure/context.dart
index 6425bb6..79ceaef 100644
--- a/pkg/kernel/lib/transformations/closure/context.dart
+++ b/pkg/kernel/lib/transformations/closure/context.dart
@@ -6,7 +6,6 @@
 
 import '../../ast.dart'
     show
-        Class,
         Expression,
         NullLiteral,
         StringLiteral,
@@ -116,8 +115,6 @@
       this.converter, this.parent, this.self, this.vectorCreation);
 
   factory LocalContext(ClosureConverter converter, Context parent) {
-    Class contextClass = converter.contextClass;
-    assert(contextClass.constructors.length == 1);
     converter.rewriter.insertContextDeclaration(parent.expression);
 
     return new LocalContext._internal(
diff --git a/pkg/kernel/lib/transformations/closure/converter.dart b/pkg/kernel/lib/transformations/closure/converter.dart
index b4edd6d..e1865f7 100644
--- a/pkg/kernel/lib/transformations/closure/converter.dart
+++ b/pkg/kernel/lib/transformations/closure/converter.dart
@@ -74,7 +74,6 @@
 
 class ClosureConverter extends Transformer {
   final CoreTypes coreTypes;
-  final Class contextClass;
   final Set<VariableDeclaration> capturedVariables;
   final Map<FunctionNode, Set<TypeParameter>> capturedTypeVariables;
   final Map<FunctionNode, VariableDeclaration> thisAccess;
@@ -136,7 +135,7 @@
   Map<TypeParameter, DartType> typeSubstitution =
       const <TypeParameter, DartType>{};
 
-  ClosureConverter(this.coreTypes, ClosureInfo info, this.contextClass)
+  ClosureConverter(this.coreTypes, ClosureInfo info)
       : this.capturedVariables = info.variables,
         this.capturedTypeVariables = info.typeVariables,
         this.thisAccess = info.thisAccess,
@@ -167,7 +166,6 @@
 
   TreeNode visitLibrary(Library node) {
     assert(newLibraryMembers.isEmpty);
-    if (node == contextClass.enclosingLibrary) return node;
 
     currentLibrary = node;
     node = super.visitLibrary(node);
@@ -416,6 +414,7 @@
           // We rename the getter to avoid an indirection in most cases.
           Name oldName = node.name;
           node.name = tearOffName;
+          node.canonicalName?.unbind();
           addGetterForwarder(oldName, node);
         } else if (node.kind == ProcedureKind.Method) {
           addTearOffMethod(tearOffName, node);
diff --git a/pkg/kernel/lib/transformations/closure/info.dart b/pkg/kernel/lib/transformations/closure/info.dart
index acbb3d2..408d37c 100644
--- a/pkg/kernel/lib/transformations/closure/info.dart
+++ b/pkg/kernel/lib/transformations/closure/info.dart
@@ -64,13 +64,19 @@
   /// Maps the names of all instance methods that may be torn off (aka
   /// implicitly closurized) to `${name.name}#get`.
   Map<Name, Name> get tearOffGetterNames {
-    Map<Name, Name> result = <Name, Name>{};
-    for (Name name in declaredInstanceMethodNames) {
-      if (invokedGetters.contains(name)) {
-        result[name] = new Name("${name.name}#get", name.library);
-      }
-    }
-    return result;
+    // TODO(dmitryas): Add support for tear-offs. When added, uncomment this.
+    //
+    // Map<Name, Name> result = <Name, Name>{};
+    // for (Name name in declaredInstanceMethodNames) {
+    //   if (invokedGetters.contains(name)) {
+    //     result[name] = new Name("${name.name}#get", name.library);
+    //   }
+    // }
+    // return result;
+    //
+    // Currently an empty map is returned, so no tear-offs supporting functions
+    // and getters are generated, and no property-get targets are renamed.
+    return <Name, Name>{};
   }
 
   void beginMember(Member member, [FunctionNode function]) {
@@ -94,8 +100,30 @@
   }
 
   visitConstructor(Constructor node) {
+    /// [currentFunction] should be set to [currentMemberFunction] before
+    /// visiting the [FunctionNode] of the constructor, because initializers may
+    /// use constructor parameters and it shouldn't be treated as capturing
+    /// them.  Consider the following code:
+    ///
+    ///     class A {
+    ///       int x;
+    ///       A(int x)  /* [x] is visible in initializers and body. */
+    ///         : this.x = x {  /* Initializer. */
+    ///         /* Constructor body. */
+    ///       }
+    ///     }
+    ///
+    /// Here the parameter shouldn't be captured into a context in the
+    /// initializer.  However, [currentFunction] is `null` if not set, and
+    /// `function[node.variable]` in this case points to the [FunctionNode] of
+    /// the constructor (which is not `null`).  It leads to `x` being treated as
+    /// captured, because it's seen as used outside of the function where it is
+    /// declared.  In turn, it leads to unnecessary context creation and usage.
     beginMember(node, node.function);
-    super.visitConstructor(node);
+    saveCurrentFunction(() {
+      currentFunction = currentMemberFunction;
+      super.visitConstructor(node);
+    });
     endMember();
   }
 
@@ -152,10 +180,12 @@
 
   visitFunctionNode(FunctionNode node) {
     localNames.putIfAbsent(node, computeUniqueLocalName);
-    var saved = currentFunction;
-    currentFunction = node;
-    node.visitChildren(this);
-    currentFunction = saved;
+
+    saveCurrentFunction(() {
+      currentFunction = node;
+      node.visitChildren(this);
+    });
+
     Set<TypeParameter> capturedTypeVariables = typeVariables[node];
     if (capturedTypeVariables != null && !isOuterMostContext) {
       // Propagate captured type variables to enclosing function.
@@ -203,4 +233,13 @@
     invokedGetters.add(node.name);
     super.visitPropertyGet(node);
   }
+
+  saveCurrentFunction(void f()) {
+    var saved = currentFunction;
+    try {
+      f();
+    } finally {
+      currentFunction = saved;
+    }
+  }
 }
diff --git a/pkg/kernel/lib/transformations/closure/mock.dart b/pkg/kernel/lib/transformations/closure/mock.dart
deleted file mode 100644
index bf03651..0000000
--- a/pkg/kernel/lib/transformations/closure/mock.dart
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library kernel.transformations.closure.mock;
-
-import '../../ast.dart'
-    show
-        Arguments,
-        Block,
-        Class,
-        Constructor,
-        ConstructorInvocation,
-        DartType,
-        DynamicType,
-        EmptyStatement,
-        Expression,
-        ExpressionStatement,
-        Field,
-        FieldInitializer,
-        FunctionNode,
-        Initializer,
-        IntLiteral,
-        Library,
-        MethodInvocation,
-        Name,
-        NullLiteral,
-        Procedure,
-        ProcedureKind,
-        Program,
-        PropertyGet,
-        ReturnStatement,
-        Source,
-        Statement,
-        StaticInvocation,
-        Supertype,
-        TreeNode,
-        VariableDeclaration,
-        VariableGet;
-
-import '../../core_types.dart' show CoreTypes;
-
-import '../../frontend/accessors.dart'
-    show
-        Accessor,
-        IndexAccessor,
-        PropertyAccessor,
-        ThisPropertyAccessor,
-        VariableAccessor;
-
-/// TODO(dmitryas): make the "[]=" operator return the value.
-/// Extend the program with this mock:
-///
-///     class Context {
-///       final List list;
-///       var parent;
-///       Context(int i) : list = new List(i);
-///       operator[] (int i) => list[i];
-///       operator[]= (int i, value) {
-///         list[i] = value;
-///       }
-///       Context copy() {
-///         Context c = new Context(list.length);
-///         c.parent = parent;
-///         c.list.setRange(0, list.length, list);
-///         return c;
-///       }
-///     }
-///
-/// Returns the mock.
-Class mockUpContext(CoreTypes coreTypes, Program program) {
-  String fileUri = "dart:mock";
-
-  ///     final List list;
-  Field listField = new Field(new Name("list"),
-      type: coreTypes.listClass.rawType, isFinal: true, fileUri: fileUri);
-  Accessor listFieldAccessor = new ThisPropertyAccessor(
-      listField.name, listField, null, TreeNode.noOffset);
-
-  ///     var parent;
-  Field parentField = new Field(new Name("parent"), fileUri: fileUri);
-  Accessor parentFieldAccessor = new ThisPropertyAccessor(
-      parentField.name, parentField, parentField, TreeNode.noOffset);
-
-  List<Field> fields = <Field>[listField, parentField];
-
-  ///     Context(int i) : list = new List(i);
-  VariableDeclaration iParameter = new VariableDeclaration("i",
-      type: coreTypes.intClass.rawType, isFinal: true);
-
-  // TODO(karlklose): use the default factory when it is exposed again.
-  Procedure listConstructor = coreTypes.listClass.procedures
-      .firstWhere((Procedure p) => p.name.name == 'filled');
-
-  Constructor constructor = new Constructor(
-      new FunctionNode(new EmptyStatement(),
-          positionalParameters: <VariableDeclaration>[iParameter]),
-      name: new Name(""),
-      initializers: <Initializer>[
-        new FieldInitializer(
-            listField,
-            new StaticInvocation(
-                listConstructor,
-                new Arguments(<Expression>[
-                  new VariableAccessor(iParameter, null, TreeNode.noOffset)
-                      .buildSimpleRead(),
-                  new NullLiteral(),
-                ], types: <DartType>[
-                  const DynamicType()
-                ])))
-      ]);
-
-  ///     operator[] (int i) => list[i];
-  iParameter = new VariableDeclaration("i",
-      type: coreTypes.intClass.rawType, isFinal: true);
-  Accessor accessor = IndexAccessor.make(
-      listFieldAccessor.buildSimpleRead(),
-      new VariableAccessor(iParameter, null, TreeNode.noOffset)
-          .buildSimpleRead(),
-      null,
-      null);
-  Procedure indexGet = new Procedure(
-      new Name("[]"),
-      ProcedureKind.Operator,
-      new FunctionNode(new ReturnStatement(accessor.buildSimpleRead()),
-          positionalParameters: <VariableDeclaration>[iParameter]),
-      fileUri: fileUri);
-
-  ///     operator[]= (int i, value) {
-  ///       list[i] = value;
-  ///     }
-  iParameter = new VariableDeclaration("i",
-      type: coreTypes.intClass.rawType, isFinal: true);
-  VariableDeclaration valueParameter =
-      new VariableDeclaration("value", isFinal: true);
-  accessor = IndexAccessor.make(
-      listFieldAccessor.buildSimpleRead(),
-      new VariableAccessor(iParameter, null, TreeNode.noOffset)
-          .buildSimpleRead(),
-      null,
-      null);
-  Expression expression = accessor.buildAssignment(
-      new VariableAccessor(valueParameter, null, TreeNode.noOffset)
-          .buildSimpleRead(),
-      voidContext: true);
-  Procedure indexSet = new Procedure(
-      new Name("[]="),
-      ProcedureKind.Operator,
-      new FunctionNode(new ExpressionStatement(expression),
-          positionalParameters: <VariableDeclaration>[
-            iParameter,
-            valueParameter
-          ]),
-      fileUri: fileUri);
-
-  ///       Context copy() {
-  ///         Context c = new Context(list.length);
-  ///         c.parent = parent;
-  ///         c.list.setRange(0, list.length, list);
-  ///         return c;
-  ///       }
-  VariableDeclaration c = new VariableDeclaration("c",
-      initializer: new ConstructorInvocation(
-          constructor,
-          new Arguments(<Expression>[
-            new PropertyGet(
-                listFieldAccessor.buildSimpleRead(), new Name("length"))
-          ])));
-  Accessor accessCParent = PropertyAccessor.make(
-      new VariableGet(c), parentField.name, parentField, parentField);
-  Accessor accessCList = PropertyAccessor.make(
-      new VariableGet(c), listField.name, listField, null);
-  List<Statement> statements = <Statement>[
-    c,
-    new ExpressionStatement(accessCParent.buildAssignment(
-        parentFieldAccessor.buildSimpleRead(),
-        voidContext: true)),
-    new ExpressionStatement(new MethodInvocation(
-        accessCList.buildSimpleRead(),
-        new Name("setRange"),
-        new Arguments(<Expression>[
-          new IntLiteral(0),
-          new PropertyGet(
-              listFieldAccessor.buildSimpleRead(), new Name("length")),
-          listFieldAccessor.buildSimpleRead()
-        ]))),
-    new ReturnStatement(new VariableGet(c))
-  ];
-  Procedure copy = new Procedure(new Name("copy"), ProcedureKind.Method,
-      new FunctionNode(new Block(statements)),
-      fileUri: fileUri);
-
-  List<Procedure> procedures = <Procedure>[indexGet, indexSet, copy];
-
-  Class contextClass = new Class(
-      name: "Context",
-      supertype: new Supertype(coreTypes.objectClass, const <DartType>[]),
-      constructors: [constructor],
-      fields: fields,
-      procedures: procedures,
-      fileUri: fileUri);
-  Library mock =
-      new Library(Uri.parse(fileUri), name: "mock", classes: [contextClass])
-        ..fileUri = fileUri;
-  program.libraries.add(mock);
-  mock.parent = program;
-  program.uriToSource[mock.fileUri] = new Source(<int>[0], const <int>[]);
-  return contextClass;
-}
diff --git a/pkg/kernel/lib/transformations/closure_conversion.dart b/pkg/kernel/lib/transformations/closure_conversion.dart
index 5588e80..8080997 100644
--- a/pkg/kernel/lib/transformations/closure_conversion.dart
+++ b/pkg/kernel/lib/transformations/closure_conversion.dart
@@ -4,7 +4,7 @@
 
 library kernel.transformations.closure_conversion;
 
-import '../ast.dart' show Class, Program;
+import '../ast.dart' show Program, Library;
 
 import '../core_types.dart' show CoreTypes;
 
@@ -13,14 +13,28 @@
 import 'closure/info.dart' show ClosureInfo;
 
 import 'closure/invalidate_closures.dart';
-import 'closure/mock.dart' show mockUpContext;
 
 Program transformProgram(CoreTypes coreTypes, Program program) {
   var info = new ClosureInfo();
   info.visitProgram(program);
 
-  Class contextClass = mockUpContext(coreTypes, program);
-  var convert = new ClosureConverter(coreTypes, info, contextClass);
+  var convert = new ClosureConverter(coreTypes, info);
   program = convert.visitProgram(program);
   return new InvalidateClosures().visitProgram(program);
 }
+
+void transformLibraries(CoreTypes coreTypes, List<Library> libraries) {
+  var info = new ClosureInfo();
+  for (var library in libraries) {
+    info.visitLibrary(library);
+  }
+
+  var convert = new ClosureConverter(coreTypes, info);
+  for (int i = 0; i < libraries.length; i++) {
+    libraries[i] = convert.visitLibrary(libraries[i]);
+  }
+  var invalidator = new InvalidateClosures();
+  for (int i = 0; i < libraries.length; i++) {
+    invalidator.visitLibrary(libraries[i]);
+  }
+}
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index a05464f..3873b48 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -129,6 +129,13 @@
 
   ClassHierarchy createClassHierarchy(Program program);
 
+  Procedure newEmptyGetter(String name,
+      {DartType returnType: const DynamicType()}) {
+    var body = new Block([new ReturnStatement(new NullLiteral())]);
+    return new Procedure(new Name(name), ProcedureKind.Getter,
+        new FunctionNode(body, returnType: returnType));
+  }
+
   Procedure newEmptyMethod(String name, {bool isAbstract: false}) {
     var body = isAbstract ? null : new Block([]);
     return new Procedure(new Name(name), ProcedureKind.Method,
@@ -136,14 +143,15 @@
         isAbstract: isAbstract);
   }
 
-  Procedure newEmptySetter(String name, {bool abstract: false}) {
+  Procedure newEmptySetter(String name,
+      {bool abstract: false, DartType type: const DynamicType()}) {
     var body = abstract ? null : new Block([]);
     return new Procedure(
         new Name(name),
         ProcedureKind.Setter,
         new FunctionNode(body,
             returnType: const VoidType(),
-            positionalParameters: [new VariableDeclaration('_')]));
+            positionalParameters: [new VariableDeclaration('_', type: type)]));
   }
 
   void setUp() {
@@ -157,6 +165,88 @@
     program.libraries.add(library);
   }
 
+  void test_forEachOverridePair_crossGetterSetter_extends() {
+    var int = coreTypes.intClass.rawType;
+    var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [
+      newEmptySetter('foo', type: int),
+      newEmptyGetter('bar', returnType: int)
+    ]));
+    var b = addClass(new Class(
+        name: 'B',
+        supertype: a.asThisSupertype,
+        procedures: [newEmptyGetter('foo'), newEmptySetter('bar')]));
+
+    _assertTestLibraryText('''
+class A {
+  set foo(core::int _) → void {}
+  get bar() → core::int {
+    return null;
+  }
+}
+class B extends self::A {
+  get foo() → dynamic {
+    return null;
+  }
+  set bar(dynamic _) → void {}
+}
+''');
+
+    // No overrides of getters with getters, or setters with setters.
+    _assertOverridePairs(b, []);
+
+    // Has cross-overrides between getters and setters.
+    _assertOverridePairs(
+        b,
+        [
+          'test::B::foo overrides test::A::foo=',
+          'test::B::bar= overrides test::A::bar'
+        ],
+        crossGettersSetters: true);
+  }
+
+  void test_forEachOverridePair_crossGetterSetter_implements() {
+    var int = coreTypes.intClass.rawType;
+    var double = coreTypes.doubleClass.rawType;
+    var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [
+      newEmptySetter('foo', type: int),
+    ]));
+    var b = addClass(new Class(name: 'B', supertype: objectSuper, procedures: [
+      newEmptySetter('foo', type: double),
+    ]));
+    var c = addClass(new Class(
+        name: 'C',
+        supertype: objectSuper,
+        implementedTypes: [a.asThisSupertype, b.asThisSupertype],
+        procedures: [newEmptyGetter('foo')]));
+
+    _assertTestLibraryText('''
+class A {
+  set foo(core::int _) → void {}
+}
+class B {
+  set foo(core::double _) → void {}
+}
+class C implements self::A, self::B {
+  get foo() → dynamic {
+    return null;
+  }
+}
+''');
+
+    // No overrides of getters with getters, or setters with setters.
+    _assertOverridePairs(c, []);
+
+    // Has cross-overrides between getters and setters.
+    // Even if these overrides are incompatible with each other.
+    _assertOverridePairs(
+        c,
+        [
+          'test::C::foo overrides test::A::foo=',
+          'test::C::foo overrides test::B::foo=',
+        ],
+        crossGettersSetters: true);
+  }
+
   /// 2. A non-abstract member is inherited from a superclass, and in the
   /// context of this class, it overrides an abstract member inheritable through
   /// one of its superinterfaces.
@@ -902,15 +992,25 @@
         new InterfaceType(objectClass));
   }
 
-  void _assertOverridePairs(Class class_, List<String> expected) {
+  void _assertOverridePairs(Class class_, List<String> expected,
+      {bool crossGettersSetters: false}) {
     List<String> overrideDescriptions = [];
     hierarchy.forEachOverridePair(class_,
         (Member declaredMember, Member interfaceMember, bool isSetter) {
-      String declaredName = '$declaredMember${isSetter ? '=': ''}';
-      String interfaceName = '$interfaceMember${isSetter ? '=': ''}';
+      String declaredSuffix;
+      String interfaceSuffix;
+      if (crossGettersSetters) {
+        declaredSuffix = _isSetter(declaredMember) ? '=' : '';
+        interfaceSuffix = _isSetter(interfaceMember) ? '=' : '';
+      } else {
+        declaredSuffix = isSetter ? '=' : '';
+        interfaceSuffix = isSetter ? '=' : '';
+      }
+      String declaredName = '$declaredMember$declaredSuffix';
+      String interfaceName = '$interfaceMember$interfaceSuffix';
       var desc = '$declaredName overrides $interfaceName';
       overrideDescriptions.add(desc);
-    });
+    }, crossGettersSetters: crossGettersSetters);
     expect(overrideDescriptions, unorderedEquals(expected));
   }
 
@@ -936,11 +1036,15 @@
     actualText = actualText.replaceAll('{\n}', '{}');
     actualText = actualText.replaceAll(' extends core::Object', '');
 
-//    if (actualText != expectedText) {
-//      print('-------- Actual --------');
-//      print(actualText + '------------------------');
-//    }
+    if (actualText != expectedText) {
+      print('-------- Actual --------');
+      print(actualText + '------------------------');
+    }
 
     expect(actualText, expectedText);
   }
+
+  static bool _isSetter(Member member) {
+    return member is Procedure && member.kind == ProcedureKind.Setter;
+  }
 }
diff --git a/pkg/kernel/test/closures/suite.dart b/pkg/kernel/test/closures/suite.dart
index 3f66f33..6e246fa 100644
--- a/pkg/kernel/test/closures/suite.dart
+++ b/pkg/kernel/test/closures/suite.dart
@@ -16,7 +16,7 @@
 import 'package:front_end/src/fasta/testing/patched_sdk_location.dart'
     show computePatchedSdk;
 
-import 'package:kernel/ast.dart' show Program;
+import 'package:kernel/ast.dart' show Program, Library;
 
 import 'package:kernel/transformations/closure_conversion.dart'
     as closure_conversion;
@@ -133,7 +133,9 @@
       Program program, ClosureConversionContext testContext) async {
     try {
       CoreTypes coreTypes = new CoreTypes(program);
-      program = closure_conversion.transformProgram(coreTypes, program);
+      Library library = program.libraries
+          .firstWhere((Library library) => library.importUri.scheme != "dart");
+      closure_conversion.transformLibraries(coreTypes, <Library>[library]);
       return pass(program);
     } catch (e, s) {
       return crash(e, s);
diff --git a/pkg/kernel/testcases/closures/closure_in_constructor.dart.expect b/pkg/kernel/testcases/closures/closure_in_constructor.dart.expect
index cba5c83..c8fea8f 100644
--- a/pkg/kernel/testcases/closures/closure_in_constructor.dart.expect
+++ b/pkg/kernel/testcases/closures/closure_in_constructor.dart.expect
@@ -5,7 +5,7 @@
 class C1 extends core::Object {
   field dynamic x;
   constructor •(dynamic y) → void
-    : self::C1::x = let final Vector #context = MakeVector(2) in let dynamic #t1 = #context[1] = y in MakeClosure<() → dynamic>(self::closure#C1##function, #context), super core::Object::•()
+    : self::C1::x = let final Vector #context = MakeVector(2) in let dynamic #t1 = #context[1] = y in MakeClosure<() → dynamic>(self::closure#C1#function#function, #context), super core::Object::•()
     ;
 }
 class C2 extends core::Object {
@@ -21,7 +21,7 @@
   new self::C1::•("hest").x();
   new self::C2::•("naebdyr").x();
 }
-static method closure#C1##function(Vector #contextParameter) → dynamic {
+static method closure#C1#function#function(Vector #contextParameter) → dynamic {
   return core::print("Hello ${#contextParameter[1]}");
 }
 static method closure#C2#function#function(Vector #contextParameter) → void {
diff --git a/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart b/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart
new file mode 100644
index 0000000..0be4a67
--- /dev/null
+++ b/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart
@@ -0,0 +1,19 @@
+// 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.
+
+// The purpose of this test is to detect that no unnecessary contexts are
+// created when a constructor parameter is used in its field initializers.  No
+// contexts should be created either in the initializer or in the constructor
+// body.
+
+class X {}
+
+class A {
+  X x;
+  A(this.x) {}
+}
+
+main() {
+  A a = new A(new X());
+}
diff --git a/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart.expect b/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart.expect
new file mode 100644
index 0000000..a029947
--- /dev/null
+++ b/pkg/kernel/testcases/closures/contexts_in_field_initializers.dart.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class A extends core::Object {
+  field self::X x;
+  constructor •(self::X x) → void
+    : self::A::x = x, super core::Object::•() {}
+}
+static method main() → dynamic {
+  self::A a = new self::A::•(new self::X::•());
+}
diff --git a/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart b/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart
new file mode 100644
index 0000000..528b76b
--- /dev/null
+++ b/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to detect that no unnecessary contexts are
+// created when a constructor parameter is used in its super initializer.  No
+// contexts should be created either in the initializer list or in the
+// constructor body.
+
+class X {}
+
+class Y {}
+
+class A {
+  X x;
+  Y y;
+  A(this.x, this.y);
+}
+
+class B extends A {
+  B(X x, Y y) : super(x, y) {}
+}
+
+main() {
+  B b = new B(new X(), new Y());
+}
diff --git a/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart.expect b/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart.expect
new file mode 100644
index 0000000..27d6de8
--- /dev/null
+++ b/pkg/kernel/testcases/closures/contexts_in_super_initializers.dart.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class Y extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class A extends core::Object {
+  field self::X x;
+  field self::Y y;
+  constructor •(self::X x, self::Y y) → void
+    : self::A::x = x, self::A::y = y, super core::Object::•()
+    ;
+}
+class B extends self::A {
+  constructor •(self::X x, self::Y y) → void
+    : super self::A::•(x, y) {}
+}
+static method main() → dynamic {
+  self::B b = new self::B::•(new self::X::•(), new self::Y::•());
+}
diff --git a/pkg/kernel/testcases/closures/instance_tear_off.dart.expect b/pkg/kernel/testcases/closures/instance_tear_off.dart.expect
index e23bec5..740fa96 100644
--- a/pkg/kernel/testcases/closures/instance_tear_off.dart.expect
+++ b/pkg/kernel/testcases/closures/instance_tear_off.dart.expect
@@ -22,26 +22,6 @@
   method d(dynamic x, {dynamic y = 2}) → dynamic {
     return x.+(y);
   }
-  method a#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<() → dynamic>(self::closure#C#a, #context);
-  }
-  method b#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic) → dynamic>(self::closure#C#b, #context);
-  }
-  method c#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic, [dynamic]) → dynamic>(self::closure#C#c, #context);
-  }
-  method d#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic, {y: dynamic}) → dynamic>(self::closure#C#d, #context);
-  }
 }
 class D<T extends core::Object> extends core::Object {
   field dynamic f = MakeClosure<() → core::String>(self::closure#D#f#function, null);
@@ -63,26 +43,6 @@
   method d(dynamic x, {dynamic y = 2}) → dynamic {
     return x.+(y);
   }
-  method a#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<() → dynamic>(self::closure#D#a, #context);
-  }
-  method b#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic) → dynamic>(self::closure#D#b, #context);
-  }
-  method c#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic, [dynamic]) → dynamic>(self::closure#D#c, #context);
-  }
-  method d#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(dynamic, {y: dynamic}) → dynamic>(self::closure#D#d, #context);
-  }
 }
 class E<T extends core::Object> extends core::Object {
   field dynamic f = MakeClosure<() → core::String>(self::closure#E#f#function, null);
@@ -104,26 +64,6 @@
   method d(self::E::T x, {self::E::T y = 2}) → dynamic {
     return x.+(y);
   }
-  method a#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<() → dynamic>(self::closure#E#a, #context);
-  }
-  method b#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(self::E::T) → dynamic>(self::closure#E#b, #context);
-  }
-  method c#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(self::E::T, [self::E::T]) → dynamic>(self::closure#E#c, #context);
-  }
-  method d#get() → dynamic {
-    final Vector #context = MakeVector(2);
-    #context[1] = this;
-    return MakeClosure<(self::E::T, {y: self::E::T}) → dynamic>(self::closure#E#d, #context);
-  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   core::print("Expecting '${expected}' and got '${actual}'");
@@ -138,17 +78,17 @@
   self::expect("g(42)", o.g(42));
   self::expect("g(42)", o.g.call(42));
   self::expect("a", o.a());
-  self::expect("a", o.a#get().call());
+  self::expect("a", o.a.call());
   self::expect(42, o.b(42));
-  self::expect(42, o.b#get().call(42));
+  self::expect(42, o.b.call(42));
   self::expect(42, o.c(40));
-  self::expect(42, o.c#get().call(40));
+  self::expect(42, o.c.call(40));
   self::expect(87, o.c(80, 7));
-  self::expect(87, o.c#get().call(80, 7));
+  self::expect(87, o.c.call(80, 7));
   self::expect(42, o.d(40));
-  self::expect(42, o.d#get().call(40));
+  self::expect(42, o.d.call(40));
   self::expect(87, o.d(80, y: 7));
-  self::expect(87, o.d#get().call(80, y: 7));
+  self::expect(87, o.d.call(80, y: 7));
 }
 static method main(dynamic arguments) → dynamic {
   self::test(new self::C::•());
@@ -158,42 +98,18 @@
 static method closure#C#g#function(Vector #contextParameter, dynamic x) → core::String {
   return "g(${x})";
 }
-static method closure#C#a(Vector #contextParameter) → dynamic
-  return (#contextParameter[1]).{self::C::a}();
-static method closure#C#b(Vector #contextParameter, dynamic x) → dynamic
-  return (#contextParameter[1]).{self::C::b}(x);
-static method closure#C#c(Vector #contextParameter, dynamic x, [dynamic y = 2]) → dynamic
-  return (#contextParameter[1]).{self::C::c}(x, y);
-static method closure#C#d(Vector #contextParameter, dynamic x, {dynamic y = 2}) → dynamic
-  return (#contextParameter[1]).{self::C::d}(x, y: y);
 static method closure#C#f#function(Vector #contextParameter) → core::String {
   return "f";
 }
 static method closure#D#g#function(Vector #contextParameter, dynamic x) → core::String {
   return "g(${x})";
 }
-static method closure#D#a(Vector #contextParameter) → dynamic
-  return (#contextParameter[1]).{self::D::a}();
-static method closure#D#b(Vector #contextParameter, dynamic x) → dynamic
-  return (#contextParameter[1]).{self::D::b}(x);
-static method closure#D#c(Vector #contextParameter, dynamic x, [dynamic y = 2]) → dynamic
-  return (#contextParameter[1]).{self::D::c}(x, y);
-static method closure#D#d(Vector #contextParameter, dynamic x, {dynamic y = 2}) → dynamic
-  return (#contextParameter[1]).{self::D::d}(x, y: y);
 static method closure#D#f#function(Vector #contextParameter) → core::String {
   return "f";
 }
 static method closure#E#g#function(Vector #contextParameter, dynamic x) → core::String {
   return "g(${x})";
 }
-static method closure#E#a(Vector #contextParameter) → dynamic
-  return (#contextParameter[1]).{self::E::a}();
-static method closure#E#b(Vector #contextParameter, dynamic x) → dynamic
-  return (#contextParameter[1]).{self::E::b}(x);
-static method closure#E#c(Vector #contextParameter, dynamic x, [dynamic y = 2]) → dynamic
-  return (#contextParameter[1]).{self::E::c}(x, y);
-static method closure#E#d(Vector #contextParameter, dynamic x, {dynamic y = 2}) → dynamic
-  return (#contextParameter[1]).{self::E::d}(x, y: y);
 static method closure#E#f#function(Vector #contextParameter) → core::String {
   return "f";
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 9d51b77..af9d397 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -14,6 +14,8 @@
 analysis_server/tool/spec/check_all_test: Skip  # Issue 29133
 analyzer_plugin/tool/spec/check_all_test: Skip  # Issue 29133
 analyzer/tool/summary/check_test: Skip  # Issue 29133
+
+analysis_server/test/analysis_server_test: Slow, Pass
 analyzer/test/generated/compile_time_error_code_driver_test: Slow, Pass
 analyzer/test/generated/non_error_resolver_driver_test: Slow, Pass
 analyzer/test/generated/static_warning_code_driver_test: Slow, Pass
@@ -106,6 +108,7 @@
 analyzer/test/generated/source_factory_test: RuntimeError # Issue 26828
 kernel/test/baseline_spec_mode_test: RuntimeError # Issue 28243
 kernel/test/baseline_strong_mode_test: RuntimeError # Issue 28243
+analyzer/tool/task_dependency_graph/check_test: Slow, Pass
 
 [ $compiler == dart2js ]
 analysis_server/test/integration: SkipByDesign # Analysis server integration tests don't make sense to run under dart2js, since the code under test always runs in the Dart vm as a subprocess.
diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart
index 296a023..ec67cd4 100644
--- a/pkg/testing/lib/src/analyze.dart
+++ b/pkg/testing/lib/src/analyze.dart
@@ -237,12 +237,6 @@
     await for (AnalyzerDiagnostic diagnostic in diagnostics) {
       if (diagnostic.uri != null) {
         String path = toFilePath(diagnostic.uri);
-        if (diagnostic.code.startsWith("STRONG_MODE") &&
-            (path.startsWith("pkg/compiler/") ||
-                path.startsWith("tests/compiler/dart2js/"))) {
-          // Hack to work around dart2js not being strong-mode clean.
-          continue;
-        }
         if (!filesToAnalyze.contains(path)) continue;
       }
       String message = "$diagnostic";
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index dad0d89..e4eec29 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -19,11 +19,6 @@
 // dart:_builtin library.
 bool _setupCompleted = false;
 
-// The root library (aka the script) is imported into this library. The
-// standalone embedder uses this to lookup the main entrypoint in the
-// root library's namespace.
-Function _getMainClosure() => main;
-
 // 'print' implementation.
 // The standalone embedder registers the closurized _print function with the
 // dart:core library.
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 45d81ae..9b37e98 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -5,12 +5,16 @@
 #include "bin/dfe.h"
 #include "bin/dartutils.h"
 #include "bin/error_exit.h"
+#include "bin/file.h"
 
 #include "vm/kernel.h"
 
 namespace dart {
 namespace bin {
 
+const char kPlatformBinaryName[] = "platform.dill";
+
+
 DFE::DFE()
     : frontend_filename_(NULL),
       platform_binary_filename_(NULL),
@@ -19,13 +23,29 @@
 
 DFE::~DFE() {
   frontend_filename_ = NULL;
-  platform_binary_filename_ = NULL;
+
+  if (platform_binary_filename_ != NULL) {
+    delete platform_binary_filename_;
+    platform_binary_filename_ = NULL;
+  }
+
   if (kernel_platform_ != NULL) {
     delete reinterpret_cast<kernel::Program*>(kernel_platform_);
+    kernel_platform_ = NULL;
   }
-  kernel_platform_ = NULL;
 }
 
+
+void DFE::SetKernelBinaries(const char* name) {
+  intptr_t len = snprintf(NULL, 0, "%s%s%s", name, File::PathSeparator(),
+                          kPlatformBinaryName) +
+                 1;
+  platform_binary_filename_ = new char[len];
+  snprintf(platform_binary_filename_, len, "%s%s%s", name,
+           File::PathSeparator(), kPlatformBinaryName);
+}
+
+
 Dart_Handle DFE::ReloadScript(Dart_Isolate isolate, const char* url_string) {
   ASSERT(!Dart_IsServiceIsolate(isolate) && !Dart_IsKernelIsolate(isolate));
   // First check if the URL points to a Kernel IR file in which case we
@@ -85,15 +105,7 @@
 
 
 void* DFE::ReadPlatform() {
-  const uint8_t* buffer = NULL;
-  intptr_t buffer_length = -1;
-  bool result =
-      TryReadKernelFile(platform_binary_filename_, &buffer, &buffer_length);
-  if (result) {
-    kernel_platform_ = Dart_ReadKernelBinary(buffer, buffer_length);
-    return kernel_platform_;
-  }
-  return NULL;
+  return kernel_platform_ = ReadScript(platform_binary_filename_);
 }
 
 
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index 2f61329..581c14a 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -25,9 +25,9 @@
   const char* platform_binary_filename() const {
     return platform_binary_filename_;
   }
-  void set_platform_binary_filename(const char* name) {
-    platform_binary_filename_ = name;
-  }
+
+  void SetKernelBinaries(const char* name);
+
   bool UsePlatformBinary() const { return platform_binary_filename_ != NULL; }
 
   void* kernel_platform() const { return kernel_platform_; }
@@ -66,7 +66,7 @@
                          intptr_t* kernel_ir_size);
 
   const char* frontend_filename_;
-  const char* platform_binary_filename_;
+  char* platform_binary_filename_;
   void* kernel_platform_;
 
   DISALLOW_COPY_AND_ASSIGN(DFE);
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index ef42a31..ad5cb45 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -507,22 +507,15 @@
 
 
 const char* File::GetCanonicalPath(const char* pathname) {
-  // TODO(MG-425): realpath() is not implemented.
-#if 0
   char* abs_path = NULL;
   if (pathname != NULL) {
     char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1);
     ASSERT(resolved_path != NULL);
-    do {
-      abs_path = realpath(pathname, resolved_path);
-    } while ((abs_path == NULL) && (errno == EINTR));
+    abs_path = realpath(pathname, resolved_path);
     ASSERT((abs_path == NULL) || IsAbsolutePath(abs_path));
     ASSERT((abs_path == NULL) || (abs_path == resolved_path));
   }
   return abs_path;
-#else
-  return pathname;
-#endif
 }
 
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 61d76f7..c969db8 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -381,13 +381,13 @@
 }
 
 
-static bool ProcessPlatformOption(const char* filename,
-                                  CommandLineOptions* vm_options) {
-  ASSERT(filename != NULL);
-  if (filename[0] == '\0') {
+static bool ProcessKernelBinariesOption(const char* dirname,
+                                        CommandLineOptions* vm_options) {
+  ASSERT(dirname != NULL);
+  if (dirname[0] == '\0') {
     return false;
   }
-  dfe.set_platform_binary_filename(filename);
+  dfe.SetKernelBinaries(dirname);
   return true;
 }
 #endif
@@ -616,7 +616,7 @@
     {"--parse_all", ProcessParseAllOption},
 #if !defined(DART_PRECOMPILED_RUNTIME)
     {"--dfe=", ProcessFrontendOption},
-    {"--platform=", ProcessPlatformOption},
+    {"--kernel-binaries=", ProcessKernelBinariesOption},
 #endif
     {"--enable-vm-service", ProcessEnableVmServiceOption},
     {"--disable-service-origin-check", ProcessDisableServiceOriginCheckOption},
@@ -1487,7 +1487,6 @@
 
     if (gen_snapshot_kind == kAppAOT) {
       Dart_QualifiedFunctionName standalone_entry_points[] = {
-          {"dart:_builtin", "::", "_getMainClosure"},
           {"dart:_builtin", "::", "_getPrintClosure"},
           {"dart:_builtin", "::", "_getUriBaseClosure"},
           {"dart:_builtin", "::", "_libraryFilePath"},
@@ -1571,13 +1570,16 @@
         CHECK_RESULT(result);
       }
 
-      // The helper function _getMainClosure creates a closure for the main
-      // entry point which is either explicitly or implictly exported from the
-      // root library.
+      // Create a closure for the main entry point which is in the exported
+      // namespace of the root library or invoke a getter of the same name
+      // in the exported namespace and return the resulting closure.
       Dart_Handle main_closure =
-          Dart_Invoke(isolate_data->builtin_lib(),
-                      Dart_NewStringFromCString("_getMainClosure"), 0, NULL);
+          Dart_GetClosure(root_lib, Dart_NewStringFromCString("main"));
       CHECK_RESULT(main_closure);
+      if (!Dart_IsClosure(main_closure)) {
+        ErrorExit(kErrorExitCode,
+                  "Unable to find 'main' in root library '%s'\n", script_name);
+      }
 
       // Call _startIsolate in the isolate library to enable dispatching the
       // initial startup message.
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index 8fd4ef7..674d94f 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -65,7 +65,7 @@
   static void SetExecutableName(const char* executable_name) {
     executable_name_ = executable_name;
   }
-  static const char* GetExecutableName() { return executable_name_; }
+  static const char* GetExecutableName();
   static const char* GetResolvedExecutableName() {
     if (resolved_executable_name_ == NULL) {
       // Try to resolve the executable path using platform specific APIs.
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index b72e3b8..cc21f19 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -89,6 +89,11 @@
 }
 
 
+const char* Platform::GetExecutableName() {
+  return executable_name_;
+}
+
+
 const char* Platform::ResolveExecutablePath() {
   return NULL;
 }
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 1225cef..cf6e523 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -7,8 +7,11 @@
 
 #include "bin/platform.h"
 
-#include <string.h>  // NOLINT
-#include <unistd.h>  // NOLINT
+#include <magenta/process.h>
+#include <magenta/status.h>
+#include <magenta/syscalls.h>
+#include <string.h>
+#include <unistd.h>
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -79,42 +82,54 @@
 }
 
 
+const char* Platform::GetExecutableName() {
+  if (executable_name_ != NULL) {
+    return executable_name_;
+  }
+  char* name = DartUtils::ScopedCString(MX_MAX_NAME_LEN);
+  mx_status_t status = mx_object_get_property(mx_process_self(), MX_PROP_NAME,
+                                              name, MX_MAX_NAME_LEN);
+  if (status != MX_OK) {
+    return NULL;
+  }
+  return name;
+}
+
+
 const char* Platform::ResolveExecutablePath() {
-  // The string used on the command line to spawn the executable is in argv_[0].
-  // If that string is a relative or absolute path, i.e. it contains a '/', then
-  // we make the path absolute if it is not already and return it. If argv_[0]
-  // does not contain a '/', we assume it is a program whose location is
-  // resolved via the PATH environment variable, and search for it using the
-  // paths found there.
-  const char* path = getenv("PATH");
-  if ((strchr(argv_[0], '/') != NULL) || (path == NULL)) {
-    if (argv_[0][0] == '/') {
-      return File::GetCanonicalPath(argv_[0]);
-    } else {
-      char* result = DartUtils::ScopedCString(PATH_MAX + 1);
-      char* cwd = DartUtils::ScopedCString(PATH_MAX + 1);
-      getcwd(cwd, PATH_MAX);
-      snprintf(result, PATH_MAX, "%s/%s", cwd, argv_[0]);
-      result[PATH_MAX] = '\0';
-      ASSERT(File::Exists(result));
-      return File::GetCanonicalPath(result);
+  const char* executable_name = Platform::GetExecutableName();
+  if (executable_name == NULL) {
+    return NULL;
+  }
+  if ((executable_name[0] == '/') && File::Exists(executable_name)) {
+    return File::GetCanonicalPath(executable_name);
+  }
+  if (strchr(executable_name, '/') != NULL) {
+    const char* result = File::GetCanonicalPath(executable_name);
+    if (File::Exists(result)) {
+      return result;
     }
   } else {
+    const char* path = getenv("PATH");
+    if (path == NULL) {
+      // If PATH isn't set, make some guesses about where we should look.
+      path = "/system/bin:/system/apps:/boot/bin";
+    }
     char* pathcopy = DartUtils::ScopedCopyCString(path);
     char* result = DartUtils::ScopedCString(PATH_MAX + 1);
     char* save = NULL;
     while ((pathcopy = strtok_r(pathcopy, ":", &save)) != NULL) {
-      snprintf(result, PATH_MAX, "%s/%s", pathcopy, argv_[0]);
+      snprintf(result, PATH_MAX, "%s/%s", pathcopy, executable_name);
       result[PATH_MAX] = '\0';
       if (File::Exists(result)) {
         return File::GetCanonicalPath(result);
       }
       pathcopy = NULL;
     }
-    // Couldn't find it. This causes null to be returned for
-    // Platform.resovledExecutable.
-    return NULL;
   }
+  // Couldn't find it. This causes null to be returned for
+  // Platform.resovledExecutable.
+  return NULL;
 }
 
 
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 4e450f1..97a9437 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -114,6 +114,11 @@
 }
 
 
+const char* Platform::GetExecutableName() {
+  return executable_name_;
+}
+
+
 const char* Platform::ResolveExecutablePath() {
   return File::LinkTarget("/proc/self/exe");
 }
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 782a83c..a03e8b9 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -192,6 +192,11 @@
 }
 
 
+const char* Platform::GetExecutableName() {
+  return executable_name_;
+}
+
+
 const char* Platform::ResolveExecutablePath() {
   // Get the required length of the buffer.
   uint32_t path_size = 0;
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index af38455..a15f437 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -259,6 +259,11 @@
 }
 
 
+const char* Platform::GetExecutableName() {
+  return executable_name_;
+}
+
+
 const char* Platform::ResolveExecutablePath() {
   // GetModuleFileNameW cannot directly provide information on the
   // required buffer size, so start out with a buffer large enough to
diff --git a/runtime/bin/vmservice_sdk/lib/libraries.json b/runtime/bin/vmservice_sdk/lib/libraries.json
new file mode 100644
index 0000000..1c46483
--- /dev/null
+++ b/runtime/bin/vmservice_sdk/lib/libraries.json
@@ -0,0 +1,6 @@
+{
+  "libraries": {
+    "vmservice_io": "../../vmservice/vmservice_io.dart",
+    "_vmservice": "../../../../sdk/lib/vmservice/vmservice.dart"
+  }
+}
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 51b9603..2e8b864 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1611,6 +1611,20 @@
  */
 DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj, double* value);
 
+/**
+ * Returns a closure of top level function 'function_name' in the exported
+ * namespace of specified 'library'. If a top level function 'function_name'
+ * does not exist, looks for a top level getter 'function_name' and invokes
+ * it and returns the object returned by the getter.
+ *
+ * \param library Library object
+ * \param function_name Name of the top level function
+ *
+ * \return A valid Dart instance if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_GetClosure(Dart_Handle library,
+                                        Dart_Handle function_name);
+
 
 /*
  * ========
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 4690ba2..b9d1cca 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -55,8 +55,8 @@
 
   String toString() {
     if (_url == null) {
-      if (message == null) return _failedAssertion;
-      return "'$_failedAssertion': $_messageString";
+      if (message == null) return _failedAssertion?.trim();
+      return "'${_failedAssertion?.trim()}': $_messageString";
     }
     var columnInfo = "";
     if (_column > 0) {
diff --git a/runtime/observatory/.analysis_options b/runtime/observatory/.analysis_options
index c3f150b..53f5fea 100644
--- a/runtime/observatory/.analysis_options
+++ b/runtime/observatory/.analysis_options
@@ -3,7 +3,10 @@
     dead_code: ignore
     unused_local_variable: ignore
   exclude:
+    - lib/src/models/objects/function.dart
     - tests/service/bad_reload/v2/main.dart
     - tests/service/complex_reload/v2/main.dart
     - tests/service/developer_extension_test.dart
+    - tests/service/evaluate_activation_in_method_class_test.dart
     - tests/service/get_isolate_after_language_error_test.dart
+    - tests/service/pause_on_unhandled_async_exceptions_test.dart
diff --git a/runtime/observatory/lib/service_html.dart b/runtime/observatory/lib/service_html.dart
index f4b166e..ddc42f5 100644
--- a/runtime/observatory/lib/service_html.dart
+++ b/runtime/observatory/lib/service_html.dart
@@ -40,7 +40,7 @@
     FileReader fileReader = new FileReader();
     fileReader.readAsArrayBuffer(data);
     return fileReader.onLoadEnd.first.then((e) {
-      var result = fileReader.result;
+      Uint8List result = fileReader.result as Uint8List;
       return new ByteData.view(
           result.buffer, result.offsetInBytes, result.length);
     });
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
index df855d4..77e1a72 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -205,11 +205,11 @@
       HtmlElement element, M.FunctionCallTreeNode item, int depth) {
     element.children[0].text =
         Utils.formatSize(item.inclusiveNativeAllocations);
-    element.children[0].title = 'memory allocated from resulting calls: ' +
+    element.children[0].title = 'memory allocated from resulting calls: '
         '${item.inclusiveNativeAllocations}B';
     element.children[1].text =
         Utils.formatSize(item.exclusiveNativeAllocations);
-    element.children[1].title = 'memory allocated during execution: ' +
+    element.children[1].title = 'memory allocated during execution: '
         '${item.exclusiveNativeAllocations}B';
     _updateLines(element.children[2].children, depth);
     if (item.children.isNotEmpty) {
@@ -248,11 +248,11 @@
       HtmlElement element, M.CodeCallTreeNode item, int depth) {
     element.children[0].text =
         Utils.formatSize(item.inclusiveNativeAllocations);
-    element.children[0].title = 'memory allocated from resulting calls: ' +
+    element.children[0].title = 'memory allocated from resulting calls: '
         '${item.inclusiveNativeAllocations}B';
     element.children[1].text =
         Utils.formatSize(item.exclusiveNativeAllocations);
-    element.children[1].title = 'memory allocated during execution: ' +
+    element.children[1].title = 'memory allocated during execution: '
         '${item.exclusiveNativeAllocations}B';
     _updateLines(element.children[2].children, depth);
     if (item.children.isNotEmpty) {
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 2cb465c..0cfbcac 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -1690,8 +1690,7 @@
     switch (event.kind) {
       case S.ServiceEvent.kVMUpdate:
         var vm = event.owner;
-        console.print(
-            "VM ${(vm as CommonWebSocketVM).target.networkAddress} renamed to '${vm.name}'");
+        console.print("VM ${vm.displayName} renamed to '${vm.name}'");
         break;
 
       case S.ServiceEvent.kIsolateStart:
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index 39312a3..716dc78 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -376,7 +376,7 @@
             new DivElement()
               ..classes = ['indent']
               ..title = '${t.zoneHighWatermark}B'
-              ..text = 'zone capacity high watermark ' +
+              ..text = 'zone capacity high watermark '
                   '${Utils.formatSize(t.zoneHighWatermark)}',
             new DivElement()
               ..classes = ['indent']
diff --git a/runtime/observatory/lib/src/elements/metric/graph.dart b/runtime/observatory/lib/src/elements/metric/graph.dart
index 4286f55..c39d29c 100644
--- a/runtime/observatory/lib/src/elements/metric/graph.dart
+++ b/runtime/observatory/lib/src/elements/metric/graph.dart
@@ -71,7 +71,7 @@
 
     var message = 'current: $current';
     if (min != null) {
-      message = 'min: $min, ' + message;
+      message = 'min: $min, $message';
     }
     if (max != null) {
       message = message + ', max: $max';
diff --git a/runtime/observatory/lib/src/models/objects/source_location.dart b/runtime/observatory/lib/src/models/objects/source_location.dart
index 1e1188b..8a03f13 100644
--- a/runtime/observatory/lib/src/models/objects/source_location.dart
+++ b/runtime/observatory/lib/src/models/objects/source_location.dart
@@ -8,21 +8,21 @@
   /// The script containing the source location.
   ScriptRef get script;
 
-  /// The last token of the location if this is a range. [optional]
+  /// [optional] The first token of the location.
   int get tokenPos;
 }
 
 abstract class SourceLocation implements Location {
-  /// The last token of the location if this is a range.
+  /// The first token of the location.
   int get tokenPos;
 
-  /// The last token of the location if this is a range. [optional]
+  /// [optional] The last token of the location if this is a range.
   int get endTokenPos;
 }
 
 abstract class UnresolvedSourceLocation implements Location {
-  // [optional] The uri of the script containing the source location if the
-  // script has yet to be loaded.
+  /// [optional] The uri of the script containing the source location if the
+  /// script has yet to be loaded.
   String get scriptUri;
 
   /// [optional] An approximate line number for the source location. This may
diff --git a/runtime/observatory/tests/service/async_next_test.dart b/runtime/observatory/tests/service/async_next_test.dart
index e1aafaf..5afefd1 100644
--- a/runtime/observatory/tests/service/async_next_test.dart
+++ b/runtime/observatory/tests/service/async_next_test.dart
@@ -4,13 +4,12 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const int LINE_A = 19;
-const int LINE_B = 20;
-const int LINE_C = 21;
+const int LINE_A = 18;
+const int LINE_B = 19;
+const int LINE_C = 20;
 
 foo() async {}
 
diff --git a/runtime/observatory/tests/service/async_single_step_exception_test.dart b/runtime/observatory/tests/service/async_single_step_exception_test.dart
index 07553e5..b8213dc 100644
--- a/runtime/observatory/tests/service/async_single_step_exception_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_exception_test.dart
@@ -4,17 +4,16 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 20;
-const LINE_B = 21;
-const LINE_C = 27;
-const LINE_D = 29;
-const LINE_E = 32;
-const LINE_F = 35;
-const LINE_G = 37;
+const LINE_A = 19;
+const LINE_B = 20;
+const LINE_C = 26;
+const LINE_D = 28;
+const LINE_E = 31;
+const LINE_F = 34;
+const LINE_G = 36;
 
 helper() async {
   print('helper'); // LINE_A.
diff --git a/runtime/observatory/tests/service/async_single_step_into_test.dart b/runtime/observatory/tests/service/async_single_step_into_test.dart
index 04b0875..3821890 100644
--- a/runtime/observatory/tests/service/async_single_step_into_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_into_test.dart
@@ -4,14 +4,13 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 17;
-const LINE_B = 18;
-const LINE_C = 23;
-const LINE_D = 24;
+const LINE_A = 16;
+const LINE_B = 17;
+const LINE_C = 22;
+const LINE_D = 23;
 
 helper() async {
   print('helper'); // LINE_A.
diff --git a/runtime/observatory/tests/service/async_single_step_out_test.dart b/runtime/observatory/tests/service/async_single_step_out_test.dart
index 6ad5e78..6671083 100644
--- a/runtime/observatory/tests/service/async_single_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_out_test.dart
@@ -4,15 +4,14 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 18;
-const LINE_B = 19;
-const LINE_C = 24;
-const LINE_D = 25;
-const LINE_E = 26;
+const LINE_A = 17;
+const LINE_B = 18;
+const LINE_C = 23;
+const LINE_D = 24;
+const LINE_E = 25;
 
 helper() async {
   print('helper'); // LINE_A.
diff --git a/runtime/observatory/tests/service/async_star_single_step_into_test.dart b/runtime/observatory/tests/service/async_star_single_step_into_test.dart
index f59fbde..0ff41ec 100644
--- a/runtime/observatory/tests/service/async_star_single_step_into_test.dart
+++ b/runtime/observatory/tests/service/async_star_single_step_into_test.dart
@@ -4,16 +4,15 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 19;
-const LINE_B = 20;
-const LINE_C = 24;
-const LINE_D = 27;
-const LINE_E = 33;
-const LINE_F = 34;
+const LINE_A = 18;
+const LINE_B = 19;
+const LINE_C = 23;
+const LINE_D = 26;
+const LINE_E = 32;
+const LINE_F = 33;
 
 foobar() async* {
   yield 1; // LINE_A.
diff --git a/runtime/observatory/tests/service/async_star_step_out_test.dart b/runtime/observatory/tests/service/async_star_step_out_test.dart
index eeeecf1..72795da 100644
--- a/runtime/observatory/tests/service/async_star_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_star_step_out_test.dart
@@ -4,19 +4,18 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 22;
-const LINE_B = 23;
-const LINE_C = 27;
-const LINE_D = 30;
-const LINE_E = 37;
-const LINE_F = 38;
-const LINE_G = 39;
-const LINE_H = 28;
-const LINE_I = 32;
+const LINE_A = 21;
+const LINE_B = 22;
+const LINE_C = 26;
+const LINE_D = 29;
+const LINE_E = 36;
+const LINE_F = 37;
+const LINE_G = 38;
+const LINE_H = 27;
+const LINE_I = 31;
 
 foobar() async* {
   yield 1; // LINE_A.
diff --git a/runtime/observatory/tests/service/async_step_out_test.dart b/runtime/observatory/tests/service/async_step_out_test.dart
index aa2be20..3f59c2d 100644
--- a/runtime/observatory/tests/service/async_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_step_out_test.dart
@@ -4,15 +4,14 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug --async_debugger
 
 import 'dart:developer';
-
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-const LINE_A = 18;
-const LINE_B = 19;
-const LINE_C = 24;
-const LINE_D = 25;
-const LINE_E = 26;
+const LINE_A = 17;
+const LINE_B = 18;
+const LINE_C = 23;
+const LINE_D = 24;
+const LINE_E = 25;
 
 helper() async {
   print('helper'); // LINE_A.
diff --git a/runtime/observatory/tests/service/evaluate_with_scope_test.dart b/runtime/observatory/tests/service/evaluate_with_scope_test.dart
index 84a7662..73e1e1f 100644
--- a/runtime/observatory/tests/service/evaluate_with_scope_test.dart
+++ b/runtime/observatory/tests/service/evaluate_with_scope_test.dart
@@ -5,7 +5,6 @@
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
-
 import 'test_helper.dart';
 
 var thing1;
diff --git a/runtime/observatory/tests/service/get_native_allocation_samples_test.dart b/runtime/observatory/tests/service/get_native_allocation_samples_test.dart
index 1012802..c09d693 100644
--- a/runtime/observatory/tests/service/get_native_allocation_samples_test.dart
+++ b/runtime/observatory/tests/service/get_native_allocation_samples_test.dart
@@ -7,7 +7,6 @@
 import 'package:observatory/models.dart' as M;
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
-
 import 'test_helper.dart';
 
 void verifyHelper(var root, bool exclusive) {
diff --git a/runtime/observatory/tests/service/get_object_store_rpc_test.dart b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
index a15abca..5582895 100644
--- a/runtime/observatory/tests/service/get_object_store_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
@@ -36,9 +36,10 @@
     // Sanity check.
     expect(object_store.fields.length, greaterThanOrEqualTo(1));
     // Checking Closures.
-    expect(object_store.fields.singleWhere(isClosureFunctionsList), isNotNull);
-    expect(object_store.fields.singleWhere(isClosureFunctionsList).value.isList,
-        isTrue);
+    var single = object_store.fields.singleWhere(isClosureFunctionsList);
+    expect(single, isNotNull);
+    var value = single.value as Instance;
+    expect(value.isList, isTrue);
   }
 ];
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index a541cbe..0188cd2 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -409,10 +409,10 @@
 cc/Parser_AllocateVariables_MiddleChain: Fail
 cc/Parser_AllocateVariables_NestedCapturedVar: Fail
 cc/Parser_AllocateVariables_TwoChains: Fail
-cc/Profiler_BasicSourcePositionOptimized: Fail
-cc/Profiler_BinaryOperatorSourcePositionOptimized: Fail
+cc/Profiler_BasicSourcePositionOptimized: Fail, Crash
+cc/Profiler_BinaryOperatorSourcePositionOptimized: Fail, Crash
 cc/Profiler_GetSourceReport: Fail
-cc/Profiler_SourcePositionOptimized: Fail
+cc/Profiler_SourcePositionOptimized: Fail, Crash
 cc/ScriptSnapshot1: Fail
 cc/ScriptSnapshot2: Crash
 cc/ScriptSnapshot: Crash
diff --git a/runtime/tools/bin_to_assembly.py b/runtime/tools/bin_to_assembly.py
index 18ade13..941a050 100755
--- a/runtime/tools/bin_to_assembly.py
+++ b/runtime/tools/bin_to_assembly.py
@@ -57,14 +57,6 @@
       output_file.write(".global _%s\n" % options.symbol_name)
       output_file.write(".balign 32\n")
       output_file.write("_%s:\n" % options.symbol_name)
-    elif options.target_os in ["linux", "android", "fuchsia"]:
-      if options.executable:
-        output_file.write(".text\n")
-      else:
-        output_file.write(".section .rodata\n")
-      output_file.write(".global %s\n" % options.symbol_name)
-      output_file.write(".balign 32\n")
-      output_file.write("%s:\n" % options.symbol_name)
     elif options.target_os in ["win"]:
       output_file.write("ifndef _ML64_X64\n")
       output_file.write(".model flat, C\n")
@@ -76,8 +68,15 @@
       output_file.write("public %s\n" % options.symbol_name)
       output_file.write("%s label byte\n" % options.symbol_name)
     else:
-      sys.stderr.write("Unknown target_os: %s" % options.target_os)
-      return -1
+      if options.executable:
+        output_file.write(".text\n")
+        output_file.write(".type %s STT_FUNC\n" % options.symbol_name)
+      else:
+        output_file.write(".section .rodata\n")
+        output_file.write(".type %s STT_OBJECT\n" % options.symbol_name)
+      output_file.write(".global %s\n" % options.symbol_name)
+      output_file.write(".balign 32\n")
+      output_file.write("%s:\n" % options.symbol_name)
 
     with open(options.input, "rb") as input_file:
       if options.target_os in ["win"]:
@@ -88,6 +87,9 @@
         for byte in input_file.read():
           output_file.write(".byte %d\n" % ord(byte))
 
+    if options.target_os not in ["mac", "ios", "win"]:
+      output_file.write(".size {0}, .-{0}\n".format(options.symbol_name))
+
   return 0
 
 if __name__ == "__main__":
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 52dc66b..efe2f1c 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -1561,13 +1561,13 @@
   if ((sz == kWord) || (sz == kUnsignedWord)) {
     return;
   }
-  LsrImmediate(tmp, src, 24);
-  str(tmp, Address(addr, 4), kUnsignedByte);
   LsrImmediate(tmp, src, 32);
-  str(tmp, Address(addr, 5), kUnsignedByte);
+  str(tmp, Address(addr, 4), kUnsignedByte);
   LsrImmediate(tmp, src, 40);
-  str(tmp, Address(addr, 6), kUnsignedByte);
+  str(tmp, Address(addr, 5), kUnsignedByte);
   LsrImmediate(tmp, src, 48);
+  str(tmp, Address(addr, 6), kUnsignedByte);
+  LsrImmediate(tmp, src, 56);
   str(tmp, Address(addr, 7), kUnsignedByte);
   if (sz == kDoubleWord) {
     return;
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index cde10da..cbeadfd 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -843,6 +843,18 @@
     EmitFPImm(FMOVDI, vd, imm8);
     return true;
   }
+  void fmovsr(VRegister vd, Register rn) {
+    ASSERT(rn != R31);
+    ASSERT(rn != CSP);
+    const Register crn = ConcreteRegister(rn);
+    EmitFPIntCvtOp(FMOVSR, static_cast<Register>(vd), crn, kWord);
+  }
+  void fmovrs(Register rd, VRegister vn) {
+    ASSERT(rd != R31);
+    ASSERT(rd != CSP);
+    const Register crd = ConcreteRegister(rd);
+    EmitFPIntCvtOp(FMOVRS, crd, static_cast<Register>(vn), kWord);
+  }
   void fmovdr(VRegister vd, Register rn) {
     ASSERT(rn != R31);
     ASSERT(rn != CSP);
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index f7fde66..566a9a3 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -2113,6 +2113,38 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(Fmovrs, assembler) {
+  __ LoadDImmediate(V2, 1.0);
+  __ fcvtsd(V1, V2);
+  __ fmovrs(R0, V1);
+  __ ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Fmovrs, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
+  const uint32_t one = bit_cast<uint32_t, float>(1.0f);
+  EXPECT_EQ(one, static_cast<uint32_t>(result));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Fmovsr, assembler) {
+  __ LoadImmediate(R2, bit_cast<uint32_t, float>(1.0f));
+  __ fmovsr(V1, R2);
+  __ fmovrs(R0, V1);
+  __ ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Fmovsr, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
+  const uint32_t one = bit_cast<uint32_t, float>(1.0f);
+  EXPECT_EQ(one, static_cast<uint32_t>(result));
+}
+
+
 ASSEMBLER_TEST_GENERATE(FldrdFstrdPrePostIndex, assembler) {
   __ SetupDartSP();
   __ LoadDImmediate(V1, 42.0);
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index bafbc73..b97f4ca 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -620,8 +620,10 @@
 
 // C3.6.30
 enum FPIntCvtOp {
-  FPIntCvtMask = 0x5f20fc00,
+  FPIntCvtMask = 0x5f00fc00,
   FPIntCvtFixed = FPFixed | B21,
+  FMOVRS = FPIntCvtFixed | B18 | B17,
+  FMOVSR = FPIntCvtFixed | B18 | B17 | B16,
   FMOVRD = FPIntCvtFixed | B22 | B18 | B17,
   FMOVDR = FPIntCvtFixed | B22 | B18 | B17 | B16,
   FCVTZDS = FPIntCvtFixed | B22 | B20 | B19,
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f32f959..cd8c54e6 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2343,6 +2343,21 @@
 }
 
 
+DART_EXPORT Dart_Handle Dart_GetClosure(Dart_Handle library,
+                                        Dart_Handle function_name) {
+  DARTSCOPE(Thread::Current());
+  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
+  if (lib.IsNull()) {
+    RETURN_TYPE_ERROR(Z, library, Library);
+  }
+  const String& name = Api::UnwrapStringHandle(Z, function_name);
+  if (name.IsNull()) {
+    RETURN_TYPE_ERROR(Z, function_name, String);
+  }
+  return Api::NewHandle(T, lib.GetFunctionClosure(name));
+}
+
+
 // --- Booleans ----
 
 DART_EXPORT Dart_Handle Dart_True() {
@@ -5422,6 +5437,9 @@
   if (tmp.IsError()) {
     return Api::NewHandle(T, tmp.raw());
   }
+  // TODO(kernel): Setting root library based on whether it has 'main' or not
+  // is not correct because main can be in the exported namespace of a library
+  // or it could be a getter.
   if (tmp.IsNull()) {
     return Api::NewError("%s: The binary program does not contain 'main'.",
                          CURRENT_FUNC);
diff --git a/runtime/vm/disassembler_arm64.cc b/runtime/vm/disassembler_arm64.cc
index 448fda3..77bc20f 100644
--- a/runtime/vm/disassembler_arm64.cc
+++ b/runtime/vm/disassembler_arm64.cc
@@ -1319,18 +1319,31 @@
 
 
 void ARM64Decoder::DecodeFPIntCvt(Instr* instr) {
-  if ((instr->Bit(29) != 0) || (instr->Bits(22, 2) != 1)) {
+  if ((instr->Bit(29) != 0)) {
     Unknown(instr);
     return;
   }
-  if (instr->Bits(16, 5) == 2) {
-    Format(instr, "scvtfd'sf 'vd, 'rn");
-  } else if (instr->Bits(16, 5) == 6) {
-    Format(instr, "fmovrd'sf 'rd, 'vn");
-  } else if (instr->Bits(16, 5) == 7) {
-    Format(instr, "fmovdr'sf 'vd, 'rn");
-  } else if (instr->Bits(16, 5) == 24) {
-    Format(instr, "fcvtzds'sf 'rd, 'vn");
+
+  if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
+    if (instr->Bits(16, 5) == 6) {
+      Format(instr, "fmovrs'sf 'rd, 'vn");
+    } else if (instr->Bits(16, 5) == 7) {
+      Format(instr, "fmovsr'sf 'vd, 'rn");
+    } else {
+      Unknown(instr);
+    }
+  } else if (instr->Bits(22, 2) == 1) {
+    if (instr->Bits(16, 5) == 2) {
+      Format(instr, "scvtfd'sf 'vd, 'rn");
+    } else if (instr->Bits(16, 5) == 6) {
+      Format(instr, "fmovrd'sf 'rd, 'vn");
+    } else if (instr->Bits(16, 5) == 7) {
+      Format(instr, "fmovdr'sf 'vd, 'rn");
+    } else if (instr->Bits(16, 5) == 24) {
+      Format(instr, "fcvtzds'sf 'rd, 'vn");
+    } else {
+      Unknown(instr);
+    }
   } else {
     Unknown(instr);
   }
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 0ab9457..2c32781 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -19,6 +19,13 @@
 #define USING_MULTICORE false
 #endif
 
+// Don't use USING_PRODUCT outside of this file.
+#if defined(PRODUCT)
+#define USING_PRODUCT true
+#else
+#define USING_PRODUCT false
+#endif
+
 // List of all flags in the VM.
 // Flags can be one of three categories:
 // * P roduct flags: Can be set in any of the deployment modes, including in
@@ -134,7 +141,7 @@
   P(reify_generic_functions, bool, false,                                      \
     "Enable reification of generic functions (not yet supported).")            \
   P(reorder_basic_blocks, bool, true, "Reorder basic blocks")                  \
-  C(causal_async_stacks, false, false, bool, true, "Improved async stacks")    \
+  P(causal_async_stacks, bool, !USING_PRODUCT, "Improved async stacks")        \
   C(stress_async_stacks, false, false, bool, false,                            \
     "Stress test async stack traces")                                          \
   C(async_debugger, false, false, bool, true,                                  \
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index b03a8f6..cfb7622 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -4080,8 +4080,6 @@
     case kExternalOneByteStringCid:
       // Don't need to worry about alignment for accessing bytes.
       return kAlignedAccess;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
     case kTypedDataFloat64x2ArrayCid:
     case kTypedDataInt32x4ArrayCid:
     case kTypedDataFloat32x4ArrayCid:
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 86d9c5a..4252de5 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1,4 +1,3 @@
-
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
@@ -1239,7 +1238,13 @@
 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = aligned() ? 0 : 1;
+  intptr_t kNumTemps = 0;
+  if (!aligned()) {
+    kNumTemps += 1;
+    if (representation() == kUnboxedDouble) {
+      kNumTemps += 1;
+    }
+  }
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
@@ -1276,6 +1281,9 @@
   }
   if (!aligned()) {
     locs->set_temp(0, Location::RequiresRegister());
+    if (representation() == kUnboxedDouble) {
+      locs->set_temp(1, Location::RequiresRegister());
+    }
   }
   return locs;
 }
@@ -1325,16 +1333,32 @@
       case kTypedDataFloat32ArrayCid:
         // Load single precision float.
         // vldrs does not support indexed addressing.
-        __ vldrs(EvenSRegisterOf(dresult0), element_address);
+        if (aligned()) {
+          __ vldrs(EvenSRegisterOf(dresult0), element_address);
+        } else {
+          const Register value = locs()->temp(1).reg();
+          __ LoadWordUnaligned(value, address, TMP);
+          __ vmovsr(EvenSRegisterOf(dresult0), value);
+        }
         break;
       case kTypedDataFloat64ArrayCid:
         // vldrd does not support indexed addressing.
-        __ vldrd(dresult0, element_address);
+        if (aligned()) {
+          __ vldrd(dresult0, element_address);
+        } else {
+          const Register value = locs()->temp(1).reg();
+          __ LoadWordUnaligned(value, address, TMP);
+          __ vmovsr(EvenSRegisterOf(dresult0), value);
+          __ AddImmediate(address, address, 4);
+          __ LoadWordUnaligned(value, address, TMP);
+          __ vmovsr(OddSRegisterOf(dresult0), value);
+        }
         break;
       case kTypedDataFloat64x2ArrayCid:
       case kTypedDataInt32x4ArrayCid:
       case kTypedDataFloat32x4ArrayCid:
         ASSERT(element_address.Equals(Address(IP)));
+        ASSERT(aligned());
         __ vldmd(IA, IP, dresult0, 2);
         break;
       default:
@@ -1459,34 +1483,35 @@
   LocationSummary* locs;
 
   bool needs_base = false;
+  intptr_t kNumTemps = 0;
   if (CanBeImmediateIndex(index(), class_id(), IsExternal(),
                           false,  // Store.
                           &needs_base)) {
-    const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2;
+    if (!aligned()) {
+      kNumTemps += 2;
+    } else if (needs_base) {
+      kNumTemps += 1;
+    }
+
     locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 
     // CanBeImmediateIndex must return false for unsafe smis.
     locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
-    if (needs_base) {
-      locs->set_temp(0, Location::RequiresRegister());
-    }
-    if (!aligned()) {
-      locs->set_temp(0, Location::RequiresRegister());
-      locs->set_temp(1, Location::RequiresRegister());
-    }
   } else {
-    const intptr_t kNumTemps = aligned() ? 0 : 2;
+    if (!aligned()) {
+      kNumTemps += 2;
+    }
+
     locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 
     locs->set_in(1, Location::WritableRegister());
-    if (!aligned()) {
-      locs->set_temp(0, Location::RequiresRegister());
-      locs->set_temp(1, Location::RequiresRegister());
-    }
   }
   locs->set_in(0, Location::RequiresRegister());
+  for (intptr_t i = 0; i < kNumTemps; i++) {
+    locs->set_temp(i, Location::RequiresRegister());
+  }
 
   switch (class_id()) {
     case kArrayCid:
@@ -1636,18 +1661,36 @@
     case kTypedDataFloat32ArrayCid: {
       const SRegister value_reg =
           EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
-      __ vstrs(value_reg, element_address);
+      if (aligned()) {
+        __ vstrs(value_reg, element_address);
+      } else {
+        const Register address = temp;
+        const Register value = temp2;
+        __ vmovrs(value, value_reg);
+        __ StoreWordUnaligned(value, address, TMP);
+      }
       break;
     }
     case kTypedDataFloat64ArrayCid: {
       const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg());
-      __ vstrd(value_reg, element_address);
+      if (aligned()) {
+        __ vstrd(value_reg, element_address);
+      } else {
+        const Register address = temp;
+        const Register value = temp2;
+        __ vmovrs(value, EvenSRegisterOf(value_reg));
+        __ StoreWordUnaligned(value, address, TMP);
+        __ AddImmediate(address, address, 4);
+        __ vmovrs(value, OddSRegisterOf(value_reg));
+        __ StoreWordUnaligned(value, address, TMP);
+      }
       break;
     }
     case kTypedDataFloat64x2ArrayCid:
     case kTypedDataInt32x4ArrayCid:
     case kTypedDataFloat32x4ArrayCid: {
       ASSERT(element_address.Equals(Address(index.reg())));
+      ASSERT(aligned());
       const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg());
       __ vstmd(IA, index.reg(), value_reg, 2);
       break;
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 8986f04..bdd9de0 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -1127,15 +1127,26 @@
       ASSERT(aligned());
       case kTypedDataFloat32ArrayCid:
         // Load single precision float.
-        __ fldrs(result, element_address);
+        if (aligned()) {
+          __ fldrs(result, element_address);
+        } else {
+          __ LoadUnaligned(TMP, address, TMP2, kUnsignedWord);
+          __ fmovsr(result, TMP);
+        }
         break;
       case kTypedDataFloat64ArrayCid:
         // Load double precision float.
-        __ fldrd(result, element_address);
+        if (aligned()) {
+          __ fldrd(result, element_address);
+        } else {
+          __ LoadUnaligned(TMP, address, TMP2, kDoubleWord);
+          __ fmovdr(result, TMP);
+        }
         break;
       case kTypedDataFloat64x2ArrayCid:
       case kTypedDataInt32x4ArrayCid:
       case kTypedDataFloat32x4ArrayCid:
+        ASSERT(aligned());
         __ fldrq(result, element_address);
         break;
       default:
@@ -1472,15 +1483,23 @@
       break;
     }
     case kTypedDataFloat32ArrayCid: {
-      ASSERT(aligned());
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrs(value_reg, element_address);
+      if (aligned()) {
+        __ fstrs(value_reg, element_address);
+      } else {
+        __ fmovrs(TMP, value_reg);
+        __ StoreUnaligned(TMP, address, scratch, kWord);
+      }
       break;
     }
     case kTypedDataFloat64ArrayCid: {
-      ASSERT(aligned());
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrd(value_reg, element_address);
+      if (aligned()) {
+        __ fstrd(value_reg, element_address);
+      } else {
+        __ fmovrd(TMP, value_reg);
+        __ StoreUnaligned(TMP, address, scratch, kDoubleWord);
+      }
       break;
     }
     case kTypedDataFloat64x2ArrayCid:
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index 6902242..4757791 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -1320,6 +1320,8 @@
   AssertStatement* stmt = new AssertStatement();
   stmt->kernel_offset_ = reader->offset() - 1;  // -1 to include tag byte.
   stmt->condition_ = Expression::ReadFrom(reader);
+  reader->ReadPosition();  // condition start offset.
+  reader->ReadPosition();  // condition end offset.
   stmt->message_ = reader->ReadOptional<Expression>();
 
   stmt->can_stream_ = stmt->condition_->can_stream() &&
diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc
index 33c8588..37f596c 100644
--- a/runtime/vm/kernel_binary_flowgraph.cc
+++ b/runtime/vm/kernel_binary_flowgraph.cc
@@ -728,12 +728,16 @@
     case kAssertStatement: {
       if (I->asserts()) {
         VisitExpression();              // Read condition.
+        builder_->ReadPosition();       // read condition start offset.
+        builder_->ReadPosition();       // read condition end offset.
         Tag tag = builder_->ReadTag();  // read (first part of) message.
         if (tag == kSomething) {
           VisitExpression();  // read (rest of) message.
         }
       } else {
         builder_->SkipExpression();     // Read condition.
+        builder_->ReadPosition();       // read condition start offset.
+        builder_->ReadPosition();       // read condition end offset.
         Tag tag = builder_->ReadTag();  // read (first part of) message.
         if (tag == kSomething) {
           builder_->SkipExpression();  // read (rest of) message.
@@ -4146,6 +4150,8 @@
       return;
     case kAssertStatement: {
       SkipExpression();     // Read condition.
+      ReadPosition();       // read condition start offset.
+      ReadPosition();       // read condition end offset.
       Tag tag = ReadTag();  // read (first part of) message.
       if (tag == kSomething) {
         SkipExpression();  // read (rest of) message.
@@ -5904,53 +5910,33 @@
   instructions += Constant(Bool::True());
   instructions += BranchIfEqual(&then, &otherwise, false);
 
+  TokenPosition condition_start_offset =
+      ReadPosition();  // read condition start offset.
+  TokenPosition condition_end_offset =
+      ReadPosition();  // read condition end offset.
+
   const dart::Class& klass = dart::Class::ZoneHandle(
       Z, dart::Library::LookupCoreClass(Symbols::AssertionError()));
   ASSERT(!klass.IsNull());
-  const dart::Function& constructor = dart::Function::ZoneHandle(
-      Z, klass.LookupConstructorAllowPrivate(
-             H.DartSymbol("_AssertionError._create")));
-  ASSERT(!constructor.IsNull());
+  const dart::Function& target = dart::Function::ZoneHandle(
+      Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
+  ASSERT(!target.IsNull());
 
-  const dart::String& url = H.DartString(
-      parsed_function()->function().ToLibNamePrefixedQualifiedCString(),
-      Heap::kOld);
-
-  // Create instance of _AssertionError
+  // Build call to _AsertionError._throwNew(start, end, message)
   Fragment otherwise_fragment(otherwise);
-  otherwise_fragment += AllocateObject(klass, 0);
-  LocalVariable* instance = MakeTemporary();
-
-  // Call _AssertionError._create constructor.
-  otherwise_fragment += LoadLocal(instance);
-  otherwise_fragment += PushArgument();  // this
-
-  otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld));
-  otherwise_fragment += PushArgument();  // failedAssertion
-
-  otherwise_fragment += Constant(url);
-  otherwise_fragment += PushArgument();  // url
-
-  otherwise_fragment += IntConstant(0);
-  otherwise_fragment += PushArgument();  // line
-
-  otherwise_fragment += IntConstant(0);
-  otherwise_fragment += PushArgument();  // column
-
+  otherwise_fragment += IntConstant(condition_start_offset.Pos());
+  otherwise_fragment += PushArgument();  // start
+  otherwise_fragment += IntConstant(condition_end_offset.Pos());
+  otherwise_fragment += PushArgument();  // end
   Tag tag = ReadTag();  // read (first part of) message.
   if (tag == kSomething) {
     otherwise_fragment += BuildExpression();  // read (rest of) message.
   } else {
-    otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld));
+    otherwise_fragment += Constant(Instance::ZoneHandle(Z));  // null.
   }
   otherwise_fragment += PushArgument();  // message
 
-  otherwise_fragment += StaticCall(TokenPosition::kNoSource, constructor, 6);
-  otherwise_fragment += Drop();
-
-  // Throw _AssertionError exception.
-  otherwise_fragment += PushArgument();
-  otherwise_fragment += ThrowException(TokenPosition::kNoSource);
+  otherwise_fragment += StaticCall(TokenPosition::kNoSource, target, 3);
   otherwise_fragment += Drop();
 
   return Fragment(instructions.entry, then);
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index bbc8e1a..f2923d5 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -176,32 +176,18 @@
     }
 
     if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) {
-      // There is a function _getMainClosure in dart:_builtin that returns the
-      // main procedure.  Since the platform libraries are compiled before the
-      // program script, this function might need to be patched here.
-
-      // If there is no main method then we have compiled a partial Kernel file
-      // and do not need to patch here.
+      // If 'main' is not found return a null library, this is the case
+      // when bootstrapping is in progress.
       NameIndex main = program_->main_method();
       if (main == -1) {
         return dart::Library::Handle(Z);
       }
 
-      // If the builtin library is not set in the object store, then we are
-      // bootstrapping and do not need to patch here.
-      dart::Library& builtin_library =
-          dart::Library::Handle(Z, I->object_store()->builtin_library());
-      if (builtin_library.IsNull()) {
-        return dart::Library::Handle(Z);
-      }
-
       NameIndex main_library = H.EnclosingName(main);
       dart::Library& library = LookupLibrary(main_library);
       // Sanity check that we can find the main entrypoint.
-      Object& main_obj = Object::Handle(
-          Z, library.LookupObjectAllowPrivate(H.DartSymbol("main")));
-      ASSERT(!main_obj.IsNull());
-
+      ASSERT(library.LookupObjectAllowPrivate(H.DartSymbol("main")) !=
+             Object::null());
       return library;
     }
   }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index a1f636e..728e2ff 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3757,7 +3757,7 @@
 
 
 void Class::set_canonical_type(const Type& value) const {
-  ASSERT(!value.IsNull());
+  ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
   StorePointer(&raw_ptr()->canonical_type_, value.raw());
 }
 
@@ -12063,6 +12063,32 @@
 }
 
 
+RawObject* Library::GetFunctionClosure(const String& name) const {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Function& func = Function::Handle(zone, LookupFunctionAllowPrivate(name));
+  if (func.IsNull()) {
+    // Check whether the function is reexported into the library.
+    const Object& obj = Object::Handle(zone, LookupReExport(name));
+    if (obj.IsFunction()) {
+      func ^= obj.raw();
+    } else {
+      // Check if there is a getter of 'name', in which case invoke it
+      // and return the result.
+      const String& getter_name = String::Handle(zone, Field::GetterName(name));
+      func = LookupFunctionAllowPrivate(getter_name);
+      if (func.IsNull()) {
+        return Closure::null();
+      }
+      // Invoke the getter and return the result.
+      return DartEntry::InvokeFunction(func, Object::empty_array());
+    }
+  }
+  func = func.ImplicitClosureFunction();
+  return func.ImplicitStaticClosure();
+}
+
+
 #if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
 void Library::CheckFunctionFingerprints() {
   GrowableArray<Library*> all_libs;
@@ -17532,13 +17558,12 @@
     return Object::dynamic_type().raw();
   }
 
-  AbstractType& type = Type::Handle(zone);
   const Class& cls = Class::Handle(zone, type_class());
 
   // Fast canonical lookup/registry for simple types.
   if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
     ASSERT(!IsFunctionType());
-    type = cls.CanonicalType();
+    Type& type = Type::Handle(zone, cls.CanonicalType());
     if (type.IsNull()) {
       ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
       // Canonicalize the type arguments of the supertype, if any.
@@ -17556,18 +17581,26 @@
         // Recheck if type exists.
         type = cls.CanonicalType();
         if (type.IsNull()) {
-          ComputeHash();
-          SetCanonical();
-          cls.set_canonical_type(*this);
-          return this->raw();
+          if (this->IsNew()) {
+            type ^= Object::Clone(*this, Heap::kOld);
+          } else {
+            type ^= this->raw();
+          }
+          ASSERT(type.IsOld());
+          type.ComputeHash();
+          type.SetCanonical();
+          cls.set_canonical_type(type);
+          return type.raw();
         }
       }
     }
     ASSERT(this->Equals(type));
     ASSERT(type.IsCanonical());
+    ASSERT(type.IsOld());
     return type.raw();
   }
 
+  AbstractType& type = Type::Handle(zone);
   ObjectStore* object_store = isolate->object_store();
   {
     SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index c6715d6..d506263 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3983,6 +3983,11 @@
   void CheckReload(const Library& replacement,
                    IsolateReloadContext* context) const;
 
+  // Returns a closure of top level function 'name' in the exported namespace
+  // of this library. If a top level function 'name' does not exist we look
+  // for a top level getter 'name' that returns a closure.
+  RawObject* GetFunctionClosure(const String& name) const;
+
  private:
   static const int kInitialImportsCapacity = 4;
   static const int kImportsCapacityIncrement = 8;
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index a4297ba..40f150b 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -346,6 +346,7 @@
       isolate_(thread->isolate()),
       jit_feedback_(NULL),
       changed_(false),
+      retain_root_library_caches_(false),
       function_count_(0),
       class_count_(0),
       selector_count_(0),
@@ -689,6 +690,27 @@
 
   AddEntryPoints(vm_entry_points);
   AddEntryPoints(embedder_entry_points);
+  const Library& lib = Library::Handle(I->object_store()->root_library());
+  const String& name = String::Handle(String::New("main"));
+  const Object& main_closure = Object::Handle(lib.GetFunctionClosure(name));
+  if (main_closure.IsClosure()) {
+    if (lib.LookupLocalFunction(name) == Function::null()) {
+      // Check whether the function is in exported namespace of library, in
+      // this case we have to retain the root library caches.
+      if (lib.LookupFunctionAllowPrivate(name) != Function::null() ||
+          lib.LookupReExport(name) != Object::null()) {
+        retain_root_library_caches_ = true;
+      }
+    }
+    AddConstObject(Closure::Cast(main_closure));
+  } else if (main_closure.IsError()) {
+    const Error& error = Error::Cast(main_closure);
+    String& msg =
+        String::Handle(Z, String::NewFormatted("Cannot find main closure %s\n",
+                                               error.ToErrorCString()));
+    Jump(Error::Handle(Z, ApiError::New(msg)));
+    UNREACHABLE();
+  }
 }
 
 
@@ -2028,7 +2050,10 @@
       dict.SetAt(j, Object::null_object());
     }
     lib.RehashDictionary(dict, used * 4 / 3 + 1);
-    lib.DropDependenciesAndCaches();
+    if (!(retain_root_library_caches_ &&
+          (lib.raw() == I->object_store()->root_library()))) {
+      lib.DropDependenciesAndCaches();
+    }
   }
 }
 
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 07dfed2..eb3a6ca 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -431,6 +431,7 @@
   ParsedJSONObject* jit_feedback_;
 
   bool changed_;
+  bool retain_root_library_caches_;
   intptr_t function_count_;
   intptr_t class_count_;
   intptr_t selector_count_;
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index f245ed5..9a4fe3b 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -302,10 +302,31 @@
       address_ticks_(0) {}
 
 
-void ProfileCode::AdjustExtent(uword start, uword end) {
+void ProfileCode::TruncateLower(uword start) {
+  if (start > start_) {
+    start_ = start;
+  }
+  ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::TruncateUpper(uword end) {
+  if (end < end_) {
+    end_ = end;
+  }
+  ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::ExpandLower(uword start) {
   if (start < start_) {
     start_ = start;
   }
+  ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::ExpandUpper(uword end) {
   if (end > end_) {
     end_ = end;
   }
@@ -695,172 +716,163 @@
 }
 
 
-typedef bool (*RangeCompare)(uword pc, uword region_start, uword region_end);
-
-class ProfileCodeTable : public ZoneAllocated {
- public:
-  ProfileCodeTable() : table_(8) {}
-
-  intptr_t length() const { return table_.length(); }
-
-  ProfileCode* At(intptr_t index) const {
-    ASSERT(index >= 0);
-    ASSERT(index < length());
-    return table_[index];
+intptr_t ProfileCodeTable::FindCodeIndexForPC(uword pc) const {
+  intptr_t length = table_.length();
+  if (length == 0) {
+    return -1;  // Not found.
   }
-
-  // Find the table index to the ProfileCode containing pc.
-  // Returns < 0 if not found.
-  intptr_t FindCodeIndexForPC(uword pc) const {
-    intptr_t index = FindCodeIndex(pc, &CompareLowerBound);
-    if (index == length()) {
-      // Not present.
-      return -1;
-    }
-    const ProfileCode* code = At(index);
-    if (!code->Contains(pc)) {
-      // Not present.
-      return -1;
-    }
-    // Found at index.
-    return index;
-  }
-
-  ProfileCode* FindCodeForPC(uword pc) const {
-    intptr_t index = FindCodeIndexForPC(pc);
-    if (index < 0) {
-      return NULL;
-    }
-    return At(index);
-  }
-
-  // Insert |new_code| into the table. Returns the table index where |new_code|
-  // was inserted. Will merge with an overlapping ProfileCode if one is present.
-  intptr_t InsertCode(ProfileCode* new_code) {
-    const uword start = new_code->start();
-    const uword end = new_code->end();
-    const intptr_t length = table_.length();
-    if (length == 0) {
-      table_.Add(new_code);
-      return length;
-    }
-    // Determine the correct place to insert or merge |new_code| into table.
-    intptr_t lo = FindCodeIndex(start, &CompareLowerBound);
-    intptr_t hi = FindCodeIndex(end - 1, &CompareUpperBound);
-    // TODO(johnmccutchan): Simplify below logic.
-    if ((lo == length) && (hi == length)) {
-      lo = length - 1;
-    }
-    if (lo == length) {
-      ProfileCode* code = At(hi);
-      if (code->Overlaps(new_code)) {
-        HandleOverlap(code, new_code, start, end);
-        return hi;
-      }
-      table_.Add(new_code);
-      return length;
-    } else if (hi == length) {
-      ProfileCode* code = At(lo);
-      if (code->Overlaps(new_code)) {
-        HandleOverlap(code, new_code, start, end);
-        return lo;
-      }
-      table_.Add(new_code);
-      return length;
-    } else if (lo == hi) {
-      ProfileCode* code = At(lo);
-      if (code->Overlaps(new_code)) {
-        HandleOverlap(code, new_code, start, end);
-        return lo;
-      }
-      table_.InsertAt(lo, new_code);
-      return lo;
+  intptr_t lo = 0;
+  intptr_t hi = length - 1;
+  while (lo <= hi) {
+    intptr_t mid = (hi - lo + 1) / 2 + lo;
+    ASSERT(mid >= lo);
+    ASSERT(mid <= hi);
+    ProfileCode* code = At(mid);
+    if (code->Contains(pc)) {
+      return mid;
+    } else if (pc < code->start()) {
+      hi = mid - 1;
     } else {
-      ProfileCode* code = At(lo);
-      if (code->Overlaps(new_code)) {
-        HandleOverlap(code, new_code, start, end);
-        return lo;
-      }
-      code = At(hi);
-      if (code->Overlaps(new_code)) {
-        HandleOverlap(code, new_code, start, end);
-        return hi;
-      }
-      table_.InsertAt(hi, new_code);
-      return hi;
-    }
-    UNREACHABLE();
-    return -1;
-  }
-
- private:
-  intptr_t FindCodeIndex(uword pc, RangeCompare comparator) const {
-    ASSERT(comparator != NULL);
-    intptr_t count = table_.length();
-    intptr_t first = 0;
-    while (count > 0) {
-      intptr_t it = first;
-      intptr_t step = count / 2;
-      it += step;
-      const ProfileCode* code = At(it);
-      if (comparator(pc, code->start(), code->end())) {
-        first = ++it;
-        count -= (step + 1);
-      } else {
-        count = step;
-      }
-    }
-    return first;
-  }
-
-  static bool CompareUpperBound(uword pc, uword start, uword end) {
-    return pc >= end;
-  }
-
-  static bool CompareLowerBound(uword pc, uword start, uword end) {
-    return end <= pc;
-  }
-
-  void HandleOverlap(ProfileCode* existing,
-                     ProfileCode* code,
-                     uword start,
-                     uword end) {
-    // We should never see overlapping Dart code regions.
-    ASSERT(existing->kind() != ProfileCode::kDartCode);
-    // We should never see overlapping Tag code regions.
-    ASSERT(existing->kind() != ProfileCode::kTagCode);
-    // When code regions overlap, they should be of the same kind.
-    ASSERT(existing->kind() == code->kind());
-    existing->AdjustExtent(start, end);
-  }
-
-  void VerifyOrder() {
-    const intptr_t length = table_.length();
-    if (length == 0) {
-      return;
-    }
-    uword last = table_[0]->end();
-    for (intptr_t i = 1; i < length; i++) {
-      ProfileCode* a = table_[i];
-      ASSERT(last <= a->start());
-      last = a->end();
+      lo = mid + 1;
     }
   }
+  return -1;
+}
 
-  void VerifyOverlap() {
-    const intptr_t length = table_.length();
-    for (intptr_t i = 0; i < length; i++) {
-      ProfileCode* a = table_[i];
-      for (intptr_t j = i + 1; j < length; j++) {
-        ProfileCode* b = table_[j];
-        ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) &&
-               !b->Contains(a->start()) && !b->Contains(a->end() - 1));
-      }
-    }
+
+intptr_t ProfileCodeTable::InsertCode(ProfileCode* new_code) {
+  const intptr_t length = table_.length();
+  if (length == 0) {
+    table_.Add(new_code);
+    return length;
   }
 
-  ZoneGrowableArray<ProfileCode*> table_;
-};
+  // Determine the correct place to insert or merge |new_code| into table.
+  intptr_t lo = -1;
+  intptr_t hi = -1;
+  ProfileCode* lo_code = NULL;
+  ProfileCode* hi_code = NULL;
+  const uword pc = new_code->end() - 1;
+  FindNeighbors(pc, &lo, &hi, &lo_code, &hi_code);
+  ASSERT((lo_code != NULL) || (hi_code != NULL));
+
+  if (lo != -1) {
+    // Has left neighbor.
+    new_code->TruncateLower(lo_code->end());
+    ASSERT(!new_code->Overlaps(lo_code));
+  }
+  if (hi != -1) {
+    // Has right neighbor.
+    new_code->TruncateUpper(hi_code->start());
+    ASSERT(!new_code->Overlaps(hi_code));
+  }
+
+  if ((lo != -1) && (lo_code->kind() == ProfileCode::kNativeCode) &&
+      (new_code->kind() == ProfileCode::kNativeCode) &&
+      (lo_code->end() == new_code->start())) {
+    // Adjacent left neighbor of the same kind: merge.
+    // (dladdr doesn't give us symbol size so processing more samples may see
+    // more PCs we didn't previously know belonged to it.)
+    lo_code->ExpandUpper(new_code->end());
+    return lo;
+  }
+
+  if ((hi != -1) && (hi_code->kind() == ProfileCode::kNativeCode) &&
+      (new_code->kind() == ProfileCode::kNativeCode) &&
+      (new_code->end() == hi_code->start())) {
+    // Adjacent right neighbor of the same kind: merge.
+    // (dladdr doesn't give us symbol size so processing more samples may see
+    // more PCs we didn't previously know belonged to it.)
+    hi_code->ExpandLower(new_code->start());
+    return hi;
+  }
+
+  intptr_t insert;
+  if (lo == -1) {
+    insert = 0;
+  } else if (hi == -1) {
+    insert = length;
+  } else {
+    insert = lo + 1;
+  }
+  table_.InsertAt(insert, new_code);
+  return insert;
+}
+
+
+void ProfileCodeTable::FindNeighbors(uword pc,
+                                     intptr_t* lo,
+                                     intptr_t* hi,
+                                     ProfileCode** lo_code,
+                                     ProfileCode** hi_code) const {
+  ASSERT(table_.length() >= 1);
+
+  intptr_t length = table_.length();
+
+  if (pc < At(0)->start()) {
+    // Lower than any existing code.
+    *lo = -1;
+    *lo_code = NULL;
+    *hi = 0;
+    *hi_code = At(*hi);
+    return;
+  }
+
+  if (pc >= At(length - 1)->end()) {
+    // Higher than any existing code.
+    *lo = length - 1;
+    *lo_code = At(*lo);
+    *hi = -1;
+    *hi_code = NULL;
+    return;
+  }
+
+  *lo = 0;
+  *lo_code = At(*lo);
+  *hi = length - 1;
+  *hi_code = At(*hi);
+
+  while ((*hi - *lo) > 1) {
+    intptr_t mid = (*hi - *lo + 1) / 2 + *lo;
+    ASSERT(*lo <= mid);
+    ASSERT(*hi >= mid);
+    ProfileCode* code = At(mid);
+    if (code->end() <= pc) {
+      *lo = mid;
+      *lo_code = code;
+    }
+    if (pc < code->end()) {
+      *hi = mid;
+      *hi_code = code;
+    }
+  }
+}
+
+
+void ProfileCodeTable::VerifyOrder() {
+  const intptr_t length = table_.length();
+  if (length == 0) {
+    return;
+  }
+  uword last = table_[0]->end();
+  for (intptr_t i = 1; i < length; i++) {
+    ProfileCode* a = table_[i];
+    ASSERT(last <= a->start());
+    last = a->end();
+  }
+}
+
+void ProfileCodeTable::VerifyOverlap() {
+  const intptr_t length = table_.length();
+  for (intptr_t i = 0; i < length; i++) {
+    ProfileCode* a = table_[i];
+    for (intptr_t j = i + 1; j < length; j++) {
+      ProfileCode* b = table_[j];
+      ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) &&
+             !b->Contains(a->start()) && !b->Contains(a->end() - 1));
+    }
+  }
+}
 
 
 ProfileTrieNode::ProfileTrieNode(intptr_t table_index)
@@ -2239,6 +2251,24 @@
     native_start &= ~1;
 #endif
 
+    if (native_start > pc) {
+      // Bogus lookup result.
+      if (native_name != NULL) {
+        NativeSymbolResolver::FreeSymbolName(native_name);
+        native_name = NULL;
+      }
+      native_start = pc;
+    }
+    if ((pc - native_start) > (32 * KB)) {
+      // Suspect lookup result. More likely dladdr going off the rails than a
+      // jumbo function.
+      if (native_name != NULL) {
+        NativeSymbolResolver::FreeSymbolName(native_name);
+        native_name = NULL;
+      }
+      native_start = pc;
+    }
+
     ASSERT(pc >= native_start);
     profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
                                    pc + 1, 0, code);
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 8045906..b746f51 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -171,7 +171,10 @@
   uword end() const { return end_; }
   void set_end(uword end) { end_ = end; }
 
-  void AdjustExtent(uword start, uword end);
+  void ExpandLower(uword start);
+  void ExpandUpper(uword end);
+  void TruncateLower(uword start);
+  void TruncateUpper(uword end);
 
   bool Contains(uword pc) const { return (pc >= start_) && (pc < end_); }
 
@@ -239,6 +242,48 @@
 };
 
 
+class ProfileCodeTable : public ZoneAllocated {
+ public:
+  ProfileCodeTable() : table_(8) {}
+
+  intptr_t length() const { return table_.length(); }
+
+  ProfileCode* At(intptr_t index) const {
+    ASSERT(index >= 0);
+    ASSERT(index < length());
+    return table_[index];
+  }
+
+  // Find the table index to the ProfileCode containing pc.
+  // Returns < 0 if not found.
+  intptr_t FindCodeIndexForPC(uword pc) const;
+
+  ProfileCode* FindCodeForPC(uword pc) const {
+    intptr_t index = FindCodeIndexForPC(pc);
+    if (index < 0) {
+      return NULL;
+    }
+    return At(index);
+  }
+
+  // Insert |new_code| into the table. Returns the table index where |new_code|
+  // was inserted. Will merge with an overlapping ProfileCode if one is present.
+  intptr_t InsertCode(ProfileCode* new_code);
+
+ private:
+  void FindNeighbors(uword pc,
+                     intptr_t* lo,
+                     intptr_t* hi,
+                     ProfileCode** lo_code,
+                     ProfileCode** hi_code) const;
+
+  void VerifyOrder();
+  void VerifyOverlap();
+
+  ZoneGrowableArray<ProfileCode*> table_;
+};
+
+
 // Stack traces are organized in a trie. This holds information about one node
 // in the trie. A node in a tree represents a stack frame and a path in the tree
 // represents a stack trace. Each unique stack trace appears in the tree once
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 8dc7aea..17f0fdc 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -2809,6 +2809,112 @@
   EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString());
 }
 
+
+TEST_CASE(Profiler_ProfileCodeTableTest) {
+  Zone* Z = Thread::Current()->zone();
+
+  ProfileCodeTable* table = new (Z) ProfileCodeTable();
+  EXPECT_EQ(table->length(), 0);
+  EXPECT_EQ(table->FindCodeForPC(42), static_cast<ProfileCode*>(NULL));
+
+  int64_t timestamp = 0;
+  Code& null_code = Code::Handle(Z);
+
+  ProfileCode* code1 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 50, 60, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code1), 0);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(55), code1);
+  EXPECT_EQ(table->FindCodeForPC(59), code1);
+  EXPECT_EQ(table->FindCodeForPC(60), static_cast<ProfileCode*>(NULL));
+
+  // Insert below all.
+  ProfileCode* code2 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 10, 20, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code2), 0);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(19), code2);
+  EXPECT_EQ(table->FindCodeForPC(20), static_cast<ProfileCode*>(NULL));
+
+  // Insert above all.
+  ProfileCode* code3 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 80, 90, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code3), 2);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(80), code3);
+  EXPECT_EQ(table->FindCodeForPC(89), code3);
+  EXPECT_EQ(table->FindCodeForPC(90), static_cast<ProfileCode*>(NULL));
+
+  // Insert between.
+  ProfileCode* code4 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 65, 75, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code4), 2);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(80), code3);
+  EXPECT_EQ(table->FindCodeForPC(65), code4);
+  EXPECT_EQ(table->FindCodeForPC(74), code4);
+  EXPECT_EQ(table->FindCodeForPC(75), static_cast<ProfileCode*>(NULL));
+
+  // Insert overlapping left.
+  ProfileCode* code5 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 15, 25, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code5), 0);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(80), code3);
+  EXPECT_EQ(table->FindCodeForPC(65), code4);
+  EXPECT_EQ(table->FindCodeForPC(15), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(24), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(25), static_cast<ProfileCode*>(NULL));
+
+  // Insert overlapping right.
+  ProfileCode* code6 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 45, 55, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code6), 1);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(80), code3);
+  EXPECT_EQ(table->FindCodeForPC(65), code4);
+  EXPECT_EQ(table->FindCodeForPC(15), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(24), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(45), code1);  // Merged right.
+  EXPECT_EQ(table->FindCodeForPC(54), code1);  // Merged right.
+  EXPECT_EQ(table->FindCodeForPC(55), code1);
+
+  // Insert overlapping both.
+  ProfileCode* code7 = new (Z)
+      ProfileCode(ProfileCode::kNativeCode, 20, 50, timestamp, null_code);
+  EXPECT_EQ(table->InsertCode(code7), 0);
+  EXPECT_EQ(table->FindCodeForPC(0), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(100), static_cast<ProfileCode*>(NULL));
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+  EXPECT_EQ(table->FindCodeForPC(10), code2);
+  EXPECT_EQ(table->FindCodeForPC(80), code3);
+  EXPECT_EQ(table->FindCodeForPC(65), code4);
+  EXPECT_EQ(table->FindCodeForPC(15), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(24), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(45), code1);  // Merged right.
+  EXPECT_EQ(table->FindCodeForPC(54), code1);  // Merged right.
+  EXPECT_EQ(table->FindCodeForPC(20), code2);  // Merged left.
+  EXPECT_EQ(table->FindCodeForPC(49), code1);  // Truncated.
+  EXPECT_EQ(table->FindCodeForPC(50), code1);
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 455bac6..6125bae 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3251,33 +3251,52 @@
   const Register rd = instr->RdField();
   const Register rn = instr->RnField();
 
-  if ((instr->Bit(29) != 0) || (instr->Bits(22, 2) != 1) ||
-      ((instr->SFField() == 0) && (instr->Bits(16, 5) != 2))) {
+  if (instr->Bit(29) != 0) {
     UnimplementedInstruction(instr);
     return;
   }
-  if (instr->Bits(16, 5) == 2) {
-    // Format(instr, "scvtfd'sf 'vd, 'rn");
-    const int64_t rn_val64 = get_register(rn, instr->RnMode());
-    const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
-    const double vn_dbl = (instr->SFField() == 1)
-                              ? static_cast<double>(rn_val64)
-                              : static_cast<double>(rn_val32);
-    set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl));
-    set_vregisterd(vd, 1, 0);
-  } else if (instr->Bits(16, 5) == 6) {
-    // Format(instr, "fmovrd'sf 'rd, 'vn");
-    const int64_t vn_val = get_vregisterd(vn, 0);
-    set_register(instr, rd, vn_val, R31IsZR);
-  } else if (instr->Bits(16, 5) == 7) {
-    // Format(instr, "fmovdr'sf 'vd, 'rn");
-    const int64_t rn_val = get_register(rn, R31IsZR);
-    set_vregisterd(vd, 0, rn_val);
-    set_vregisterd(vd, 1, 0);
-  } else if (instr->Bits(16, 5) == 24) {
-    // Format(instr, "fcvtzds'sf 'rd, 'vn");
-    const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
-    set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
+
+  if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
+    if (instr->Bits(16, 5) == 6) {
+      // Format(instr, "fmovrs'sf 'rd, 'vn");
+      const int32_t vn_val = get_vregisters(vn, 0);
+      set_wregister(rd, vn_val, R31IsZR);
+    } else if (instr->Bits(16, 5) == 7) {
+      // Format(instr, "fmovsr'sf 'vd, 'rn");
+      const int32_t rn_val = get_wregister(rn, R31IsZR);
+      set_vregisters(vd, 0, rn_val);
+      set_vregisters(vd, 1, 0);
+      set_vregisters(vd, 2, 0);
+      set_vregisters(vd, 3, 0);
+    } else {
+      UnimplementedInstruction(instr);
+    }
+  } else if (instr->Bits(22, 2) == 1) {
+    if (instr->Bits(16, 5) == 2) {
+      // Format(instr, "scvtfd'sf 'vd, 'rn");
+      const int64_t rn_val64 = get_register(rn, instr->RnMode());
+      const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
+      const double vn_dbl = (instr->SFField() == 1)
+                                ? static_cast<double>(rn_val64)
+                                : static_cast<double>(rn_val32);
+      set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl));
+      set_vregisterd(vd, 1, 0);
+    } else if (instr->Bits(16, 5) == 6) {
+      // Format(instr, "fmovrd'sf 'rd, 'vn");
+      const int64_t vn_val = get_vregisterd(vn, 0);
+      set_register(instr, rd, vn_val, R31IsZR);
+    } else if (instr->Bits(16, 5) == 7) {
+      // Format(instr, "fmovdr'sf 'vd, 'rn");
+      const int64_t rn_val = get_register(rn, R31IsZR);
+      set_vregisterd(vd, 0, rn_val);
+      set_vregisterd(vd, 1, 0);
+    } else if (instr->Bits(16, 5) == 24) {
+      // Format(instr, "fcvtzds'sf 'rd, 'vn");
+      const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
+      set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
+    } else {
+      UnimplementedInstruction(instr);
+    }
   } else {
     UnimplementedInstruction(instr);
   }
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index fdb1d39..ee341a5 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -2740,6 +2740,7 @@
 LayoutTests/fast/canvas/2d.text.draw.fill.maxWidth.verySmall_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/DrawImageSinglePixelStretch_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/alpha_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-alphaImageData-behavior_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-arc-negative-radius_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blend-solid_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blending-text_t01: RuntimeError # Please triage this failure
@@ -2766,18 +2767,22 @@
 LayoutTests/fast/canvas/canvas-lose-restore-max-int-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-putImageData_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-resize-after-paint_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-fillPath-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-fillRect-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-scale-shadowBlur_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-scale-strokePath-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-set-properties-with-non-invertible-ctm_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-stroke-zeroSizeGradient_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-strokePath-alpha-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-strokeRect-alpha-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-strokeRect-zeroSizeGradient_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-strokeText-zeroSizeGradient_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/drawImage-with-bad-canvas_t01: RuntimeError # Issue 28983
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/gradient-addColorStop-with-invalid-color_t01: RuntimeError # Issue 28983
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
@@ -2888,7 +2893,6 @@
 LayoutTests/fast/css/deprecated-flexbox-auto-min-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/draggable-region-parser_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/dynamic-class-backdrop-pseudo_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/focus-display-block-inline_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-insert-link_t01: Pass, RuntimeError # Please triage this failure
@@ -2924,19 +2928,14 @@
 LayoutTests/fast/css/insertRule-font-face_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-media_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-hex-color_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalid-import-rule-insertion_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-predefined-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/clears-invalidation-whole-tree_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/detach-reattach-shadow_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalidation/detach-reattach_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/dynamic-selector-list-pseudo_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalidation/invalidation-set-with-adjacent-combinators_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/shadow-host-toggle_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/targeted-class-any-pseudo_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/targeted-class-host-pseudo_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalidation/targeted-class-id_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/targeted-class-shadow-combinator_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalidation/targeted-class-type-selectors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalidation/toggle-style-inside-shadow-root_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/legacy-opacity-styles_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/link-alternate-stylesheet-1_t01: RuntimeError # Please triage this failure
@@ -2965,7 +2964,6 @@
 LayoutTests/fast/css/pseudo-invalid-001_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LayoutTests/fast/css/pseudo-invalid-novalidate-001_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LayoutTests/fast/css/pseudo-required-optional-004_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/pseudo-required-optional-006_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/pseudo-required-optional-unapplied_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/pseudo-target-indirect-sibling-001_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/pseudo-target-indirect-sibling-002_t01: Skip # Times out. Please triage this failure
@@ -2978,8 +2976,6 @@
 LayoutTests/fast/css/readonly-pseudoclass-opera-005_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/readwrite-contenteditable-recalc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/recalc-optgroup-inherit_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/remove-attribute-style_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/remove-class-name_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/selector-text-escape_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-setProperty-important_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/sibling-selectors_t01: RuntimeError # Please triage this failure
@@ -3714,9 +3710,11 @@
 LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # co19 issue #90
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # co19 issue #90
 LibTest/core/double/roundToDouble_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LibTest/core/double/round_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -3726,8 +3724,6 @@
 LibTest/core/int/remainder_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/int/remainder_A01_t03: RuntimeError # Please triage this failure
 LibTest/core/int/toRadixString_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # co19 issue #90
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # co19 issue #90
 LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t03: RuntimeError # Please triage this failure
 LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t06: RuntimeError # Please triage this failure
 LibTest/html/Document/childNodes_A01_t01: RuntimeError # Please triage this failure
@@ -3940,9 +3936,6 @@
 WebPlatformTest/html/semantics/selectors/pseudo-classes/enabled_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/focus_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/indeterminate_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/tabular-data/the-caption-element/caption_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/tabular-data/the-table-element/caption-methods_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/tabular-data/the-table-element/table-insertRow_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/tabular-data/the-table-element/table-rows_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/syntax/parsing/Document.getElementsByTagName-foreign_t02: RuntimeError # Please triage this failure
 WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index b860a5d..abc1525 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -2,6 +2,9 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+[ $compiler == dartk && $mode == debug ]
+Language/Libraries_and_Scripts/Scripts/top_level_main_t05: Crash
+
 [ $compiler == dartk || $compiler == dartkp ]
 Language/Classes/Constructors/Generative_Constructors/initializers_t12: MissingCompileTimeError # Test bug: Test doesn't execute erroneous code.
 Language/Classes/Constructors/Generative_Constructors/redirection_t09: MissingCompileTimeError # Test bug: Test doesn't execute erroneous code.
@@ -116,7 +119,6 @@
 Language/Libraries_and_Scripts/Scripts/syntax_t08: MissingCompileTimeError
 Language/Libraries_and_Scripts/Scripts/syntax_t10: MissingCompileTimeError
 Language/Libraries_and_Scripts/Scripts/syntax_t14: MissingCompileTimeError
-Language/Libraries_and_Scripts/Scripts/top_level_main_t05: Crash
 Language/Libraries_and_Scripts/definition_syntax_t01: MissingCompileTimeError
 Language/Libraries_and_Scripts/definition_syntax_t03: MissingCompileTimeError
 Language/Libraries_and_Scripts/definition_syntax_t04: MissingCompileTimeError
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 3dfa964..2f91775 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -25,6 +25,9 @@
 
 LibTest/core/int/toRadixString_A01_t01: Fail # co19 issue 492
 
+# Skip until Issue 29895 is fixed.
+Language/Libraries_and_Scripts/Scripts/top_level_main_t01: skip
+
 Language/Libraries_and_Scripts/Exports/reexport_t02: fail # Dart issue 12916
 
 Language/Statements/Assert/execution_t02: skip # co19 issue 734
diff --git a/tests/compiler/dart2js/analysis_options.yaml b/tests/compiler/dart2js/analysis_options.yaml
new file mode 100644
index 0000000..07561c4
--- /dev/null
+++ b/tests/compiler/dart2js/analysis_options.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+analyzer:
+  strong-mode: true
+
+  language:
+    enableSuperMixins: false
+
+  errors:
+    todo: ignore
+
+    deprecated_member_use: ignore
+
+  exclude:
+    - data/*
+    - sourcemaps/data/*
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 695efe2..458824e 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -7,7 +7,6 @@
 import 'package:sdk_library_metadata/libraries.dart';
 import 'analyze_helper.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/diagnostics/messages.dart' show MessageKind;
 
 /**
  * Map of white-listed warnings and errors.
diff --git a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
index 22f6cca..7e190bf 100644
--- a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
+++ b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
@@ -61,7 +61,8 @@
           }
           library.forEachLocalMember((Element element) {
             if (element is ClassElement) {
-              element.forEachLocalMember((AstElement member) {
+              element.forEachLocalMember((_member) {
+                AstElement member = _member;
                 analyzer.analyze(member.resolvedAst);
               });
             } else if (element is MemberElement) {
diff --git a/tests/compiler/dart2js/fasta_analyze_test.dart b/tests/compiler/dart2js/analyze_dart_test.dart
similarity index 76%
rename from tests/compiler/dart2js/fasta_analyze_test.dart
rename to tests/compiler/dart2js/analyze_dart_test.dart
index 711e847..6d3f559 100644
--- a/tests/compiler/dart2js/fasta_analyze_test.dart
+++ b/tests/compiler/dart2js/analyze_dart_test.dart
@@ -7,10 +7,8 @@
 main() {
   // This method is async, but keeps a port open to prevent the VM from exiting
   // prematurely.
-  // Note: this should stay in sync with
-  // pkg/front_end/test/fasta/analyze_test.dart
   return testing.main(<String>[
-    "--config=pkg/front_end/test/fasta/testing.json",
+    "--config=pkg/compiler/testing_dart.json",
     "--verbose",
     "analyze"
   ]);
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index 779f389..fa06084 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -39,18 +39,19 @@
   bool lastWasWhitelisted = false;
   bool showWhitelisted = true;
 
-  Map<String, Map<dynamic /*String|MessageKind*/, int>> whiteListMap =
-      new Map<String, Map<dynamic /*String|MessageKind*/, int>>();
+  Map<String, Map<dynamic /* String|MessageKind */, int>> whiteListMap =
+      new Map<String, Map<dynamic /* String|MessageKind */, int>>();
   List<MessageKind> skipList;
   List<CollectedMessage> collectedMessages = <CollectedMessage>[];
 
   CollectingDiagnosticHandler(
-      Map<String, List/*<String|MessageKind>*/ > whiteList,
+      Map<String, List /* <String|MessageKind> */ > whiteList,
       this.skipList,
       SourceFileProvider provider)
       : super(provider) {
-    whiteList.forEach((String file, List/*<String|MessageKind>*/ messageParts) {
-      var useMap = new Map<dynamic /*String|MessageKind*/, int>();
+    whiteList
+        .forEach((String file, List /* <String|MessageKind> */ messageParts) {
+      var useMap = new Map<dynamic /* String|MessageKind */, int>();
       for (var messagePart in messageParts) {
         useMap[messagePart] = 0;
       }
@@ -131,8 +132,8 @@
   }
 
   @override
-  void report(Message message, Uri uri, int begin, int end, String text,
-      api.Diagnostic kind) {
+  void report(covariant Message message, Uri uri, int begin, int end,
+      String text, api.Diagnostic kind) {
     if (kind == api.Diagnostic.WARNING) {
       if (checkWhiteList(uri, message, text)) {
         // Suppress whitelisted warnings.
@@ -202,7 +203,7 @@
 /// Messages can be generally allowed using [skipList] or on a per-file basis
 /// using [whiteList].
 Future analyze(
-    List<Uri> uriList, Map<String, List/*<String|MessageKind>*/ > whiteList,
+    List<Uri> uriList, Map<String, List /* <String|MessageKind> */ > whiteList,
     {AnalysisMode mode: AnalysisMode.ALL,
     CheckResults checkResults,
     List<String> options: const <String>[],
diff --git a/tests/compiler/dart2js/analyze_test_test.dart b/tests/compiler/dart2js/analyze_test_test.dart
index 9a24cc0..6f692fd 100644
--- a/tests/compiler/dart2js/analyze_test_test.dart
+++ b/tests/compiler/dart2js/analyze_test_test.dart
@@ -7,13 +7,10 @@
 import 'dart:io';
 
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/apiimpl.dart' show CompilerImpl;
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/diagnostics/messages.dart' show MessageKind;
 import 'package:compiler/src/filenames.dart' show nativeToUriPath;
 
 import 'analyze_helper.dart';
-import 'memory_compiler.dart';
 
 /**
  * Map of white-listed warnings and errors.
@@ -22,7 +19,7 @@
  * the error/warning message in the list of white-listings for each file.
  */
 // TODO(johnniwinther): Support canonical URIs as keys.
-const Map<String, List/*<String|MessageKind>*/ > WHITE_LIST = const {
+const Map<String, List /* <String|MessageKind> */ > WHITE_LIST = const {
   "/test/lib/src/util/": const [
     "Library 'package:async/async.dart' doesn't export a "
         "'ForkableStream' declaration.",
diff --git a/tests/compiler/dart2js/annotated_code_helper.dart b/tests/compiler/dart2js/annotated_code_helper.dart
index 2e776fb..3e57a05 100644
--- a/tests/compiler/dart2js/annotated_code_helper.dart
+++ b/tests/compiler/dart2js/annotated_code_helper.dart
@@ -6,6 +6,12 @@
 const int _CR = 0x0D;
 const int _LBRACE = 0x7B;
 
+const Pattern atBraceStart = '@{';
+const Pattern braceEnd = '}';
+
+final Pattern commentStart = new RegExp(r' */\*');
+final Pattern commentEnd = new RegExp(r'\*/ *');
+
 class Annotation {
   /// 1-based line number of the annotation.
   final int lineNo;
@@ -55,7 +61,7 @@
   /// delimited by [start] and [end] are converted into [Annotation]s and
   /// removed from the [annotatedCode] to produce the source code.
   factory AnnotatedCode.fromText(String annotatedCode,
-      [String start = '@{', String end = '}']) {
+      [Pattern start = atBraceStart, Pattern end = braceEnd]) {
     StringBuffer codeBuffer = new StringBuffer();
     List<Annotation> annotations = <Annotation>[];
     int index = 0;
@@ -65,39 +71,47 @@
     List<int> lineStarts = <int>[];
     lineStarts.add(offset);
     while (index < annotatedCode.length) {
-      if (annotatedCode.startsWith(start, index)) {
-        int endIndex = annotatedCode.indexOf(end, index + start.length);
-        String text = annotatedCode.substring(index + start.length, endIndex);
-        annotations.add(new Annotation(lineNo, columnNo, offset, text));
-        index = endIndex + end.length;
-      } else {
-        int charCode = annotatedCode.codeUnitAt(index);
-        switch (charCode) {
-          case _LF:
-            codeBuffer.write('\n');
-            offset++;
-            lineStarts.add(offset);
-            lineNo++;
-            columnNo = 1;
-            break;
-          case _CR:
-            if (index + 1 < annotatedCode.length &&
-                annotatedCode.codeUnitAt(index + 1) == _LF) {
-              index++;
-            }
-            codeBuffer.write('\n');
-            offset++;
-            lineStarts.add(offset);
-            lineNo++;
-            columnNo = 1;
-            break;
-          default:
-            codeBuffer.writeCharCode(charCode);
-            offset++;
-            columnNo++;
+      Match startMatch = start.matchAsPrefix(annotatedCode, index);
+      if (startMatch != null) {
+        int startIndex = startMatch.end;
+        Iterable<Match> endMatches =
+            end.allMatches(annotatedCode, startMatch.end);
+        if (!endMatches.isEmpty) {
+          Match endMatch = endMatches.first;
+          annotatedCode.indexOf(end, startIndex);
+          String text = annotatedCode.substring(startMatch.end, endMatch.start);
+          annotations.add(new Annotation(lineNo, columnNo, offset, text));
+          index = endMatch.end;
+          continue;
         }
-        index++;
       }
+
+      int charCode = annotatedCode.codeUnitAt(index);
+      switch (charCode) {
+        case _LF:
+          codeBuffer.write('\n');
+          offset++;
+          lineStarts.add(offset);
+          lineNo++;
+          columnNo = 1;
+          break;
+        case _CR:
+          if (index + 1 < annotatedCode.length &&
+              annotatedCode.codeUnitAt(index + 1) == _LF) {
+            index++;
+          }
+          codeBuffer.write('\n');
+          offset++;
+          lineStarts.add(offset);
+          lineNo++;
+          columnNo = 1;
+          break;
+        default:
+          codeBuffer.writeCharCode(charCode);
+          offset++;
+          columnNo++;
+      }
+      index++;
     }
     lineStarts.add(offset);
     return new AnnotatedCode.internal(
diff --git a/tests/compiler/dart2js/array_tracing_mirror_test.dart b/tests/compiler/dart2js/array_tracing_mirror_test.dart
index 4b28acb..d19f1fb 100644
--- a/tests/compiler/dart2js/array_tracing_mirror_test.dart
+++ b/tests/compiler/dart2js/array_tracing_mirror_test.dart
@@ -34,7 +34,7 @@
   asyncTest(() async {
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
-    var element = compiler.mainFunction;
+    var element = compiler.frontendStrategy.elementEnvironment.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
     Expect.isTrue(code.contains('return 2'), "Unexpected code:\n$code");
   });
diff --git a/tests/compiler/dart2js/assert_message_throw_test.dart b/tests/compiler/dart2js/assert_message_throw_test.dart
index 7295153..be95a24 100644
--- a/tests/compiler/dart2js/assert_message_throw_test.dart
+++ b/tests/compiler/dart2js/assert_message_throw_test.dart
@@ -63,7 +63,7 @@
         compiler.resolutionWorldBuilder.closedWorldForTesting;
 
     void check(String methodName, TypeMask expectedReturnType) {
-      LibraryElement mainApp = compiler.mainApp;
+      LibraryElement mainApp = closedWorld.elementEnvironment.mainLibrary;
       MemberElement element = mainApp.find(methodName);
       TypeMask typeMask = simplify(
           compiler.globalInference.results.resultOfMember(element).returnType,
diff --git a/tests/compiler/dart2js/bad_output_io_test.dart b/tests/compiler/dart2js/bad_output_io_test.dart
index 943a97d..ada95c0 100644
--- a/tests/compiler/dart2js/bad_output_io_test.dart
+++ b/tests/compiler/dart2js/bad_output_io_test.dart
@@ -6,17 +6,25 @@
 
 library dart2js.test.bad_output_io;
 
-import 'dart:async';
+import 'dart:async' show Future;
 import 'dart:io' show exit;
 import 'package:expect/expect.dart';
 
 import 'package:compiler/compiler.dart' show Diagnostic;
-import 'package:compiler/compiler_new.dart' show OutputType;
+import 'package:compiler/compiler_new.dart'
+    show
+        CompilationResult,
+        CompilerDiagnostics,
+        CompilerInput,
+        CompilerOutput,
+        OutputType;
 import 'package:compiler/src/dart2js.dart'
     show exitFunc, compileFunc, compile, diagnosticHandler;
 import 'package:compiler/src/source_file_provider.dart'
     show FormattingDiagnosticHandler;
 
+import 'package:compiler/src/options.dart' show CompilerOptions;
+
 class CollectingFormattingDiagnosticHandler
     implements FormattingDiagnosticHandler {
   final provider = null;
@@ -56,10 +64,15 @@
   int throwOnErrorCount;
 }
 
-testOutputProvider(options, input, diagnostics, output) {
+Future<CompilationResult> testOutputProvider(
+    CompilerOptions options,
+    CompilerInput input,
+    CompilerDiagnostics diagnostics,
+    CompilerOutput output) {
   diagnosticHandler = new CollectingFormattingDiagnosticHandler();
   output.createOutputSink(
       "/non/existing/directory/should/fail/file", "js", OutputType.js);
+  return null;
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/benign_error_test.dart b/tests/compiler/dart2js/benign_error_test.dart
index 143239b..3e01a7d 100644
--- a/tests/compiler/dart2js/benign_error_test.dart
+++ b/tests/compiler/dart2js/benign_error_test.dart
@@ -34,6 +34,7 @@
         .isTrue(collector.errors.any((message) => message.messageKind == kind));
     Compiler compiler = result.compiler;
     JavaScriptBackend backend = compiler.backend;
-    Expect.isNotNull(backend.generatedCode[compiler.mainFunction]);
+    Expect.isNotNull(backend.generatedCode[
+        compiler.frontendStrategy.elementEnvironment.mainFunction]);
   }
 }
diff --git a/tests/compiler/dart2js/boolified_operator_test.dart b/tests/compiler/dart2js/boolified_operator_test.dart
index d632fed..6f51ac4 100644
--- a/tests/compiler/dart2js/boolified_operator_test.dart
+++ b/tests/compiler/dart2js/boolified_operator_test.dart
@@ -51,8 +51,6 @@
 """;
 
 main() {
-  RegExp regexp = new RegExp('=== true');
-
   asyncTest(() => Future.wait([
         compile(TEST_EQUAL, entry: 'foo', check: (String generated) {
           Expect.isFalse(generated.contains('=== true'));
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 44ea2ba..6759727 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/types/masks.dart';
 import 'package:expect/expect.dart';
 
@@ -14,7 +15,7 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri, disableInlining: disableInlining);
   asyncTest(() => compiler.run(uri).then((_) {
-        var cls = findElement(compiler, className);
+        ClassElement cls = findElement(compiler, className);
         var member = cls.lookupLocalMember(memberName);
         return check(compiler, member);
       }));
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index 5feee9c..3a4f36a 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -91,7 +91,7 @@
   ClassHierarchyNodeIterator iterator;
 
   void checkState(ClassElement root,
-      {ClassElement currentNode, List<List<ClassElement>> stack}) {
+      {ClassElement currentNode, List<ClassElement> stack}) {
     ClassElement classOf(ClassHierarchyNode node) {
       return node != null ? node.cls : null;
     }
@@ -399,7 +399,7 @@
   void checkForEachSubclass(ClassElement cls, List<ClassElement> expected) {
     ClassSet classSet = world.getClassSet(cls);
     List<ClassElement> visited = <ClassElement>[];
-    classSet.forEachSubclass((ClassElement cls) {
+    classSet.forEachSubclass((cls) {
       visited.add(cls);
     }, ClassHierarchyNode.ALL);
 
@@ -410,7 +410,7 @@
         "Actual: $visited, expected: $expected\n$classSet");
 
     visited = <ClassElement>[];
-    classSet.forEachSubclass((ClassElement cls) {
+    classSet.forEachSubclass((cls) {
       visited.add(cls);
       return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
@@ -436,7 +436,7 @@
   void checkForEachSubtype(ClassElement cls, List<ClassElement> expected) {
     ClassSet classSet = world.getClassSet(cls);
     List<ClassElement> visited = <ClassElement>[];
-    classSet.forEachSubtype((ClassElement cls) {
+    classSet.forEachSubtype((cls) {
       visited.add(cls);
     }, ClassHierarchyNode.ALL);
 
@@ -447,7 +447,7 @@
         "Actual: $visited, expected: $expected\n$classSet");
 
     visited = <ClassElement>[];
-    classSet.forEachSubtype((ClassElement cls) {
+    classSet.forEachSubtype((cls) {
       visited.add(cls);
       return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
@@ -482,7 +482,8 @@
     ClassSet classSet = world.getClassSet(cls);
     List<ClassElement> visited = <ClassElement>[];
 
-    IterationStep visit(ClassElement cls) {
+    IterationStep visit(_cls) {
+      ClassElement cls = _cls;
       visited.add(cls);
       if (cls == stop) {
         return IterationStep.STOP;
@@ -538,7 +539,7 @@
     ClassSet classSet = world.getClassSet(cls);
     List<ClassElement> visited = <ClassElement>[];
 
-    bool visit(ClassElement cls) {
+    bool visit(cls) {
       visited.add(cls);
       return cls == find;
     }
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index b578c56..a5f37bc 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -31,7 +31,7 @@
     Expect.isTrue(success);
     Map<String, String> result = new Map<String, String>();
     var backend = compiler.backend;
-    for (var element in backend.generatedCode.keys) {
+    for (dynamic element in backend.generatedCode.keys) {
       if (element.compilationUnit.script.readableUri != uri) continue;
       var name = element.name;
       var code = backend.getGeneratedCode(element);
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 5cae225..bf58478 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -9,6 +9,8 @@
 
 import 'package:compiler/compiler_new.dart';
 
+import 'package:compiler/src/common_elements.dart';
+
 import 'package:compiler/src/elements/elements.dart';
 export 'package:compiler/src/elements/elements.dart';
 
@@ -74,19 +76,17 @@
         outputProvider: outputCollector);
     await compiler.init();
     compiler.parseScript(code);
-    LibraryElement mainApp = compiler.mainApp;
-    MethodElement element = mainApp.find(entry);
+    ElementEnvironment elementEnvironment =
+        compiler.frontendStrategy.elementEnvironment;
+    MethodElement element = compiler.mainApp.find(entry);
     if (element == null) return null;
     compiler.phase = Compiler.PHASE_RESOLVING;
-    compiler.processQueue(
-        compiler.frontendStrategy.elementEnvironment,
-        compiler.enqueuer.resolution,
-        element,
-        compiler.libraryLoader.libraries);
+    compiler.processQueue(elementEnvironment, compiler.enqueuer.resolution,
+        element, compiler.libraryLoader.libraries);
     ResolutionWorkItem resolutionWork =
         new ResolutionWorkItem(compiler.resolution, element);
     resolutionWork.run();
-    ClosedWorld closedWorld = compiler.closeResolution().closedWorld;
+    ClosedWorld closedWorld = compiler.closeResolution(element).closedWorld;
     CodegenWorkItem work =
         new ElementCodegenWorkItem(compiler.backend, closedWorld, element);
     compiler.phase = Compiler.PHASE_COMPILING;
@@ -129,7 +129,8 @@
         outputProvider: outputCollector);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    LibraryElement mainApp = compiler.mainApp;
+    LibraryElement mainApp =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary;
     Element element = mainApp.find(entry);
     js.JavaScriptBackend backend = compiler.backend;
     String generated = backend.getGeneratedCode(element);
@@ -199,7 +200,7 @@
 }
 
 Element findElement(compiler, String name, [Uri library]) {
-  LibraryElement lib = compiler.mainApp;
+  LibraryElement lib = compiler.frontendStrategy.elementEnvironment.mainLibrary;
   if (library != null) {
     lib = compiler.libraryLoader.lookupLibrary(library);
     Expect.isNotNull(lib, 'Could not locate library $library.');
diff --git a/tests/compiler/dart2js/const_exp_test.dart b/tests/compiler/dart2js/const_exp_test.dart
index a903a62..c2ba74e 100644
--- a/tests/compiler/dart2js/const_exp_test.dart
+++ b/tests/compiler/dart2js/const_exp_test.dart
@@ -32,7 +32,7 @@
 """,
               expectNoWarningsOrErrors: true)
           .then((env) {
-        var element = env.getElement('constant');
+        dynamic element = env.getElement('constant');
         Expect.isNotNull(element, "Element 'constant' not found.");
         var constant = element.constant;
         var value = env.compiler.constants.getConstantValue(constant);
diff --git a/tests/compiler/dart2js/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
index 8ba312b..ce4d509 100644
--- a/tests/compiler/dart2js/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:compiler/src/common/backend_api.dart';
 import 'package:compiler/src/constants/constructors.dart';
 import 'package:compiler/src/constants/evaluation.dart';
 import 'package:compiler/src/constants/expressions.dart';
@@ -276,7 +275,7 @@
   CompilationResult result = await runCompiler(
       memorySourceFiles: {'main.dart': source}, options: ['--analyze-all']);
   Compiler compiler = result.compiler;
-  var library = compiler.mainApp;
+  dynamic library = compiler.frontendStrategy.elementEnvironment.mainLibrary;
   constants.forEach((String name, ConstantData data) {
     FieldElement field = library.localLookup(name);
     ConstantExpression constant = field.constant;
diff --git a/tests/compiler/dart2js/constant_expression_test.dart b/tests/compiler/dart2js/constant_expression_test.dart
index d8f582c..8be001e 100644
--- a/tests/compiler/dart2js/constant_expression_test.dart
+++ b/tests/compiler/dart2js/constant_expression_test.dart
@@ -210,10 +210,10 @@
       memorySourceFiles: {'main.dart': source}, options: ['--analyze-all']);
   Compiler compiler = result.compiler;
   MemoryEnvironment environment = new MemoryEnvironment(compiler);
-  var library = compiler.mainApp;
+  dynamic library = compiler.frontendStrategy.elementEnvironment.mainLibrary;
   constants.forEach((String name, ConstantData data) {
     FieldElement field = library.localLookup(name);
-    var constant = field.constant;
+    dynamic constant = field.constant;
     Expect.equals(
         data.kind,
         constant.kind,
diff --git a/tests/compiler/dart2js/container_mask_equal_test.dart b/tests/compiler/dart2js/container_mask_equal_test.dart
index 5bb5298..0cded25 100644
--- a/tests/compiler/dart2js/container_mask_equal_test.dart
+++ b/tests/compiler/dart2js/container_mask_equal_test.dart
@@ -33,16 +33,20 @@
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
     var closedWorld = typesInferrer.closedWorld;
 
-    var element = compiler.mainApp.find('a');
+    var element =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary.find('a');
     var mask1 = typesInferrer.getReturnTypeOfElement(element);
 
-    element = compiler.mainApp.find('b');
+    element =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary.find('b');
     var mask2 = typesInferrer.getReturnTypeOfElement(element);
 
-    element = compiler.mainApp.find('c');
+    element =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary.find('c');
     var mask3 = typesInferrer.getReturnTypeOfElement(element);
 
-    element = compiler.mainApp.find('d');
+    element =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary.find('d');
     var mask4 = typesInferrer.getReturnTypeOfElement(element);
 
     Expect.notEquals(
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 916c04a..3ae5ad3 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -6,6 +6,8 @@
 
 analyze_test: Slow, Pass
 
+analyze_dart_test: Slow, Pass
+
 compile_with_empty_libraries_test: Fail # Issue 24223
 
 kernel/*: Slow, Pass
diff --git a/tests/compiler/dart2js/dart2js_batch2_test.dart b/tests/compiler/dart2js/dart2js_batch2_test.dart
index 9aeec1d..0fac8aa 100644
--- a/tests/compiler/dart2js/dart2js_batch2_test.dart
+++ b/tests/compiler/dart2js/dart2js_batch2_test.dart
@@ -67,14 +67,11 @@
   Future<String> errorOut = process.stderr.transform(UTF8.decoder).join();
   return Future.wait([output, errorOut]).then((result) {
     String stdoutOutput = result[0];
-    String stderrOutput = result[1];
-
     Expect.isFalse(stdoutOutput.contains("crashed"));
   });
 }
 
 void main() {
-  var tmpDir;
   asyncTest(() {
     return setup().then(launchDart2Js).then(runTests).whenComplete(cleanUp);
   });
diff --git a/tests/compiler/dart2js/dart2js_batch_test.dart b/tests/compiler/dart2js/dart2js_batch_test.dart
index 1d41bf0..7e33ed5 100644
--- a/tests/compiler/dart2js/dart2js_batch_test.dart
+++ b/tests/compiler/dart2js/dart2js_batch_test.dart
@@ -86,7 +86,6 @@
 }
 
 void main() {
-  var tmpDir;
   asyncTest(() {
     return setup().then(launchDart2Js).then(runTests).whenComplete(cleanUp);
   });
diff --git a/tests/compiler/dart2js/dart2js_resolver_test.dart b/tests/compiler/dart2js/dart2js_resolver_test.dart
index 272cccd..7100827 100644
--- a/tests/compiler/dart2js/dart2js_resolver_test.dart
+++ b/tests/compiler/dart2js/dart2js_resolver_test.dart
@@ -4,7 +4,6 @@
 
 library dart2js.dart2js_resolver.test;
 
-import 'dart:io';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/dart2js_resolver.dart' as resolver;
 import 'analyze_test_test.dart';
diff --git a/tests/compiler/dart2js/data/dart2js_batch2_run.dart b/tests/compiler/dart2js/data/dart2js_batch2_run.dart
index aee55ef..b6de254 100644
--- a/tests/compiler/dart2js/data/dart2js_batch2_run.dart
+++ b/tests/compiler/dart2js/data/dart2js_batch2_run.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.
 
+// ignore: INVALID_ANNOTATION
 @notExisting
 var x;
 
diff --git a/tests/compiler/dart2js/data/mirrors_helper.dart b/tests/compiler/dart2js/data/mirrors_helper.dart
index 23544c1..b8de0ac 100644
--- a/tests/compiler/dart2js/data/mirrors_helper.dart
+++ b/tests/compiler/dart2js/data/mirrors_helper.dart
@@ -56,10 +56,14 @@
   }
 }
 
+// ignore: UNUSED_ELEMENT
 class _PrivateClass {
   var _privateField;
+  // ignore: UNUSED_ELEMENT
   get _privateGetter => _privateField;
+  // ignore: UNUSED_ELEMENT
   void set _privateSetter(value) => _privateField = value;
+  // ignore: UNUSED_ELEMENT
   void _privateMethod() {}
   _PrivateClass._privateConstructor();
   factory _PrivateClass._privateFactoryConstructor() => null;
diff --git a/tests/compiler/dart2js/deferred_custom_element_test.dart b/tests/compiler/dart2js/deferred_custom_element_test.dart
index c89ec9a..1205748 100644
--- a/tests/compiler/dart2js/deferred_custom_element_test.dart
+++ b/tests/compiler/dart2js/deferred_custom_element_test.dart
@@ -18,7 +18,7 @@
     Compiler compiler = result.compiler;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-    var lib =
+    dynamic lib =
         compiler.libraryLoader.lookupLibrary(Uri.parse("memory:lib.dart"));
     var customType = lib.find("CustomType");
     var foo = lib.find("foo");
diff --git a/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart b/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
index 3eec777..853d5b4 100644
--- a/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
+++ b/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
@@ -23,22 +23,22 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
 
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
-    var lib1 = lookupLibrary("memory:lib1.dart");
+    dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var foo1 = lib1.find("foo");
     var ou_lib1 = outputUnitForElement(foo1);
 
-    var lib2 = lookupLibrary("memory:lib2.dart");
+    dynamic lib2 = lookupLibrary("memory:lib2.dart");
     var foo2 = lib2.find("foo");
     var ou_lib2 = outputUnitForElement(foo2);
 
-    var mainApp = compiler.mainApp;
+    dynamic mainApp = compiler.frontendStrategy.elementEnvironment.mainLibrary;
     var fooMain = mainApp.find("foo");
     var ou_lib1_lib2 = outputUnitForElement(fooMain);
 
diff --git a/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart b/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
index 779bee0..3ceafd0 100644
--- a/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
+++ b/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
@@ -22,14 +22,14 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
 
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
-    var lib1 = lookupLibrary("memory:lib1.dart");
+    dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var foo1 = lib1.find("finalVar");
     var ou_lib1 = outputUnitForElement(foo1);
 
diff --git a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
index c0eeba9..718574a 100644
--- a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
+++ b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
@@ -5,7 +5,6 @@
 // Test that constants depended on by other constants are correctly deferred.
 
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/common.dart';
 import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:expect/expect.dart';
@@ -25,11 +24,11 @@
       c.getDependencies().forEach(addConstantWithDependendencies);
     }
 
-    var codegenWorldBuilder = compiler.codegenWorldBuilder;
+    dynamic codegenWorldBuilder = compiler.codegenWorldBuilder;
     codegenWorldBuilder.compiledConstants
         .forEach(addConstantWithDependendencies);
     for (String stringValue in ["cA", "cB", "cC"]) {
-      ConstantValue constant = allConstants.firstWhere((constant) {
+      ConstantValue constant = allConstants.firstWhere((dynamic constant) {
         return constant.isString && constant.primitiveValue == stringValue;
       });
       Expect.notEquals(null, outputUnitForConstant(constant),
diff --git a/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart b/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
index 67389f4..6b10ed3 100644
--- a/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
+++ b/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
@@ -18,14 +18,14 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
 
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
-    var lib = lookupLibrary("memory:lib.dart");
+    dynamic lib = lookupLibrary("memory:lib.dart");
     var a = lib.find("a");
     var b = lib.find("b");
     var c = lib.find("c");
diff --git a/tests/compiler/dart2js/deferred_inline_restrictions_test.dart b/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
index 4a5d8f6..9b305b7 100644
--- a/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
+++ b/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
@@ -24,11 +24,11 @@
 
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
-    var lib1 = lookupLibrary("memory:lib1.dart");
+    dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var inlineMeAway = lib1.find("inlineMeAway");
     var ou_lib1 = outputUnitForElement(inlineMeAway);
 
-    var lib3 = lookupLibrary("memory:lib3.dart");
+    dynamic lib3 = lookupLibrary("memory:lib3.dart");
     var sameContextInline = lib3.find("sameContextInline");
     var ou_lib3 = outputUnitForElement(sameContextInline);
 
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
index 1320fe2..312d7cc 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
@@ -18,7 +18,7 @@
     Compiler compiler = result.compiler;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-    var lib =
+    dynamic lib =
         compiler.libraryLoader.lookupLibrary(Uri.parse("memory:lib.dart"));
     var f1 = lib.find("f1");
     var f2 = lib.find("f2");
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index 0563a63..5a7c3ce 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -22,7 +22,7 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
 
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
@@ -31,13 +31,13 @@
     var backend = compiler.backend;
     var classes = backend.emitter.neededClasses;
     var inputElement = classes.where((e) => e.name == 'InputElement').single;
-    var lib1 = lookupLibrary("memory:lib1.dart");
+    dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var foo1 = lib1.find("foo1");
-    var lib2 = lookupLibrary("memory:lib2.dart");
+    dynamic lib2 = lookupLibrary("memory:lib2.dart");
     var foo2 = lib2.find("foo2");
-    var lib3 = lookupLibrary("memory:lib3.dart");
+    dynamic lib3 = lookupLibrary("memory:lib3.dart");
     var foo3 = lib3.find("foo3");
-    var lib4 = lookupLibrary("memory:lib4.dart");
+    dynamic lib4 = lookupLibrary("memory:lib4.dart");
     var bar1 = lib4.find("bar1");
     var bar2 = lib4.find("bar2");
 
diff --git a/tests/compiler/dart2js/deferred_mirrors_test.dart b/tests/compiler/dart2js/deferred_mirrors_test.dart
index e7d878d..ff7b5ff 100644
--- a/tests/compiler/dart2js/deferred_mirrors_test.dart
+++ b/tests/compiler/dart2js/deferred_mirrors_test.dart
@@ -10,7 +10,6 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'memory_compiler.dart';
-import 'package:compiler/src/compiler.dart' as dart2js;
 
 Future runTest(String mainScript, test) async {
   CompilationResult result = await runCompiler(
@@ -29,7 +28,7 @@
 
 runTests() async {
   await runTest('memory:main.dart', (compiler) {
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
@@ -53,7 +52,7 @@
     Expect.isTrue(true);
   });
   await runTest('memory:main3.dart', (compiler) {
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
@@ -69,14 +68,14 @@
     Expect.equals(outputUnitForElement(main), outputUnitForElement(C));
   });
   await runTest('memory:main4.dart', (compiler) {
-    var main = compiler.mainFunction;
+    var main = compiler.frontendStrategy.elementEnvironment.mainFunction;
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(
         main, compiler.resolutionWorldBuilder.closedWorldForTesting);
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
-    var mainLib = lookupLibrary(compiler, "memory:main4.dart");
-    var lib4 = lookupLibrary(compiler, "memory:lib4.dart");
+    lookupLibrary(compiler, "memory:main4.dart");
+    lookupLibrary(compiler, "memory:lib4.dart");
     var lib5 = lookupLibrary(compiler, "memory:lib5.dart");
     var lib6 = lookupLibrary(compiler, "memory:lib6.dart");
     var foo5 = lib5.find("foo");
diff --git a/tests/compiler/dart2js/deferred_not_in_main_test.dart b/tests/compiler/dart2js/deferred_not_in_main_test.dart
index 9e45223..428fb64 100644
--- a/tests/compiler/dart2js/deferred_not_in_main_test.dart
+++ b/tests/compiler/dart2js/deferred_not_in_main_test.dart
@@ -25,14 +25,12 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-    var backend = compiler.backend;
-    var lib1 = lookupLibrary("memory:lib1.dart");
-    var lib2 = lookupLibrary("memory:lib2.dart");
-    var foo1 = lib1.find("foo1");
+    dynamic lib1 = lookupLibrary("memory:lib1.dart");
+    dynamic lib2 = lookupLibrary("memory:lib2.dart");
+    lib1.find("foo1");
     var foo2 = lib2.find("foo2");
 
     Expect.notEquals(mainOutputUnit, outputUnitForElement(foo2));
@@ -48,11 +46,10 @@
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
 
-    var main = compiler.mainFunction;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
 
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
-    var shared = lookupLibrary("memory:shared.dart");
+    dynamic shared = lookupLibrary("memory:shared.dart");
     var a = shared.find("A");
 
     Expect.equals(mainOutputUnit, outputUnitForElement(a));
diff --git a/tests/compiler/dart2js/diagnostic_helper.dart b/tests/compiler/dart2js/diagnostic_helper.dart
index 6f63e8a..e5d433d 100644
--- a/tests/compiler/dart2js/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_helper.dart
@@ -35,8 +35,8 @@
   List<CollectedMessage> messages = <CollectedMessage>[];
 
   @override
-  void report(Message message, Uri uri, int begin, int end, String text,
-      Diagnostic kind) {
+  void report(covariant Message message, Uri uri, int begin, int end,
+      String text, Diagnostic kind) {
     messages.add(new CollectedMessage(message, uri, begin, end, text, kind));
   }
 
diff --git a/tests/compiler/dart2js/diagnostic_reporter_helper.dart b/tests/compiler/dart2js/diagnostic_reporter_helper.dart
index 0a706f7..0ca8649 100644
--- a/tests/compiler/dart2js/diagnostic_reporter_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_reporter_helper.dart
@@ -8,7 +8,7 @@
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/diagnostics/source_span.dart';
 import 'package:compiler/src/diagnostics/spannable.dart';
-import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
 import 'package:front_end/src/fasta/scanner.dart';
 import 'options_helper.dart';
 
@@ -67,7 +67,7 @@
   SourceSpan spanFromToken(Token token) => reporter.spanFromToken(token);
 
   @override
-  withCurrentElement(Element element, f()) {
+  withCurrentElement(Entity element, f()) {
     return reporter.withCurrentElement(element, f);
   }
 
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index ff37cab..1c50039 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -151,7 +151,7 @@
   if (!createCode) {
     checker(commonMasks, getType, closedWorld);
   } else {
-    var element = compiler.mainFunction;
+    var element = compiler.frontendStrategy.elementEnvironment.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
     checker(code);
   }
diff --git a/tests/compiler/dart2js/embedded_category_api_boundary_test.dart b/tests/compiler/dart2js/embedded_category_api_boundary_test.dart
index 80151cd..8fcf124 100644
--- a/tests/compiler/dart2js/embedded_category_api_boundary_test.dart
+++ b/tests/compiler/dart2js/embedded_category_api_boundary_test.dart
@@ -7,7 +7,6 @@
 /// processed.
 library embedded_category_boundary_test;
 
-import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
@@ -37,8 +36,8 @@
 ]);
 
 bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
-  return compiler.enqueuer.resolution.processedEntities
-      .every((MemberElement element) {
+  return compiler.enqueuer.resolution.processedEntities.every((_element) {
+    MemberElement element = _element;
     if (whiteList.contains("$element")) return true;
     LibraryInfo info = libraries[element.library.canonicalUri.path];
     bool isAllowedInEmbedded =
diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
index 658c747..ad8f1f1 100644
--- a/tests/compiler/dart2js/equivalence/check_functions.dart
+++ b/tests/compiler/dart2js/equivalence/check_functions.dart
@@ -624,12 +624,14 @@
   return usage1.hasSameUsage(usage2);
 }
 
+bool _areEntitiesEquivalent(a, b) => areElementsEquivalent(a, b);
+
 void checkResolutionEnqueuers(
     BackendUsage backendUsage1,
     BackendUsage backendUsage2,
     ResolutionEnqueuer enqueuer1,
     ResolutionEnqueuer enqueuer2,
-    {bool elementEquivalence(Entity a, Entity b): areElementsEquivalent,
+    {bool elementEquivalence(Entity a, Entity b): _areEntitiesEquivalent,
     bool typeEquivalence(DartType a, DartType b): areTypesEquivalent,
     bool elementFilter(Element element),
     bool verbose: false,
@@ -720,7 +722,7 @@
 }
 
 void checkCodegenEnqueuers(CodegenEnqueuer enqueuer1, CodegenEnqueuer enqueuer2,
-    {bool elementEquivalence(Entity a, Entity b): areElementsEquivalent,
+    {bool elementEquivalence(Entity a, Entity b): _areEntitiesEquivalent,
     bool typeEquivalence(DartType a, DartType b): areTypesEquivalent,
     bool elementFilter(Element element),
     bool verbose: false}) {
diff --git a/tests/compiler/dart2js/equivalence/check_helpers.dart b/tests/compiler/dart2js/equivalence/check_helpers.dart
index c7fff7e..4b9836b 100644
--- a/tests/compiler/dart2js/equivalence/check_helpers.dart
+++ b/tests/compiler/dart2js/equivalence/check_helpers.dart
@@ -8,7 +8,6 @@
 
 import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/constants/values.dart';
-import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
 import 'package:compiler/src/elements/types.dart';
@@ -56,7 +55,7 @@
 /// inequivalence.
 class CheckStrategy extends TestStrategy {
   const CheckStrategy(
-      {Equivalence<Entity> elementEquivalence: areElementsEquivalent,
+      {Equivalence<Entity> elementEquivalence: areEntitiesEquivalent,
       Equivalence<DartType> typeEquivalence: areTypesEquivalent,
       Equivalence<ConstantExpression> constantEquivalence:
           areConstantsEquivalent,
@@ -90,7 +89,6 @@
         throw "$o1.$p = '${v1}' <> "
             "$o2.$p = '${v2}'";
       }
-      return true;
     });
   }
 
@@ -249,7 +247,7 @@
 ///
 /// Uses [object1], [object2] and [property] to provide context for failures.
 bool checkElementIdentities(Object object1, Object object2, String property,
-    Element element1, Element element2) {
+    Entity element1, Entity element2) {
   if (identical(element1, element2)) return true;
   return check(
       object1, object2, property, element1, element2, areElementsEquivalent);
@@ -260,7 +258,7 @@
 ///
 /// Uses [object1], [object2] and [property] to provide context for failures.
 bool checkElementListIdentities(Object object1, Object object2, String property,
-    Iterable<Element> list1, Iterable<Element> list2) {
+    Iterable<Entity> list1, Iterable<Entity> list2) {
   return checkListEquivalence(
       object1, object2, property, list1, list2, checkElementIdentities);
 }
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index e833e4a..fe5784a 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -11,7 +11,6 @@
 import 'package:expect/expect.dart';
 
 import 'package:compiler/compiler_new.dart' as api;
-import 'package:compiler/src/common/backend_api.dart';
 import 'package:compiler/src/common/codegen.dart';
 import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/compile_time_constants.dart';
@@ -23,6 +22,7 @@
 import 'package:compiler/src/diagnostics/spannable.dart';
 import 'package:compiler/src/apiimpl.dart' as apiimpl;
 import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/library_loader.dart';
 import 'package:compiler/src/null_compiler_output.dart';
@@ -139,7 +139,7 @@
   DiagnosticReporter reporter;
 
   @override
-  withCurrentElement(Element element, f()) {
+  withCurrentElement(Entity element, f()) {
     return super.withCurrentElement(element, () {
       compiler.test('Compiler.withCurrentElement');
       return f();
diff --git a/tests/compiler/dart2js/expect_annotations2_test.dart b/tests/compiler/dart2js/expect_annotations2_test.dart
index d00755e..981ba57 100644
--- a/tests/compiler/dart2js/expect_annotations2_test.dart
+++ b/tests/compiler/dart2js/expect_annotations2_test.dart
@@ -38,7 +38,7 @@
 void main() {
   asyncTest(() async {
     OutputCollector collector = new OutputCollector();
-    CompilationResult result = await runCompiler(
+    await runCompiler(
         memorySourceFiles: MEMORY_SOURCE_FILES, outputProvider: collector);
     // Simply check that the constants of the small functions are still in the
     // output, and that we don't see the result of constant folding.
diff --git a/tests/compiler/dart2js/expect_annotations_test.dart b/tests/compiler/dart2js/expect_annotations_test.dart
index 83e1de3..c2b39f0 100644
--- a/tests/compiler/dart2js/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/expect_annotations_test.dart
@@ -83,7 +83,8 @@
         TypeMask expectedParameterType: null,
         TypeMask expectedReturnType: null,
         bool expectAssumeDynamic: false}) {
-      LibraryElement mainApp = compiler.mainApp;
+      LibraryElement mainApp =
+          compiler.frontendStrategy.elementEnvironment.mainLibrary;
       MethodElement method = mainApp.find(name);
       Expect.isNotNull(method);
       Expect.equals(expectNoInline, backend.optimizerHints.noInline(method),
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index d81aa1f..8040ed1 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -15,7 +15,7 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri, disableInlining: disableInlining);
   asyncTest(() => compiler.run(uri).then((_) {
-        var cls = findElement(compiler, className);
+        dynamic cls = findElement(compiler, className);
         var member = cls.lookupMember(memberName);
         check(compiler, member);
       }));
diff --git a/tests/compiler/dart2js/flatten_test.dart b/tests/compiler/dart2js/flatten_test.dart
index c624e48..68e97a5 100644
--- a/tests/compiler/dart2js/flatten_test.dart
+++ b/tests/compiler/dart2js/flatten_test.dart
@@ -8,7 +8,7 @@
 import "package:async_helper/async_helper.dart";
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
-import "package:compiler/src/elements/elements.dart" show Element, ClassElement;
+import "package:compiler/src/elements/elements.dart" show ClassElement;
 
 void main() {
   asyncTest(() => TypeEnvironment.create(r"""
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index 25af24aa..d7c0bec 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -25,13 +25,13 @@
 
 main() {
   Uri uri = new Uri(scheme: 'source');
-  var compiler = compilerFor(TEST, uri);
+  dynamic compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         String generated = compiler.assembledCode;
         RegExp regexp = new RegExp(r"get\$foo");
         Iterator matches = regexp.allMatches(generated).iterator;
         checkNumberOfMatches(matches, 1);
-        var cls = findElement(compiler, 'A');
+        dynamic cls = findElement(compiler, 'A');
         Expect.isNotNull(cls);
         String name = 'foo';
         var element = cls.lookupLocalMember(name);
diff --git a/tests/compiler/dart2js/import_mirrors_test.dart b/tests/compiler/dart2js/import_mirrors_test.dart
index e6d5fac..37e4ad7 100644
--- a/tests/compiler/dart2js/import_mirrors_test.dart
+++ b/tests/compiler/dart2js/import_mirrors_test.dart
@@ -316,7 +316,7 @@
   if (enableExperimentalMirrors) {
     options.add('--enable-experimental-mirrors');
   }
-  CompilationResult result = await runCompiler(
+  await runCompiler(
       entryPoint: Uri.parse('memory:/main.dart'),
       memorySourceFiles: sourceFiles,
       diagnosticHandler: collector,
diff --git a/tests/compiler/dart2js/import_test.dart b/tests/compiler/dart2js/import_test.dart
index c7b8f26..8684fe1 100644
--- a/tests/compiler/dart2js/import_test.dart
+++ b/tests/compiler/dart2js/import_test.dart
@@ -7,10 +7,8 @@
 
 library dart2js.test.import;
 
-import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
-import 'package:compiler/compiler.dart';
 import 'memory_compiler.dart';
 
 const MEMORY_SOURCE_FILES = const {
diff --git a/tests/compiler/dart2js/in_user_code_test.dart b/tests/compiler/dart2js/in_user_code_test.dart
index 486d3ec..1f926c6 100644
--- a/tests/compiler/dart2js/in_user_code_test.dart
+++ b/tests/compiler/dart2js/in_user_code_test.dart
@@ -48,7 +48,7 @@
       packageRoot: Uri.parse('memory:pkg/'));
   Compiler compiler = result.compiler;
   expectedResults.forEach((String uri, bool expectedResult) {
-    var element = compiler.libraryLoader.lookupLibrary(Uri.parse(uri));
+    dynamic element = compiler.libraryLoader.lookupLibrary(Uri.parse(uri));
     Expect.isNotNull(element, "Unknown library '$uri'.");
     Expect.equals(
         expectedResult,
diff --git a/tests/compiler/dart2js/inference/data/super_set.dart b/tests/compiler/dart2js/inference/data/super_set.dart
index 937a147..eb77cbc 100644
--- a/tests/compiler/dart2js/inference/data/super_set.dart
+++ b/tests/compiler/dart2js/inference/data/super_set.dart
@@ -10,12 +10,13 @@
 class Sub extends Super {
   /*Sub.method:[subclass=Closure]*/
   method() {
+    // ignore: INVALID_ASSIGNMENT
     var a = super.field = new Sub();
-    return a./*[exact=Sub]*/method;
+    return a. /*[exact=Sub]*/ method;
   }
 }
 
 /*main:[null]*/
 main() {
-  new Sub()./*[exact=Sub]*/method();
+  new Sub(). /*[exact=Sub]*/ method();
 }
diff --git a/tests/compiler/dart2js/inference/enumerator.dart b/tests/compiler/dart2js/inference/enumerator.dart
index 1c52456..fe219ce 100644
--- a/tests/compiler/dart2js/inference/enumerator.dart
+++ b/tests/compiler/dart2js/inference/enumerator.dart
@@ -90,7 +90,7 @@
   }
 
   NodeId computeNodeId(ast.Send node) {
-    var sendStructure = elements.getSendStructure(node);
+    dynamic sendStructure = elements.getSendStructure(node);
     if (sendStructure == null) return null;
     switch (sendStructure.kind) {
       case SendStructureKind.GET:
diff --git a/tests/compiler/dart2js/inference/id_equivalence_test.dart b/tests/compiler/dart2js/inference/id_equivalence_test.dart
index 033e690..73e1725 100644
--- a/tests/compiler/dart2js/inference/id_equivalence_test.dart
+++ b/tests/compiler/dart2js/inference/id_equivalence_test.dart
@@ -55,7 +55,8 @@
     }
   }
 
-  elementMap.forEach((Id id, AstElement element) {
+  elementMap.forEach((Id id, _element) {
+    AstElement element = _element;
     ir.Node irNode = irMap[id];
     Expect.equals(kernel.elementToIr(element), irNode,
         "Element mismatch on $id = $element");
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart
index a7252ca..e518df2 100644
--- a/tests/compiler/dart2js/inference/inference_test_helper.dart
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart
@@ -24,15 +24,17 @@
 /// annotation. Any [Id] left in the map will be reported as missing.
 checkCode(String annotatedCode, CheckMemberFunction checkMember,
     {List<String> options: const <String>[]}) async {
-  AnnotatedCode code = new AnnotatedCode.fromText(annotatedCode, '/*', '*/');
+  AnnotatedCode code =
+      new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd);
   Map<Id, String> expectedMap = computeExpectedMap(code);
   Compiler compiler = compilerFor(
       memorySourceFiles: {'main.dart': code.sourceCode}, options: options);
   compiler.stopAfterTypeInference = true;
   Uri mainUri = Uri.parse('memory:main.dart');
   await compiler.run(mainUri);
-  LibraryElement mainApp = compiler.mainApp;
-  mainApp.forEachLocalMember((member) {
+  LibraryElement mainApp =
+      compiler.frontendStrategy.elementEnvironment.mainLibrary;
+  mainApp.forEachLocalMember((dynamic member) {
     if (member.isClass) {
       member.forEachLocalMember((member) {
         checkMember(compiler, expectedMap, member);
diff --git a/tests/compiler/dart2js/instantiated_classes_test.dart b/tests/compiler/dart2js/instantiated_classes_test.dart
index b270135..f511379 100644
--- a/tests/compiler/dart2js/instantiated_classes_test.dart
+++ b/tests/compiler/dart2js/instantiated_classes_test.dart
@@ -7,7 +7,8 @@
 import 'dart:async';
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/elements/entities.dart' show ClassEntity;
+import 'package:compiler/src/elements/entities.dart'
+    show ClassEntity, LibraryEntity;
 import 'type_test_helper.dart';
 
 void main() {
@@ -89,12 +90,14 @@
   mainSource.write('}');
   return TypeEnvironment
       .create(source, mainSource: mainSource.toString(), useMockCompiler: true)
-      .then((env) {
+      .then((dynamic env) {
+    LibraryEntity mainLibrary =
+        env.compiler.frontendStrategy.elementEnvironment.mainLibrary;
     Iterable<ClassEntity> expectedClasses =
         directlyInstantiatedClasses.map(env.getElement);
     Iterable<ClassEntity> actualClasses = env
         .compiler.resolutionWorldBuilder.directlyInstantiatedClasses
-        .where((c) => c.library == env.compiler.mainApp);
+        .where((c) => c.library == mainLibrary);
     Expect.setEquals(expectedClasses, actualClasses);
   });
 }
diff --git a/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart b/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
index c278eb5..a8616b4 100644
--- a/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
+++ b/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
@@ -4,8 +4,6 @@
 
 library tests.dart2js.interop_anonymous_unreachable_test;
 
-import 'dart:async';
-
 import 'package:test/test.dart';
 import 'compiler_helper.dart';
 
diff --git a/tests/compiler/dart2js/issue13354_test.dart b/tests/compiler/dart2js/issue13354_test.dart
index cf87020..7a25451 100644
--- a/tests/compiler/dart2js/issue13354_test.dart
+++ b/tests/compiler/dart2js/issue13354_test.dart
@@ -43,7 +43,7 @@
         }
 
         checkReturnInClass(String className, String methodName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
diff --git a/tests/compiler/dart2js/js_constant_test.dart b/tests/compiler/dart2js/js_constant_test.dart
index 3ebf646..341edbc 100644
--- a/tests/compiler/dart2js/js_constant_test.dart
+++ b/tests/compiler/dart2js/js_constant_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
 import 'compiler_helper.dart';
 
 const String TEST_1 = r"""
diff --git a/tests/compiler/dart2js/js_model/model_test.dart b/tests/compiler/dart2js/js_model/model_test.dart
index b561418..0a24b74 100644
--- a/tests/compiler/dart2js/js_model/model_test.dart
+++ b/tests/compiler/dart2js/js_model/model_test.dart
@@ -44,6 +44,6 @@
     Flags.disableTypeInference
   ], beforeRun: (Compiler compiler) {
     compiler.backendStrategy = new JsBackendStrategy(compiler);
-  });
+  }, printSteps: true);
   Expect.isFalse(compiler1.compilationFailed);
 }
diff --git a/tests/compiler/dart2js/js_parser_statements_test.dart b/tests/compiler/dart2js/js_parser_statements_test.dart
index 72d53e1..709b957 100644
--- a/tests/compiler/dart2js/js_parser_statements_test.dart
+++ b/tests/compiler/dart2js/js_parser_statements_test.dart
@@ -28,7 +28,7 @@
     }
 
     void action() {
-      jsAst.Node node = js.statement(statement, arguments);
+      js.statement(statement, arguments);
     }
 
     Expect.throws(action, doCheck);
diff --git a/tests/compiler/dart2js/js_spec_optimization_test.dart b/tests/compiler/dart2js/js_spec_optimization_test.dart
index 457a90a..0e60675 100644
--- a/tests/compiler/dart2js/js_spec_optimization_test.dart
+++ b/tests/compiler/dart2js/js_spec_optimization_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
 import 'compiler_helper.dart';
 
 const String TEST_1 = r"""
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
index 6b24ecb..821b25c 100644
--- a/tests/compiler/dart2js/jsinterop/world_test.dart
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -6,10 +6,8 @@
 
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/common.dart';
 import 'package:compiler/src/elements/elements.dart' show ClassElement;
 import 'package:compiler/src/elements/names.dart';
-import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/universe/selector.dart';
 import 'package:compiler/src/world.dart';
 import '../type_test_helper.dart';
@@ -90,7 +88,6 @@
     }
 
     ClosedWorld world = env.closedWorld;
-    JavaScriptBackend backend = env.compiler.backend;
     ClassElement Object_ = registerClass(world.commonElements.objectClass);
     ClassElement Interceptor =
         registerClass(world.commonElements.jsInterceptorClass);
diff --git a/tests/compiler/dart2js/kernel/class_hierarchy_test.dart b/tests/compiler/dart2js/kernel/class_hierarchy_test.dart
index 2e63e59..72e4fe2 100644
--- a/tests/compiler/dart2js/kernel/class_hierarchy_test.dart
+++ b/tests/compiler/dart2js/kernel/class_hierarchy_test.dart
@@ -7,7 +7,6 @@
 
 import 'package:compiler/src/commandline_options.dart' show Flags;
 import 'package:compiler/src/compiler.dart' show Compiler;
-import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:compiler/src/library_loader.dart' show LoadedLibraries;
 import 'package:kernel/ast.dart' as ir;
@@ -60,6 +59,7 @@
         }
       }
       fail('Class $name not found.');
+      throw "Not reachable.";
     }
 
     ir.Class classS = getClass('S');
diff --git a/tests/compiler/dart2js/kernel/closed_world2_test.dart b/tests/compiler/dart2js/kernel/closed_world2_test.dart
index 7ea0ad9..219ce62 100644
--- a/tests/compiler/dart2js/kernel/closed_world2_test.dart
+++ b/tests/compiler/dart2js/kernel/closed_world2_test.dart
@@ -13,7 +13,6 @@
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/elements/resolution_types.dart';
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/enqueue.dart';
 import 'package:compiler/src/js_backend/backend_usage.dart';
@@ -148,10 +147,12 @@
   checkBackendUsage(backendUsage1, backendUsage2, strategy);
 
   checkResolutionEnqueuers(backendUsage1, backendUsage2, enqueuer1, enqueuer2,
-      elementEquivalence: equivalence.entityEquivalence,
-      typeEquivalence: (ResolutionDartType a, DartType b) {
-    return equivalence.typeEquivalence(unalias(a), b);
-  }, elementFilter: elementFilter, verbose: arguments.verbose);
+      elementEquivalence: (a, b) => equivalence.entityEquivalence(a, b),
+      typeEquivalence: (DartType a, DartType b) {
+        return equivalence.typeEquivalence(unalias(a), b);
+      },
+      elementFilter: elementFilter,
+      verbose: arguments.verbose);
 
   checkClosedWorlds(closedWorld1, closedWorld2,
       strategy: equivalence.defaultStrategy, verbose: arguments.verbose);
diff --git a/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart b/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
index 8e951de..c2daf13 100644
--- a/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
+++ b/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
@@ -13,7 +13,6 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/elements/resolution_types.dart';
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/enqueue.dart';
 import 'package:compiler/src/kernel/element_map.dart';
@@ -143,10 +142,13 @@
       equivalence.defaultStrategy);
 
   checkResolutionEnqueuers(closedWorld1.backendUsage, closedWorld2.backendUsage,
-      enqueuer1, enqueuer2, elementEquivalence: equivalence.entityEquivalence,
-      typeEquivalence: (ResolutionDartType a, DartType b) {
-    return equivalence.typeEquivalence(unalias(a), b);
-  }, elementFilter: elementFilter, verbose: arguments.verbose);
+      enqueuer1, enqueuer2,
+      elementEquivalence: (a, b) => equivalence.entityEquivalence(a, b),
+      typeEquivalence: (DartType a, DartType b) {
+        return equivalence.typeEquivalence(unalias(a), b);
+      },
+      elementFilter: elementFilter,
+      verbose: arguments.verbose);
 
   checkClosedWorlds(closedWorld1, closedWorld2,
       strategy: equivalence.defaultStrategy, verbose: arguments.verbose);
diff --git a/tests/compiler/dart2js/kernel/closed_world_test.dart b/tests/compiler/dart2js/kernel/closed_world_test.dart
index fc918140..7c7cfcd 100644
--- a/tests/compiler/dart2js/kernel/closed_world_test.dart
+++ b/tests/compiler/dart2js/kernel/closed_world_test.dart
@@ -10,28 +10,20 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/common/backend_api.dart';
-import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/common/work.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/elements/resolution_types.dart';
-import 'package:compiler/src/elements/elements.dart';
-import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/enqueue.dart';
 import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_backend/backend_usage.dart';
 import 'package:compiler/src/js_backend/interceptor_data.dart';
 import 'package:compiler/src/js_backend/resolution_listener.dart';
 import 'package:compiler/src/js_backend/type_variable_handler.dart';
-import 'package:compiler/src/ssa/kernel_impact.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
 import 'package:compiler/src/universe/world_builder.dart';
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/world.dart';
-import 'impact_test.dart';
 import '../memory_compiler.dart';
 import '../serialization/helper.dart';
-import '../serialization/model_test_helper.dart';
 import '../equivalence/check_functions.dart';
 import 'test_helpers.dart';
 
@@ -117,9 +109,7 @@
     BackendUsage backendUsage = backendUsageBuilder.close();
     checkResolutionEnqueuers(
         backendUsage, backendUsage, compiler.enqueuer.resolution, enqueuer,
-        typeEquivalence: (ResolutionDartType a, ResolutionDartType b) {
-      return areTypesEquivalent(unalias(a), unalias(b));
-    },
+        typeEquivalence: (a, b) => areTypesEquivalent(unalias(a), unalias(b)),
         elementFilter: elementFilter,
         verbose: arguments.verbose,
         // TODO(johnniwinther): Support class usage testing in presence of
diff --git a/tests/compiler/dart2js/kernel/compile_from_dill_test.dart b/tests/compiler/dart2js/kernel/compile_from_dill_test.dart
index b2ef74b..1350587 100644
--- a/tests/compiler/dart2js/kernel/compile_from_dill_test.dart
+++ b/tests/compiler/dart2js/kernel/compile_from_dill_test.dart
@@ -14,7 +14,6 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/elements/resolution_types.dart';
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/kernel/element_map.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
@@ -141,13 +140,17 @@
   checkBackendUsage(closedWorld1.backendUsage, closedWorld2.backendUsage,
       equivalence.defaultStrategy);
 
+  print('--- checking resolution enqueuers ----------------------------------');
   checkResolutionEnqueuers(closedWorld1.backendUsage, closedWorld2.backendUsage,
       compiler1.enqueuer.resolution, compiler2.enqueuer.resolution,
-      elementEquivalence: equivalence.entityEquivalence,
-      typeEquivalence: (ResolutionDartType a, DartType b) {
-    return equivalence.typeEquivalence(unalias(a), b);
-  }, elementFilter: elementFilter, verbose: arguments.verbose);
+      elementEquivalence: (a, b) => equivalence.entityEquivalence(a, b),
+      typeEquivalence: (DartType a, DartType b) {
+        return equivalence.typeEquivalence(unalias(a), b);
+      },
+      elementFilter: elementFilter,
+      verbose: arguments.verbose);
 
+  print('--- checking closed worlds -----------------------------------------');
   checkClosedWorlds(closedWorld1, closedWorld2,
       strategy: equivalence.defaultStrategy,
       verbose: arguments.verbose,
@@ -158,13 +161,17 @@
   // TODO(johnniwinther): Perform equivalence tests on the model: codegen world
   // impacts, program model, etc.
 
+  print('--- checking codegen enqueuers--------------------------------------');
   checkCodegenEnqueuers(compiler1.enqueuer.codegenEnqueuerForTesting,
       compiler2.enqueuer.codegenEnqueuerForTesting,
-      elementEquivalence: equivalence.entityEquivalence,
-      typeEquivalence: (ResolutionDartType a, DartType b) {
-    return equivalence.typeEquivalence(unalias(a), b);
-  }, elementFilter: elementFilter, verbose: arguments.verbose);
+      elementEquivalence: (a, b) => equivalence.entityEquivalence(a, b),
+      typeEquivalence: (DartType a, DartType b) {
+        return equivalence.typeEquivalence(unalias(a), b);
+      },
+      elementFilter: elementFilter,
+      verbose: arguments.verbose);
 
+  print('--- checking output------- -----------------------------------------');
   collector1.outputMap
       .forEach((OutputType outputType, Map<String, BufferedOutputSink> map1) {
     if (outputType == OutputType.sourceMap) {
diff --git a/tests/compiler/dart2js/kernel/compiler_helper.dart b/tests/compiler/dart2js/kernel/compiler_helper.dart
index ba8ab72..bea95fa 100644
--- a/tests/compiler/dart2js/kernel/compiler_helper.dart
+++ b/tests/compiler/dart2js/kernel/compiler_helper.dart
@@ -139,11 +139,8 @@
   }
 }
 
-Future<Compiler> compileWithDill(
-    Uri entryPoint, Map<String, String> memorySourceFiles, List<String> options,
-    {bool printSteps: false,
-    CompilerOutput compilerOutput,
-    void beforeRun(Compiler compiler)}) async {
+Future createTemp(Uri entryPoint, Map<String, String> memorySourceFiles,
+    {bool printSteps: false}) async {
   if (memorySourceFiles.isNotEmpty) {
     Directory dir = await Directory.systemTemp.createTemp('dart2js-with-dill');
     if (printSteps) {
@@ -166,6 +163,16 @@
     '--platform=$buildDir/$configuration/patched_dart2js_sdk/platform.dill',
     '$entryPoint'
   ]);
+  return dillFile;
+}
+
+Future<Compiler> compileWithDill(
+    Uri entryPoint, Map<String, String> memorySourceFiles, List<String> options,
+    {bool printSteps: false,
+    CompilerOutput compilerOutput,
+    void beforeRun(Compiler compiler)}) async {
+  Uri dillFile =
+      await createTemp(entryPoint, memorySourceFiles, printSteps: printSteps);
 
   if (printSteps) {
     print('---- compile from dill $dillFile ---------------------------------');
diff --git a/tests/compiler/dart2js/kernel/constructors_test.dart b/tests/compiler/dart2js/kernel/constructors_test.dart
index bc5b8cc..1acb688 100644
--- a/tests/compiler/dart2js/kernel/constructors_test.dart
+++ b/tests/compiler/dart2js/kernel/constructors_test.dart
@@ -70,7 +70,8 @@
 }
 
 defaultConstructorFor(String className) => (Compiler compiler) {
-      LibraryElement mainApp = compiler.mainApp;
+      LibraryElement mainApp =
+          compiler.frontendStrategy.elementEnvironment.mainLibrary;
       ClassElement clazz = mainApp.find(className);
       return clazz.lookupDefaultConstructor();
     };
diff --git a/tests/compiler/dart2js/kernel/helper.dart b/tests/compiler/dart2js/kernel/helper.dart
index 65f219d..d64c48c 100644
--- a/tests/compiler/dart2js/kernel/helper.dart
+++ b/tests/compiler/dart2js/kernel/helper.dart
@@ -33,7 +33,8 @@
       memorySourceFiles: {'main.dart': code}, options: options);
   expect(result.isSuccess, isTrue);
   Compiler compiler = result.compiler;
-  LibraryElement mainApp = compiler.mainApp;
+  LibraryElement mainApp =
+      compiler.frontendStrategy.elementEnvironment.mainLibrary;
   Element element;
   if (lookup is String) {
     element = mainApp.find(lookup);
diff --git a/tests/compiler/dart2js/kernel/impact_test.dart b/tests/compiler/dart2js/kernel/impact_test.dart
index 32a8303..9aee852 100644
--- a/tests/compiler/dart2js/kernel/impact_test.dart
+++ b/tests/compiler/dart2js/kernel/impact_test.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
 import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/kernel/element_map.dart';
@@ -748,10 +749,11 @@
         new KernelToElementMapImpl(compiler.reporter, compiler.environment);
     kernelElementMap.addProgram(backend.kernelTask.program);
 
-    checkLibrary(compiler, kernelElementMap, compiler.mainApp,
-        fullTest: fullTest);
-    compiler.libraryLoader.libraries.forEach((LibraryElement library) {
-      if (library == compiler.mainApp) return;
+    LibraryElement mainApp =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary;
+    checkLibrary(compiler, kernelElementMap, mainApp, fullTest: fullTest);
+    compiler.libraryLoader.libraries.forEach((LibraryEntity library) {
+      if (library == mainApp) return;
       checkLibrary(compiler, kernelElementMap, library, fullTest: fullTest);
     });
   });
@@ -760,10 +762,12 @@
 void checkLibrary(Compiler compiler, KernelToElementMapMixin elementMap,
     LibraryElement library,
     {bool fullTest: false}) {
-  library.forEachLocalMember((AstElement element) {
+  library.forEachLocalMember((_element) {
+    AstElement element = _element;
     if (element.isClass) {
       ClassElement cls = element;
-      cls.forEachLocalMember((AstElement member) {
+      cls.forEachLocalMember((_member) {
+        AstElement member = _member;
         checkElement(compiler, elementMap, member, fullTest: fullTest);
       });
     } else if (element.isTypedef) {
@@ -863,7 +867,7 @@
                 }
               }
               if (constructor.resolvedAst.kind == ResolvedAstKind.PARSED) {
-                var function = constructor.resolvedAst.node;
+                dynamic function = constructor.resolvedAst.node;
                 if (function.initializers != null) {
                   TreeElements elements = constructor.resolvedAst.elements;
                   for (var initializer in function.initializers) {
diff --git a/tests/compiler/dart2js/kernel/run_from_dill_test.dart b/tests/compiler/dart2js/kernel/run_from_dill_test.dart
new file mode 100644
index 0000000..2d28c68
--- /dev/null
+++ b/tests/compiler/dart2js/kernel/run_from_dill_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// Test that we can compile from dill and run the generated code with d8.
+library dart2js.kernel.run_from_dill_test;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/dart2js.dart' as dart2js;
+import 'package:compiler/src/filenames.dart';
+
+import 'compiler_helper.dart';
+import '../sourcemaps/stacktrace_test.dart';
+import '../serialization/helper.dart';
+
+const SOURCE = const {
+  'main.dart': '''
+main() {
+  print('Hello World!');
+}
+'''
+};
+
+main(List<String> args) {
+  asyncTest(() async {
+    await mainInternal(args);
+  });
+}
+
+enum ResultKind { crashes, errors, warnings, success, failure }
+
+Future<ResultKind> mainInternal(List<String> args,
+    {bool skipWarnings: false, bool skipErrors: false}) async {
+  Arguments arguments = new Arguments.from(args);
+  Uri entryPoint;
+  Map<String, String> memorySourceFiles;
+  if (arguments.uri != null) {
+    entryPoint = arguments.uri;
+    memorySourceFiles = const <String, String>{};
+  } else {
+    entryPoint = Uri.parse('memory:main.dart');
+    memorySourceFiles = SOURCE;
+  }
+
+  Uri dillFile =
+      await createTemp(entryPoint, memorySourceFiles, printSteps: true);
+  String output = uriPathToNative(dillFile.resolve('out.js').path);
+  List<String> dart2jsArgs = [
+    dillFile.toString(),
+    '-o$output',
+    Flags.loadFromDill,
+    Flags.disableTypeInference,
+    Flags.disableInlining,
+    Flags.enableAssertMessage
+  ];
+  print('Running: dart2js ${dart2jsArgs.join(' ')}');
+
+  await dart2js.internalMain(dart2jsArgs);
+
+  print('---- run from dill --------------------------------------------');
+  ProcessResult runResult = Process.runSync(d8executable,
+      ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]);
+  String out = '${runResult.stderr}\n${runResult.stdout}';
+  print('d8 output:');
+  print(out);
+  Expect.equals(0, runResult.exitCode);
+
+  return ResultKind.success;
+}
diff --git a/tests/compiler/dart2js/kernel/test_helpers.dart b/tests/compiler/dart2js/kernel/test_helpers.dart
index 87994cb..052a3be 100644
--- a/tests/compiler/dart2js/kernel/test_helpers.dart
+++ b/tests/compiler/dart2js/kernel/test_helpers.dart
@@ -254,6 +254,7 @@
 
   @override
   ResolutionDartType visit(ResolutionDartType type, [_]) =>
+      // ignore: ARGUMENT_TYPE_NOT_ASSIGNABLE
       type.accept(this, null);
 
   @override
diff --git a/tests/compiler/dart2js/kernel/visitor_test.dart b/tests/compiler/dart2js/kernel/visitor_test.dart
index 8c78f75..661c134 100644
--- a/tests/compiler/dart2js/kernel/visitor_test.dart
+++ b/tests/compiler/dart2js/kernel/visitor_test.dart
@@ -105,7 +105,7 @@
   var loadedLibraries =
       await compiler.libraryLoader.loadLibrary(Uri.parse('dart:core'));
   compiler.processLoadedLibraries(loadedLibraries);
-  var core = loadedLibraries.rootLibrary;
+  dynamic core = loadedLibraries.rootLibrary;
   compiler.startResolution();
   var cls = core.implementation.localLookup('Iterator');
   cls.ensureResolved(compiler.resolution);
diff --git a/tests/compiler/dart2js/least_upper_bound_test.dart b/tests/compiler/dart2js/least_upper_bound_test.dart
index dab1188..6cdbb02 100644
--- a/tests/compiler/dart2js/least_upper_bound_test.dart
+++ b/tests/compiler/dart2js/least_upper_bound_test.dart
@@ -7,7 +7,7 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
-import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
+import 'package:compiler/src/elements/elements.dart' show ClassElement;
 
 import 'type_test_helper.dart';
 
diff --git a/tests/compiler/dart2js/library_resolution_test.dart b/tests/compiler/dart2js/library_resolution_test.dart
index d2e3c46..7487a13 100644
--- a/tests/compiler/dart2js/library_resolution_test.dart
+++ b/tests/compiler/dart2js/library_resolution_test.dart
@@ -6,8 +6,6 @@
 /// library. This only matters for dart:-libraries, so this test mocks up two
 /// dart:-libraries.
 
-import "dart:io";
-
 import "dart:async";
 
 import "memory_source_file_helper.dart";
diff --git a/tests/compiler/dart2js/list_tracer2_test.dart b/tests/compiler/dart2js/list_tracer2_test.dart
index 215b84a..2bf1bd4 100644
--- a/tests/compiler/dart2js/list_tracer2_test.dart
+++ b/tests/compiler/dart2js/list_tracer2_test.dart
@@ -7,7 +7,7 @@
 
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
-import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/types/types.dart' show ContainerTypeMask;
 
 import 'compiler_helper.dart';
 import 'type_mask_test_helper.dart';
diff --git a/tests/compiler/dart2js/list_tracer3_test.dart b/tests/compiler/dart2js/list_tracer3_test.dart
index 599933c3..5d9182f 100644
--- a/tests/compiler/dart2js/list_tracer3_test.dart
+++ b/tests/compiler/dart2js/list_tracer3_test.dart
@@ -7,7 +7,7 @@
 
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
-import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/types/types.dart' show ContainerTypeMask;
 
 import 'compiler_helper.dart';
 import 'type_mask_test_helper.dart';
diff --git a/tests/compiler/dart2js/location_collector_test.dart b/tests/compiler/dart2js/location_collector_test.dart
index d35f8b1..d34f636 100644
--- a/tests/compiler/dart2js/location_collector_test.dart
+++ b/tests/compiler/dart2js/location_collector_test.dart
@@ -14,6 +14,7 @@
 test(List events, Map<int, List<int>> expectedPositions) {
   BufferedOutputSink sink = new BufferedOutputSink();
   LocationProvider locationProvider = new LocationCollector();
+  // ignore: LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
   CodeOutput output = new StreamCodeOutput(sink, [locationProvider]);
   for (var event in events) {
     if (event is String) {
diff --git a/tests/compiler/dart2js/members_test.dart b/tests/compiler/dart2js/members_test.dart
index 170ff6b..88131a8 100644
--- a/tests/compiler/dart2js/members_test.dart
+++ b/tests/compiler/dart2js/members_test.dart
@@ -194,7 +194,6 @@
           .then((env) {
         ResolutionInterfaceType bool_ = env['bool'];
         ResolutionInterfaceType String_ = env['String'];
-        ResolutionInterfaceType num_ = env['num'];
         ResolutionInterfaceType int_ = env['int'];
         ResolutionDynamicType dynamic_ = env['dynamic'];
         ResolutionVoidType void_ = env['void'];
@@ -454,7 +453,6 @@
         ResolutionDynamicType dynamic_ = env['dynamic'];
         ResolutionVoidType void_ = env['void'];
         ResolutionInterfaceType num_ = env['num'];
-        ResolutionInterfaceType int_ = env['int'];
 
         ResolutionInterfaceType A = env['A'];
         ResolutionInterfaceType B = env['B'];
@@ -622,9 +620,6 @@
     abstract class C extends A implements B {}
     """).then((env) {
         ResolutionDynamicType dynamic_ = env['dynamic'];
-        ResolutionVoidType void_ = env['void'];
-        ResolutionInterfaceType num_ = env['num'];
-        ResolutionInterfaceType int_ = env['int'];
 
         ResolutionInterfaceType A = env['A'];
         ResolutionInterfaceType B = env['B'];
@@ -676,9 +671,6 @@
     abstract class C<U, V> extends Object with A<U> implements B<V> {}
     """).then((env) {
         ResolutionDynamicType dynamic_ = env['dynamic'];
-        ResolutionVoidType void_ = env['void'];
-        ResolutionInterfaceType num_ = env['num'];
-        ResolutionInterfaceType int_ = env['int'];
 
         ClassElement A = env.getElement('A');
         ClassElement B = env.getElement('B');
@@ -748,12 +740,8 @@
     abstract class C extends Object with B {}
     """).then((env) {
         ResolutionDynamicType dynamic_ = env['dynamic'];
-        ResolutionVoidType void_ = env['void'];
-        ResolutionInterfaceType num_ = env['num'];
-        ResolutionInterfaceType int_ = env['int'];
 
         ResolutionInterfaceType A = env['A'];
-        ResolutionInterfaceType B = env['B'];
         ResolutionInterfaceType C = env['C'];
 
         // Ensure that members have been computed on all classes.
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index a33e77f..f196912 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -35,8 +35,8 @@
   const MultiDiagnostics([this.diagnosticsList = const []]);
 
   @override
-  void report(Message message, Uri uri, int begin, int end, String text,
-      Diagnostic kind) {
+  void report(covariant Message message, Uri uri, int begin, int end,
+      String text, Diagnostic kind) {
     for (CompilerDiagnostics diagnostics in diagnosticsList) {
       diagnostics.report(message, uri, begin, end, text, kind);
     }
@@ -173,9 +173,9 @@
     Types types = cachedCompiler.types;
     compiler.types = types.copy(compiler.resolution);
     Map copiedLibraries = {};
-    cachedCompiler.libraryLoader.libraries.forEach((library) {
+    cachedCompiler.libraryLoader.libraries.forEach((dynamic library) {
       if (library.isPlatformLibrary) {
-        var libraryLoader = compiler.libraryLoader;
+        dynamic libraryLoader = compiler.libraryLoader;
         libraryLoader.mapLibrary(library);
         copiedLibraries[library.canonicalUri] = library;
       }
@@ -203,7 +203,7 @@
     cachedCompiler.patchParser = null;
     cachedCompiler.libraryLoader = null;
     cachedCompiler.resolver = null;
-    cachedCompiler.closureToClassMapper = null;
+    cachedCompiler.closureDataLookup = null;
     cachedCompiler.checker = null;
     cachedCompiler.globalInference = null;
     cachedCompiler.backend = null;
diff --git a/tests/compiler/dart2js/message_kind_helper.dart b/tests/compiler/dart2js/message_kind_helper.dart
index 8e348ac8..86e6081 100644
--- a/tests/compiler/dart2js/message_kind_helper.dart
+++ b/tests/compiler/dart2js/message_kind_helper.dart
@@ -113,7 +113,7 @@
           messageFound,
           '${template.kind}} does not match any in\n '
           '${messages.join('\n ')}');
-      var reporter = compiler.reporter;
+      dynamic reporter = compiler.reporter;
       Expect.isFalse(reporter.hasCrashed);
       if (!unexpectedMessages.isEmpty) {
         for (CollectedMessage message in unexpectedMessages) {
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index bcf9ef5..d1e94a6 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -89,7 +89,7 @@
                    }
                    main() {}""";
 
-  analyzeAndCheck(source3, 'Foo', (compiler, element) {
+  analyzeAndCheck(source3, 'Foo', (compiler, dynamic element) {
     compiler.enqueuer.resolution.queueIsClosed = false;
     Expect.equals(0, element.metadata.length);
     element.ensureResolved(compiler.resolution);
@@ -115,7 +115,7 @@
                    }
                    main() {}""";
 
-  analyzeAndCheck(source4, 'Foo', (compiler, element) {
+  analyzeAndCheck(source4, 'Foo', (compiler, dynamic element) {
     compiler.enqueuer.resolution.queueIsClosed = false;
     Expect.equals(0, element.metadata.length);
     element.ensureResolved(compiler.resolution);
@@ -197,32 +197,32 @@
               library foo;
               const native = 'xyz';
               main() {}""";
-  compileAndCheckLibrary(source, (e) => e.libraryTag.metadata);
+  compileAndCheckLibrary(source, (dynamic e) => e.libraryTag.metadata);
 
   source = """@native
               import 'lib.dart';
               const native = 'xyz';
               main() {}""";
-  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);
+  compileAndCheckLibrary(source, (dynamic e) => e.tags.single.metadata);
 
   source = """@native
               export 'lib.dart';
               const native = 'xyz';
               main() {}""";
-  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);
+  compileAndCheckLibrary(source, (dynamic e) => e.tags.single.metadata);
 
   source = """@native
               part 'part.dart';
               const native = 'xyz';
               main() {}""";
-  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);
+  compileAndCheckLibrary(source, (dynamic e) => e.tags.single.metadata);
 
   source = """@native
               part 'part.dart';
               const native = 'xyz';
               main() {}""";
   compileAndCheckLibrary(
-      source, (e) => e.compilationUnits.first.partTag.metadata);
+      source, (dynamic e) => e.compilationUnits.first.partTag.metadata);
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/minimal_resolution_test.dart b/tests/compiler/dart2js/minimal_resolution_test.dart
index 483c612..a571f55 100644
--- a/tests/compiler/dart2js/minimal_resolution_test.dart
+++ b/tests/compiler/dart2js/minimal_resolution_test.dart
@@ -9,7 +9,6 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/enqueue.dart';
-import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:expect/expect.dart';
 import 'memory_compiler.dart';
 
diff --git a/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart b/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
index 0c4193f..ebeb829 100644
--- a/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
+++ b/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
@@ -40,9 +40,9 @@
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
 
-    var superclass =
+    dynamic superclass =
         findElement(compiler, 'Super', Uri.parse('memory:lib.dart'));
-    var subclass = findElement(compiler, 'Subclass');
+    dynamic subclass = findElement(compiler, 'Subclass');
     var oracle = compiler.backend.mirrorsData.isMemberAccessibleByReflection;
     print(superclass.lookupMember('_private'));
     Expect.isTrue(oracle(superclass.lookupMember('_private')));
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index f1758a3..5238472 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -97,7 +97,10 @@
       compiler.resolution.commonElements.nullClass,
       compiler.resolution.commonElements.listClass
     ];
-    Iterable<String> nativeNames = nativeClasses.map(backend.namer.className);
+    Iterable<String> nativeNames =
+        // `backend.namer.className` returns a Name, but a String is required.
+        // ignore: ARGUMENT_TYPE_NOT_ASSIGNABLE
+        nativeClasses.map((c) => backend.namer.className(c));
     expectedNames = expectedNames.map(backend.namer.asName).toList();
     expectedNames.addAll(nativeNames);
 
@@ -110,10 +113,12 @@
       ..addAll(fullEmitter.mangledGlobalFieldNames.keys);
     Expect.setEquals(new Set.from(expectedNames), recordedNames);
 
-    for (var library in compiler.libraryLoader.libraries) {
+    for (dynamic library in compiler.libraryLoader.libraries) {
       library.forEachLocalMember((member) {
         if (member.isClass) {
-          if (library == compiler.mainApp && member.name == 'Foo') {
+          if (library ==
+                  compiler.frontendStrategy.elementEnvironment.mainLibrary &&
+              member.name == 'Foo') {
             Expect.isTrue(
                 compiler.backend.mirrorsData
                     .isClassAccessibleByReflection(member),
diff --git a/tests/compiler/dart2js/mixin_typevariable_test.dart b/tests/compiler/dart2js/mixin_typevariable_test.dart
index deb26ab..ec29f20 100644
--- a/tests/compiler/dart2js/mixin_typevariable_test.dart
+++ b/tests/compiler/dart2js/mixin_typevariable_test.dart
@@ -8,7 +8,7 @@
 import "package:async_helper/async_helper.dart";
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
-import "package:compiler/src/elements/elements.dart" show Element, ClassElement;
+import "package:compiler/src/elements/elements.dart" show ClassElement;
 
 void main() {
   testMixinSupertypes();
@@ -33,7 +33,6 @@
         ClassElement S = env.getElement('S');
         ClassElement M1 = env.getElement('M1');
         ClassElement M2 = env.getElement('M2');
-        ClassElement M3 = env.getElement('M3');
         ClassElement C1 = env.getElement('C1');
         ClassElement C2 = env.getElement('C2');
 
@@ -112,11 +111,6 @@
         ClassElement F1 = env.getElement('F1');
         ClassElement F2 = env.getElement('F2');
 
-        ClassElement C1_A_B = C1.superclass;
-        ClassElement D1_A_B = D1.superclass;
-        ClassElement E1_A_B = E1.superclass;
-        ClassElement F1_A_B = F1.superclass;
-
         void testSupertypes(ClassElement element,
             Map<ClassElement, List<ResolutionDartType>> typeArguments) {
           if (element != Object) {
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 928223d..0f59366 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -18,7 +18,6 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/elements/visitor.dart';
 import 'package:compiler/src/library_loader.dart' show LoadedLibraries;
-import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:compiler/src/js_backend/lookup_map_analysis.dart'
     show LookupMapResolutionAnalysis;
 import 'package:compiler/src/io/source_file.dart';
@@ -67,6 +66,7 @@
   final ResolvedUriTranslator resolvedUriTranslator =
       new MockResolvedUriTranslator();
   final Measurer measurer = new Measurer();
+  LibraryElement mainApp;
 
   MockCompiler.internal(
       {Map<String, String> coreSource,
@@ -153,7 +153,7 @@
     }).then((_) => uri);
   }
 
-  Future run(Uri uri, [String mainSource = ""]) {
+  Future<bool> run(Uri uri, [String mainSource = ""]) {
     return init(mainSource).then((Uri mainUri) {
       return super.run(uri == null ? mainUri : uri);
     }).then((result) {
@@ -290,7 +290,7 @@
 }
 
 class MockResolvedUriTranslator implements ResolvedUriTranslator {
-  static final _emptySet = new Set();
+  static final dynamic _emptySet = new Set();
 
   Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
           Spannable spannable) =>
diff --git a/tests/compiler/dart2js/modulo_remainder_test.dart b/tests/compiler/dart2js/modulo_remainder_test.dart
index eeec8593..aef3238 100644
--- a/tests/compiler/dart2js/modulo_remainder_test.dart
+++ b/tests/compiler/dart2js/modulo_remainder_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'compiler_helper.dart';
 
diff --git a/tests/compiler/dart2js/needs_no_such_method_test.dart b/tests/compiler/dart2js/needs_no_such_method_test.dart
index 7368038..96199a8 100644
--- a/tests/compiler/dart2js/needs_no_such_method_test.dart
+++ b/tests/compiler/dart2js/needs_no_such_method_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:compiler/src/common.dart';
 import 'package:compiler/src/elements/elements.dart' show ClassElement;
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/universe/call_structure.dart';
diff --git a/tests/compiler/dart2js/no_such_method_enabled_test.dart b/tests/compiler/dart2js/no_such_method_enabled_test.dart
index 286635d..81a5d1d 100644
--- a/tests/compiler/dart2js/no_such_method_enabled_test.dart
+++ b/tests/compiler/dart2js/no_such_method_enabled_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 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
@@ -279,8 +278,8 @@
 
   // Test [NoSuchMethodResolver] results for each method.
   for (NoSuchMethodInfo info in test.methods) {
-    ClassEntity cls =
-        elementEnvironment.lookupClass(compiler.mainApp, info.className);
+    ClassEntity cls = elementEnvironment.lookupClass(
+        elementEnvironment.mainLibrary, info.className);
     Expect.isNotNull(cls, "Class ${info.className} not found.");
     FunctionEntity noSuchMethod =
         elementEnvironment.lookupClassMember(cls, 'noSuchMethod');
@@ -289,8 +288,8 @@
     if (info.superClassName == null) {
       Expect.equals(ObjectNSM, resolver.getSuperNoSuchMethod(noSuchMethod));
     } else {
-      ClassEntity superclass =
-          elementEnvironment.lookupClass(compiler.mainApp, info.superClassName);
+      ClassEntity superclass = elementEnvironment.lookupClass(
+          elementEnvironment.mainLibrary, info.superClassName);
       Expect.isNotNull(
           superclass, "Superclass ${info.superClassName} not found.");
       FunctionEntity superNoSuchMethod =
@@ -317,8 +316,8 @@
   // the [NoSuchMethodResolver] results which are therefore tested for all
   // methods first.
   for (NoSuchMethodInfo info in test.methods) {
-    ClassEntity cls =
-        elementEnvironment.lookupClass(compiler.mainApp, info.className);
+    ClassEntity cls = elementEnvironment.lookupClass(
+        elementEnvironment.mainLibrary, info.className);
     Expect.isNotNull(cls, "Class ${info.className} not found.");
     FunctionEntity noSuchMethod =
         elementEnvironment.lookupClassMember(cls, 'noSuchMethod');
diff --git a/tests/compiler/dart2js/output_collector.dart b/tests/compiler/dart2js/output_collector.dart
index c81cb99..a5c1cdb 100644
--- a/tests/compiler/dart2js/output_collector.dart
+++ b/tests/compiler/dart2js/output_collector.dart
@@ -6,7 +6,6 @@
 
 library output_collector;
 
-import 'dart:async';
 import 'package:compiler/compiler_new.dart';
 
 class BufferedOutputSink implements OutputSink {
diff --git a/tests/compiler/dart2js/override_inheritance_test.dart b/tests/compiler/dart2js/override_inheritance_test.dart
index d1bf4f0..4777f47 100644
--- a/tests/compiler/dart2js/override_inheritance_test.dart
+++ b/tests/compiler/dart2js/override_inheritance_test.dart
@@ -27,7 +27,7 @@
   return MockCompiler.create((MockCompiler compiler) {
     compiler.diagnosticHandler = createHandler(compiler, source);
     compiler.parseScript(source);
-    var mainApp = compiler.mainApp;
+    dynamic mainApp = compiler.mainApp;
     var cls = mainApp.find('Class');
     cls.ensureResolved(compiler.resolution);
     MembersCreator.computeAllClassMembers(compiler.resolution, cls);
diff --git a/tests/compiler/dart2js/package_root_test.dart b/tests/compiler/dart2js/package_root_test.dart
index d9b36ad..1552a81 100644
--- a/tests/compiler/dart2js/package_root_test.dart
+++ b/tests/compiler/dart2js/package_root_test.dart
@@ -10,8 +10,7 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:compiler/compiler.dart'
-    show DiagnosticHandler, Diagnostic, PackagesDiscoveryProvider;
+import 'package:compiler/compiler.dart' show PackagesDiscoveryProvider;
 import 'package:compiler/src/diagnostics/messages.dart' show MessageKind;
 import 'package:package_config/packages.dart';
 
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index 2dbeced..b789b06 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -7,6 +7,7 @@
 import 'package:expect/expect.dart';
 
 import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/id_generator.dart';
 import 'package:compiler/src/tree/tree.dart';
 import 'package:compiler/src/parser/element_listener.dart';
@@ -37,6 +38,8 @@
 export 'package:compiler/src/parser/diet_parser_task.dart';
 export 'package:front_end/src/fasta/scanner/token_constants.dart';
 
+import 'mock_compiler.dart';
+
 class LoggerCanceler extends DiagnosticReporter {
   DiagnosticOptions get options => const MockDiagnosticOptions();
 
@@ -44,7 +47,7 @@
     print(message);
   }
 
-  void internalError(node, String message) {
+  void internalError(Spannable node, message) {
     log(message);
   }
 
@@ -77,7 +80,7 @@
     infos.forEach(log);
   }
 
-  withCurrentElement(Element element, f()) => f();
+  withCurrentElement(Entity element, f()) => f();
 
   @override
   DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
@@ -115,7 +118,7 @@
 Node parseStatement(String text) =>
     parseBodyCode(text, (parser, tokens) => parser.parseStatement(tokens));
 
-Node parseFunction(String text, Compiler compiler) {
+Node parseFunction(String text, MockCompiler compiler) {
   ElementX element = parseUnit(text, compiler, compiler.mainApp).head;
   Expect.isNotNull(element);
   Expect.equals(ElementKind.FUNCTION, element.kind);
diff --git a/tests/compiler/dart2js/partial_parser_test.dart b/tests/compiler/dart2js/partial_parser_test.dart
index 5acb840..22acb66 100644
--- a/tests/compiler/dart2js/partial_parser_test.dart
+++ b/tests/compiler/dart2js/partial_parser_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import 'options_helper.dart';
 import 'parser_helper.dart';
 
 void main() {
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 805fa93..ad2f485 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -39,7 +39,7 @@
 }
 
 void expectHasBody(compiler, ElementX element) {
-  var node = element.parseNode(compiler.parsingContext);
+  dynamic node = element.parseNode(compiler.parsingContext);
   Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
   Expect.isNotNull(node.body);
   // If the element has a body it is either a Block or a Return statement,
@@ -49,7 +49,7 @@
 }
 
 void expectHasNoBody(compiler, ElementX element) {
-  var node = element.parseNode(compiler.parsingContext);
+  dynamic node = element.parseNode(compiler.parsingContext);
   Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
   Expect.isFalse(node.hasBody);
 }
@@ -61,7 +61,7 @@
     bool expectIsGetter: false,
     bool expectIsFound: true,
     bool expectIsRegular: false}) {
-  var element = lookup(name);
+  dynamic element = lookup(name);
   if (!expectIsFound) {
     Expect.isNull(element);
     return element;
@@ -119,7 +119,7 @@
 }
 
 Future testPatchFunction() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       "external test();", "@patch test() { return 'string'; } ");
   ensure(compiler, "test", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true, checkHasBody: true);
@@ -135,7 +135,7 @@
 }
 
 Future testPatchFunctionMetadata() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       const a = 0;
       @a external test();
@@ -164,7 +164,7 @@
 }
 
 Future testPatchFunctionGeneric() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       "external T test<T>();", "@patch T test<T>() { return null; } ");
   Element origin = ensure(
       compiler, "test", compiler.resolution.commonElements.coreLibrary.find,
@@ -182,7 +182,7 @@
 }
 
 Future testPatchFunctionGenericExtraTypeVariable() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       "external T test<T>();", "@patch T test<T, S>() { return null; } ");
   Element origin = ensure(
       compiler, "test", compiler.resolution.commonElements.coreLibrary.find,
@@ -201,7 +201,7 @@
 }
 
 Future testPatchFunctionGenericDifferentNames() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       "external T test<T, S>();", "@patch T test<S, T>() { return null; } ");
   Element origin = ensure(
       compiler, "test", compiler.resolution.commonElements.coreLibrary.find,
@@ -220,7 +220,7 @@
 }
 
 Future testPatchConstructor() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         external Class();
@@ -231,21 +231,21 @@
         @patch Class();
       }
       """);
-  var classOrigin = ensure(
+  dynamic classOrigin = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   classOrigin.ensureResolved(compiler.resolution);
-  var classPatch = ensure(compiler, "Class",
+  dynamic classPatch = ensure(compiler, "Class",
       compiler.resolution.commonElements.coreLibrary.patch.find,
       expectIsPatch: true);
 
   Expect.equals(classPatch, classOrigin.patch);
   Expect.equals(classOrigin, classPatch.origin);
 
-  var constructorOrigin = ensure(
+  dynamic constructorOrigin = ensure(
       compiler, "", (name) => classOrigin.localLookup(name),
       expectIsPatched: true);
-  var constructorPatch = ensure(
+  dynamic constructorPatch = ensure(
       compiler, "", (name) => classPatch.localLookup(name),
       expectIsPatch: true);
 
@@ -260,7 +260,7 @@
 }
 
 Future testPatchRedirectingConstructor() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         Class(x) : this._(x, false);
@@ -273,24 +273,24 @@
         @patch Class._(x, y) { print('$x,$y'); }
       }
       """);
-  var classOrigin = ensure(
+  dynamic classOrigin = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   classOrigin.ensureResolved(compiler.resolution);
 
-  var classPatch = ensure(compiler, "Class",
+  dynamic classPatch = ensure(compiler, "Class",
       compiler.resolution.commonElements.coreLibrary.patch.find,
       expectIsPatch: true);
 
   Expect.equals(classOrigin, classPatch.origin);
   Expect.equals(classPatch, classOrigin.patch);
 
-  var constructorRedirecting =
+  dynamic constructorRedirecting =
       ensure(compiler, "", (name) => classOrigin.localLookup(name));
-  var constructorOrigin = ensure(
+  dynamic constructorOrigin = ensure(
       compiler, "_", (name) => classOrigin.localLookup(name),
       expectIsPatched: true);
-  var constructorPatch = ensure(
+  dynamic constructorPatch = ensure(
       compiler, "_", (name) => classPatch.localLookup(name),
       expectIsPatch: true);
   Expect.equals(constructorOrigin, constructorPatch.origin);
@@ -306,7 +306,7 @@
 }
 
 Future testPatchMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         external String toString();
@@ -317,7 +317,7 @@
         @patch String toString() => 'string';
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -338,7 +338,7 @@
 }
 
 Future testPatchGetter() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         external int get field;
@@ -349,7 +349,7 @@
         @patch int get field => 5;
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -366,7 +366,7 @@
 }
 
 Future testRegularMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         void regular() {}
@@ -376,7 +376,7 @@
       @patch class Class {
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -397,7 +397,7 @@
 }
 
 Future testInjectedMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
       }
@@ -407,7 +407,7 @@
         void _injected() {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -428,7 +428,7 @@
 }
 
 Future testInjectedPublicMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
       }
@@ -438,7 +438,7 @@
         void injected() {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -461,7 +461,7 @@
 }
 
 Future testInjectedFunction() async {
-  var compiler = await applyPatch("", "int _function() => 5;");
+  dynamic compiler = await applyPatch("", "int _function() => 5;");
   ensure(compiler, "_function",
       compiler.resolution.commonElements.coreLibrary.find,
       expectIsFound: false);
@@ -477,7 +477,7 @@
 }
 
 Future testInjectedPublicFunction() async {
-  var compiler = await applyPatch("", "int function() => 5;");
+  dynamic compiler = await applyPatch("", "int function() => 5;");
   ensure(
       compiler, "function", compiler.resolution.commonElements.coreLibrary.find,
       expectIsFound: false);
@@ -495,7 +495,7 @@
 }
 
 Future testPatchSignatureCheck() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         external String method1();
@@ -526,7 +526,7 @@
         @patch void method11({int str}) {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.ensureResolved(compiler.resolution);
@@ -571,14 +571,14 @@
 }
 
 Future testExternalWithoutImplementationTopLevel() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external void foo();
       """,
       """
       // @patch void foo() {}
       """);
-  var function = ensure(
+  dynamic function = ensure(
       compiler, "foo", compiler.resolution.commonElements.coreLibrary.find);
   compiler.resolver.resolve(function);
   DiagnosticCollector collector = compiler.diagnosticCollector;
@@ -593,7 +593,7 @@
 }
 
 Future testExternalWithoutImplementationMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         external void foo();
@@ -604,7 +604,7 @@
         // @patch void foo() {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -623,7 +623,7 @@
 }
 
 Future testIsSubclass() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class A {}
       """,
@@ -640,7 +640,7 @@
 }
 
 Future testPatchNonExistingTopLevel() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       // class Class {}
       """,
@@ -657,7 +657,7 @@
 }
 
 Future testPatchNonExistingMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {}
       """,
@@ -666,7 +666,7 @@
         @patch void foo() {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -681,7 +681,7 @@
 }
 
 Future testPatchNonPatchablePatch() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external get foo;
       """,
@@ -700,7 +700,7 @@
 }
 
 Future testPatchNonPatchableOrigin() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external var foo;
       """,
@@ -724,7 +724,7 @@
 }
 
 Future testPatchNonExternalTopLevel() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       void foo() {}
       """,
@@ -744,7 +744,7 @@
 }
 
 Future testPatchNonExternalMember() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class Class {
         void foo() {}
@@ -755,7 +755,7 @@
         @patch void foo() {}
       }
       """);
-  var container = ensure(
+  dynamic container = ensure(
       compiler, "Class", compiler.resolution.commonElements.coreLibrary.find,
       expectIsPatched: true);
   container.parseNode(compiler.parsingContext);
@@ -773,7 +773,7 @@
 }
 
 Future testPatchNonClass() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external void Class() {}
       """,
@@ -793,7 +793,7 @@
 }
 
 Future testPatchNonGetter() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external void foo() {}
       """,
@@ -813,7 +813,7 @@
 }
 
 Future testPatchNoGetter() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external set foo(var value) {}
       """,
@@ -833,7 +833,7 @@
 }
 
 Future testPatchNonSetter() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external void foo() {}
       """,
@@ -853,7 +853,7 @@
 }
 
 Future testPatchNoSetter() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external get foo;
       """,
@@ -873,7 +873,7 @@
 }
 
 Future testPatchNonFunction() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       external get foo;
       """,
@@ -893,7 +893,7 @@
 }
 
 Future testPatchAndSelector() async {
-  var compiler = await applyPatch(
+  dynamic compiler = await applyPatch(
       """
       class A {
         external void clear();
@@ -915,7 +915,8 @@
       """,
       runCompiler: true,
       analyzeOnly: true);
-  compiler.closeResolution();
+  compiler.closeResolution(
+      compiler.frontendStrategy.elementEnvironment.mainFunction);
   ClosedWorld world = compiler.resolutionWorldBuilder.closedWorldForTesting;
 
   ClassElement cls = ensure(
@@ -968,7 +969,7 @@
       expectedWarnings = <MessageKind>[expectedWarnings];
     }
 
-    var compiler =
+    dynamic compiler =
         await applyPatch('', patchText, analyzeAll: true, analyzeOnly: true);
     compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
     await compiler.run(null);
@@ -1030,10 +1031,11 @@
     }
     """;
 
-  var compiler = await applyPatch(origin, patch,
+  dynamic compiler = await applyPatch(origin, patch,
       analyzeAll: true, analyzeOnly: true, runCompiler: true);
   ClassElement clsA = compiler.resolution.commonElements.coreLibrary.find("A");
   ClassElement clsB = compiler.resolution.commonElements.coreLibrary.find("B");
+  Expect.isNotNull(clsB);
 
   ConstructorElement forward = clsA.lookupConstructor("forward");
   ConstructorElement target = forward.effectiveTarget;
@@ -1068,7 +1070,7 @@
                        String s = 0;
                      }
                      """;
-  var compiler = await applyPatch(originText, patchText,
+  dynamic compiler = await applyPatch(originText, patchText,
       analyzeAll: true, analyzeOnly: true);
   compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
   await compiler.run(null);
diff --git a/tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package.dart b/tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package.dart
index 3a8acff..03ffa18 100644
--- a/tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package.dart
+++ b/tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package.dart
@@ -2,8 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// ignore: URI_DOES_NOT_EXIST
 import 'package:simple/simple.dart';
 
 main() {
+  // ignore: UNDEFINED_FUNCTION
   print(foo());
 }
diff --git a/tests/compiler/dart2js/quarantined/http_test.dart b/tests/compiler/dart2js/quarantined/http_test.dart
index 1132029..d28805f 100644
--- a/tests/compiler/dart2js/quarantined/http_test.dart
+++ b/tests/compiler/dart2js/quarantined/http_test.dart
@@ -50,7 +50,6 @@
 
 void checkNotFound(ProcessResult result, String filename) {
   Expect.notEquals(0, result.exitCode);
-  File outFile = new File(outFilePath);
   Expect.isTrue(result.stdout.contains("404"));
   Expect.isTrue(result.stdout.contains(filename));
 }
@@ -164,13 +163,19 @@
 void initializeSSL() {
   Uri pathOfPkcert = pathOfData.resolve('pkcert');
   String testPkcertDatabase = pathOfPkcert.toFilePath();
+  // Issue 29926.
+  // ignore: UNDEFINED_METHOD
   SecureSocket.initialize(database: testPkcertDatabase, password: 'dartdart');
 }
 
 Future testHttps() {
   initializeSSL();
   return HttpServer
+      // Issue 29926.
+      // ignore: NOT_ENOUGH_REQUIRED_ARGUMENTS
       .bindSecure(InternetAddress.LOOPBACK_IP_V4, 0,
+          // Issue 29926.
+          // ignore: UNDEFINED_NAMED_PARAMETER
           certificateName: 'localhost_cert')
       .then((HttpServer server) => serverRunning(server, "https"));
 }
diff --git a/tests/compiler/dart2js/reexport_handled_test.dart b/tests/compiler/dart2js/reexport_handled_test.dart
index 8a7c6f7..b153fe8 100644
--- a/tests/compiler/dart2js/reexport_handled_test.dart
+++ b/tests/compiler/dart2js/reexport_handled_test.dart
@@ -7,8 +7,6 @@
 import "package:expect/expect.dart";
 import "package:async_helper/async_helper.dart";
 import 'mock_compiler.dart';
-import 'package:compiler/src/elements/elements.dart'
-    show Element, LibraryElement;
 
 final exportingLibraryUri = Uri.parse('exporting.dart');
 const String EXPORTING_LIBRARY_SOURCE = '''
@@ -40,7 +38,7 @@
 
         // Load reexporting library when exports are handled on the exporting library.
         return compiler.libraryLoader.loadLibrary(reexportingLibraryUri);
-      }).then((loadedLibraries) {
+      }).then((dynamic loadedLibraries) {
         compiler.processLoadedLibraries(loadedLibraries);
         var foo = loadedLibraries.rootLibrary.findExported('foo');
         Expect.isNotNull(foo);
diff --git a/tests/compiler/dart2js/related_types.dart b/tests/compiler/dart2js/related_types.dart
index 580dd14..9ae51bc 100644
--- a/tests/compiler/dart2js/related_types.dart
+++ b/tests/compiler/dart2js/related_types.dart
@@ -36,7 +36,8 @@
 
 /// Check all loaded libraries in [compiler] for unrelated types.
 void checkRelatedTypes(Compiler compiler) {
-  compiler.closeResolution();
+  compiler.closeResolution(
+      compiler.frontendStrategy.elementEnvironment.mainFunction);
   for (LibraryElement library in compiler.libraryLoader.libraries) {
     checkLibraryElement(compiler, library);
   }
@@ -47,7 +48,8 @@
   library.forEachLocalMember((Element element) {
     if (element.isClass) {
       ClassElement cls = element;
-      cls.forEachLocalMember((MemberElement member) {
+      cls.forEachLocalMember((_member) {
+        MemberElement member = _member;
         checkMemberElement(compiler, member);
       });
     } else if (!element.isTypedef) {
diff --git a/tests/compiler/dart2js/related_types_test.dart b/tests/compiler/dart2js/related_types_test.dart
index 89ee01a..ecc40d0 100644
--- a/tests/compiler/dart2js/related_types_test.dart
+++ b/tests/compiler/dart2js/related_types_test.dart
@@ -7,6 +7,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/elements/elements.dart';
@@ -267,9 +268,12 @@
     Expect.isFalse(
         collector.hasRegularMessages, "Unexpected analysis messages.");
     Compiler compiler = result.compiler;
-    compiler.closeResolution();
+    ElementEnvironment elementEnvironment =
+        compiler.frontendStrategy.elementEnvironment;
+    compiler.closeResolution(elementEnvironment.mainFunction);
 
-    void checkMember(MemberElement member) {
+    void checkMember(Element element) {
+      MemberElement member = element;
       if (!member.name.startsWith('test_')) return;
 
       collector.clear();
@@ -283,7 +287,7 @@
           "for $member.");
     }
 
-    LibraryElement mainApp = compiler.mainApp;
+    LibraryElement mainApp = elementEnvironment.mainLibrary;
     mainApp.forEachLocalMember((Element element) {
       if (element.isClass) {
         ClassElement cls = element;
diff --git a/tests/compiler/dart2js/resolution_test.dart b/tests/compiler/dart2js/resolution_test.dart
index a0afddf..d3bfc9a 100644
--- a/tests/compiler/dart2js/resolution_test.dart
+++ b/tests/compiler/dart2js/resolution_test.dart
@@ -94,7 +94,7 @@
 
 void test(String code, void check(CompilerImpl compiler)) {
   Uri uri = new Uri(scheme: 'source');
-  var compiler = compilerFor(code, uri);
+  dynamic compiler = compilerFor(code, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         check(compiler);
       }));
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index f16e481..9bbfe8e 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -134,8 +134,6 @@
 class Bar extends Foo implements X<Bar> {}
 """);
       compiler.resolveStatement("Bar bar;");
-      LibraryElement mainApp = compiler.mainApp;
-      ClassElement classBar = mainApp.find("Bar");
       DiagnosticCollector collector = compiler.diagnosticCollector;
       Expect.equals(0, collector.warnings.length);
       Expect.equals(1, collector.errors.length);
@@ -289,7 +287,6 @@
           (funElement as FunctionElementX).parseNode(compiler.parsingContext);
       visitor.visit(function.body);
       Map mapping = map(visitor);
-      List<Element> values = mapping.values.toList();
       DiagnosticCollector collector = compiler.diagnosticCollector;
       Expect.equals(0, mapping.length);
       Expect.equals(0, collector.warnings.length);
@@ -628,11 +625,6 @@
     // correctly.
     compiler.parseScript("abstract class Bar {}");
 
-    ResolverVisitor visitor = new ResolverVisitor(
-        compiler.resolution,
-        null,
-        new ResolutionRegistry(
-            compiler.backend.target, new CollectingTreeElements(null)));
     compiler.resolveStatement("Foo bar;");
 
     LibraryElement mainApp = compiler.mainApp;
diff --git a/tests/compiler/dart2js/serialization/analysis_test_helper.dart b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
index 00d19e6..64c7c52 100644
--- a/tests/compiler/dart2js/serialization/analysis_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
@@ -8,7 +8,6 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/filenames.dart';
 import '../memory_compiler.dart';
 import 'helper.dart';
diff --git a/tests/compiler/dart2js/serialization/compilation_test_helper.dart b/tests/compiler/dart2js/serialization/compilation_test_helper.dart
index 44807dc..05f76b2 100644
--- a/tests/compiler/dart2js/serialization/compilation_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test_helper.dart
@@ -34,7 +34,6 @@
           resolutionInputs: result.serializedData.toUris(),
           sourceFiles: result.serializedData.toMemorySourceFiles());
     } else {
-      Uri entryPoint = Uri.parse('memory:main.dart');
       await arguments.forEachTest(serializedData, TESTS, compile);
     }
     printMeasurementResults();
diff --git a/tests/compiler/dart2js/serialization/duplicate_library_test.dart b/tests/compiler/dart2js/serialization/duplicate_library_test.dart
index 290a704..854cc0a 100644
--- a/tests/compiler/dart2js/serialization/duplicate_library_test.dart
+++ b/tests/compiler/dart2js/serialization/duplicate_library_test.dart
@@ -4,16 +4,12 @@
 
 library dart2js.serialization.duplicate_libraryc_test;
 
-import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common/names.dart';
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/filenames.dart';
 import '../memory_compiler.dart';
 import 'helper.dart';
-import 'test_data.dart';
 
 void main(List<String> args) {
   asyncTest(() async {
diff --git a/tests/compiler/dart2js/serialization/members_test.dart b/tests/compiler/dart2js/serialization/members_test.dart
index ac7a508..0ef66a6 100644
--- a/tests/compiler/dart2js/serialization/members_test.dart
+++ b/tests/compiler/dart2js/serialization/members_test.dart
@@ -57,9 +57,11 @@
 }
 
 /// Check equivalence of members of [class1] and [class2].
-void checkMembers(Compiler compiler1, ClassMemberMixin class1,
-    Compiler compiler2, ClassMemberMixin class2,
+void checkMembers(
+    Compiler compiler1, Element _class1, Compiler compiler2, Element _class2,
     {bool verbose: false}) {
+  ClassMemberMixin class1 = _class1;
+  ClassMemberMixin class2 = _class2;
   if (verbose) {
     print('Checking $class1 vs $class2');
   }
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index b23cb1e..8c901d6 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -9,6 +9,7 @@
 import 'package:expect/expect.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/deferred_load.dart';
@@ -50,7 +51,6 @@
           resolutionInputs:
               serializedData.toUris(result.serializedData.toUris()));
     } else {
-      Uri entryPoint = Uri.parse('memory:main.dart');
       await arguments.forEachTest(serializedData, TESTS, checkModels);
     }
     printMeasurementResults();
@@ -71,7 +71,9 @@
         memorySourceFiles: sourceFiles, options: [Flags.analyzeOnly]);
     compilerNormal.resolution.retainCachesForTesting = true;
     await compilerNormal.run(entryPoint);
-    compilerNormal.closeResolution();
+    ElementEnvironment elementEnvironment =
+        compilerNormal.frontendStrategy.elementEnvironment;
+    compilerNormal.closeResolution(elementEnvironment.mainFunction);
     return compilerNormal;
   });
 
@@ -83,7 +85,9 @@
         options: [Flags.analyzeOnly]);
     compilerDeserialized.resolution.retainCachesForTesting = true;
     await compilerDeserialized.run(entryPoint);
-    compilerDeserialized.closeResolution();
+    ElementEnvironment elementEnvironment =
+        compilerDeserialized.frontendStrategy.elementEnvironment;
+    compilerDeserialized.closeResolution(elementEnvironment.mainFunction);
     return compilerDeserialized;
   });
 
@@ -160,48 +164,40 @@
   if (element1.isFunction ||
       element1.isConstructor ||
       (element1.isField && element1.isInstanceMember)) {
-    ClosureClassMap closureData1 =
-        compiler1.closureToClassMapper.getClosureToClassMapping(element1);
-    ClosureClassMap closureData2 =
-        compiler2.closureToClassMapper.getClosureToClassMapping(element2);
+    ClosureRepresentationInfo closureData1 =
+        compiler1.closureDataLookup.getClosureRepresentationInfo(element1);
+    ClosureRepresentationInfo closureData2 =
+        compiler2.closureDataLookup.getClosureRepresentationInfo(element2);
 
     checkElementIdentities(
         closureData1,
         closureData2,
-        '$element1.closureElement',
-        closureData1.closureElement,
-        closureData2.closureElement);
+        '$element1.closureEntity',
+        closureData1.closureEntity,
+        closureData2.closureEntity);
     checkElementIdentities(
         closureData1,
         closureData2,
-        '$element1.closureClassElement',
-        closureData1.closureClassElement,
-        closureData2.closureClassElement);
-    checkElementIdentities(closureData1, closureData2, '$element1.callElement',
-        closureData1.callElement, closureData2.callElement);
+        '$element1.closureClassEntity',
+        closureData1.closureClassEntity,
+        closureData2.closureClassEntity);
+    checkElementIdentities(closureData1, closureData2, '$element1.callMethod',
+        closureData1.callMethod, closureData2.callMethod);
     check(closureData1, closureData2, '$element1.thisLocal',
         closureData1.thisLocal, closureData2.thisLocal, areLocalsEquivalent);
-    checkMaps(
-        closureData1.freeVariableMap,
-        closureData2.freeVariableMap,
-        "$element1.freeVariableMap",
-        areLocalsEquivalent,
-        areCapturedVariablesEquivalent,
-        verbose: verbose);
-    checkMaps(
-        closureData1.capturingScopes,
-        closureData2.capturingScopes,
-        "$element1.capturingScopes",
-        areNodesEquivalent,
-        areClosureScopesEquivalent,
-        verbose: verbose,
-        keyToString: nodeToString);
-    checkSets(
-        closureData1.variablesUsedInTryOrGenerator,
-        closureData2.variablesUsedInTryOrGenerator,
-        "$element1.variablesUsedInTryOrGenerator",
-        areLocalsEquivalent,
-        verbose: verbose);
+    checkElementListIdentities(
+        closureData1,
+        closureData2,
+        "$element1.createdFieldEntities",
+        closureData1.createdFieldEntities,
+        closureData2.createdFieldEntities);
+    check(
+        closureData1,
+        closureData2,
+        '$element1.thisFieldEntity',
+        closureData1.thisFieldEntity,
+        closureData2.thisFieldEntity,
+        areLocalsEquivalent);
     if (element1 is MemberElement && element2 is MemberElement) {
       MemberElement member1 = element1.implementation;
       MemberElement member2 = element2.implementation;
diff --git a/tests/compiler/dart2js/serialization/native_data_test.dart b/tests/compiler/dart2js/serialization/native_data_test.dart
index e6d89ad..9343e17 100644
--- a/tests/compiler/dart2js/serialization/native_data_test.dart
+++ b/tests/compiler/dart2js/serialization/native_data_test.dart
@@ -36,7 +36,9 @@
   SerializationResult result = await serialize(uri);
   Compiler compiler1 = result.compiler;
   SerializedData serializedData = result.serializedData;
-  ClosedWorld closedWorld1 = compiler1.closeResolution().closedWorld;
+  var elementEnvironment1 = compiler1.frontendStrategy.elementEnvironment;
+  ClosedWorld closedWorld1 =
+      compiler1.closeResolution(elementEnvironment1.mainFunction).closedWorld;
 
   print('------------------------------------------------------------------');
   print('analyze deserialized: $uri');
@@ -46,7 +48,9 @@
       resolutionInputs: serializedData.toUris(),
       options: [Flags.analyzeAll]);
   await compiler2.run(uri);
-  ClosedWorld closedWorld2 = compiler2.closeResolution().closedWorld;
+  var elementEnvironment2 = compiler2.frontendStrategy.elementEnvironment;
+  ClosedWorld closedWorld2 =
+      compiler2.closeResolution(elementEnvironment2.mainFunction).closedWorld;
 
   JavaScriptBackend backend1 = compiler1.backend;
   JavaScriptBackend backend2 = compiler2.backend;
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index e73f8c0..3b64fa0 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -4,20 +4,6 @@
 
 library dart2js.serialization_test_helper;
 
-import 'dart:collection';
-import 'package:compiler/src/common/resolution.dart';
-import 'package:compiler/src/constants/expressions.dart';
-import 'package:compiler/src/constants/values.dart';
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/elements/elements.dart';
-import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/elements/resolution_types.dart';
-import 'package:compiler/src/elements/types.dart';
-import 'package:compiler/src/kernel/elements.dart';
-import 'package:compiler/src/kernel/element_map_impl.dart';
-import 'package:compiler/src/serialization/equivalence.dart';
-import 'package:compiler/src/util/util.dart';
-import 'package:expect/expect.dart';
 import 'test_data.dart';
 
 /// Returns the test arguments for testing the [index]th skipped test. The
diff --git a/tests/compiler/dart2js/simple_inferrer_callers_test.dart b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
index 6bf7e6a..ac18525 100644
--- a/tests/compiler/dart2js/simple_inferrer_callers_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
@@ -7,6 +7,7 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
+import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
 import 'package:compiler/src/world.dart' show ClosedWorld, ClosedWorldRefiner;
 
@@ -39,18 +40,23 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri, analyzeOnly: true);
   asyncTest(() => compiler.run(uri).then((_) {
-        ClosedWorldRefiner closedWorldRefiner = compiler.closeResolution();
+        ElementEnvironment elementEnvironment =
+            compiler.frontendStrategy.elementEnvironment;
+        ClosedWorldRefiner closedWorldRefiner =
+            compiler.closeResolution(elementEnvironment.mainFunction);
         ClosedWorld closedWorld =
             compiler.resolutionWorldBuilder.closedWorldForTesting;
         var inferrer =
             new MyInferrer(compiler, closedWorld, closedWorldRefiner);
         compiler.globalInference.typesInferrerInternal = inferrer;
         compiler.globalInference.runGlobalTypeInference(
-            compiler.mainFunction, closedWorld, closedWorldRefiner);
+            closedWorld.elementEnvironment.mainFunction,
+            closedWorld,
+            closedWorldRefiner);
         var mainElement = findElement(compiler, 'main');
-        var classA = findElement(compiler, 'A');
+        dynamic classA = findElement(compiler, 'A');
         var fieldA = classA.lookupLocalMember('field');
-        var classB = findElement(compiler, 'B');
+        dynamic classB = findElement(compiler, 'B');
         var fieldB = classB.lookupLocalMember('field');
 
         Expect.isTrue(inferrer.getCallersOf(fieldA).contains(mainElement));
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 39e5811..4899319 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -146,7 +146,7 @@
         checkReturn('returnNum1', closedWorld.commonMasks.numType);
 
         checkReturnInClass(String className, String methodName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
@@ -154,7 +154,7 @@
                   typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
-        var cls = findElement(compiler, 'A');
+        dynamic cls = findElement(compiler, 'A');
         checkReturnInClass(
             'A', 'foo', new TypeMask.nonNullExact(cls, closedWorld));
       }));
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
index c4c9194..458318b 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
@@ -33,10 +33,8 @@
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
-          Expect.equals(
-              type,
-              typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
-              name);
+          dynamic returnType = typesInferrer.getReturnTypeOfElement(element);
+          Expect.equals(type, returnType.simplify(compiler), name);
         }
 
         checkReturn('method', closedWorld.commonMasks.numType);
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
index af85fa9..fad3035 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
@@ -32,7 +32,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
+          dynamic functionElement = findElement(compiler, functionName);
           var signature = functionElement.functionSignature;
           var element = signature.requiredParameters.first;
           Expect.equals(
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
index 2a2fd62..9878710 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
@@ -33,7 +33,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
+          dynamic functionElement = findElement(compiler, functionName);
           var signature = functionElement.functionSignature;
           var element = signature.requiredParameters.first;
           Expect.equals(
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
index 41b5feb..c8bafe6 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
@@ -33,7 +33,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
+          dynamic functionElement = findElement(compiler, functionName);
           var signature = functionElement.functionSignature;
           var element = signature.requiredParameters.first;
           Expect.equals(
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
index ce1cc2c..cd1f33d 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
@@ -46,7 +46,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
+          dynamic functionElement = findElement(compiler, functionName);
           var signature = functionElement.functionSignature;
           var element = signature.requiredParameterCount > 0
               ? signature.requiredParameters.first
@@ -57,16 +57,6 @@
               functionName);
         }
 
-        checkOptionalArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
-          var signature = functionElement.functionSignature;
-          var element = signature.optionalParameters.first;
-          Expect.equals(
-              type,
-              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
-              functionName);
-        }
-
         checkArgument('foo1', closedWorld.commonMasks.functionType);
 
         /// 01: ok
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
index 6183de0..13e6876 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
@@ -42,10 +42,8 @@
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
-          Expect.equals(
-              type,
-              typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
-              name);
+          dynamic returnType = typesInferrer.getReturnTypeOfElement(element);
+          Expect.equals(type, returnType.simplify(compiler), name);
         }
 
         checkReturn('method1', closedWorld.commonMasks.uint31Type);
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index 6967d56..d81f3fc 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -31,7 +31,7 @@
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
 
         checkFieldTypeInClass(String className, String fieldName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(fieldName);
           Expect.isTrue(
               typesInferrer.getTypeOfElement(element).containsOnly(type));
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index c321c54..9c530bd 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -31,7 +31,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkFieldTypeInClass(String className, String fieldName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(fieldName);
           Expect.equals(type,
               simplify(typesInferrer.getTypeOfElement(element), closedWorld));
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 7b14057..9f2ca0e 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -35,7 +35,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkFieldTypeInClass(String className, String fieldName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(fieldName);
           Expect.equals(type,
               simplify(typesInferrer.getTypeOfElement(element), closedWorld));
diff --git a/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart b/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
index 35969e1..f282b76 100644
--- a/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
@@ -32,7 +32,7 @@
         var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
-          var functionElement = findElement(compiler, functionName);
+          dynamic functionElement = findElement(compiler, functionName);
           var signature = functionElement.functionSignature;
           var element = signature.requiredParameters.first;
           Expect.equals(
diff --git a/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
index 430f464..80674f1 100644
--- a/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
@@ -42,10 +42,8 @@
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
-          Expect.equals(
-              type,
-              typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
-              name);
+          dynamic returnType = typesInferrer.getReturnTypeOfElement(element);
+          Expect.equals(type, returnType.simplify(compiler), name);
         }
 
         checkReturn('method1', closedWorld.commonMasks.uint31Type);
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index 27ed1a4..a0f0c5a 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -71,7 +71,7 @@
         var commonMasks = closedWorld.commonMasks;
 
         checkReturnInClass(String className, String methodName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 4731499..9034418 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -829,7 +829,7 @@
         checkReturn('testDoWhile4', commonMasks.numType);
 
         checkReturnInClass(String className, String methodName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
@@ -864,7 +864,7 @@
         checkReturnInClass('C', 'returnInt6', commonMasks.positiveIntType);
 
         checkFactoryConstructor(String className, String factoryName) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.localLookup(factoryName);
           Expect.equals(new TypeMask.nonNullExact(cls, closedWorld),
               typesInferrer.getReturnTypeOfElement(element));
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index 8456a95..9b17e80 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -35,7 +35,7 @@
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
 
         checkReturnInClass(String className, String methodName, type) {
-          var cls = findElement(compiler, className);
+          dynamic cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
         }
diff --git a/tests/compiler/dart2js/size_test.dart b/tests/compiler/dart2js/size_test.dart
index 74f5106..39bc9e9 100644
--- a/tests/compiler/dart2js/size_test.dart
+++ b/tests/compiler/dart2js/size_test.dart
@@ -29,8 +29,6 @@
   asyncTest(() =>
       compileAll(TEST, coreSource: DEFAULT_CORELIB_WITH_LIST).then((generated) {
         return MockCompiler.create((MockCompiler compiler) {
-          var backend = compiler.backend;
-
           // Make sure no class is emitted.
           Expect.isFalse(generated.contains('finishClasses'));
         });
diff --git a/tests/compiler/dart2js/source_map_name_test.dart b/tests/compiler/dart2js/source_map_name_test.dart
index 413efd3..edfc286 100644
--- a/tests/compiler/dart2js/source_map_name_test.dart
+++ b/tests/compiler/dart2js/source_map_name_test.dart
@@ -82,7 +82,8 @@
     CompilationResult result =
         await runCompiler(memorySourceFiles: {'main.dart': SOURCE});
     Compiler compiler = result.compiler;
-    LibraryElement mainApp = compiler.mainApp;
+    LibraryElement mainApp =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary;
 
     Element lookup(String name) {
       Element element;
@@ -104,7 +105,7 @@
       if (lookupName == null) {
         lookupName = expectedName;
       }
-      var element = lookup(lookupName);
+      dynamic element = lookup(lookupName);
       check(element, expectedName);
       if (element.isConstructor) {
         var constructorBody =
diff --git a/tests/compiler/dart2js/source_map_validator_helper.dart b/tests/compiler/dart2js/source_map_validator_helper.dart
index 3e24a80..b171c4c 100644
--- a/tests/compiler/dart2js/source_map_validator_helper.dart
+++ b/tests/compiler/dart2js/source_map_validator_helper.dart
@@ -110,7 +110,8 @@
     });
   }
 
-  compiler.libraryLoader.libraries.forEach((LibraryElement library) {
+  compiler.libraryLoader.libraries.forEach((_library) {
+    LibraryElement library = _library;
     mapCompilationUnits(library);
     if (library.patch != null) {
       mapCompilationUnits(library.patch);
@@ -121,7 +122,6 @@
     for (TargetEntry entry in line.entries) {
       if (entry.sourceNameId != null) {
         Uri uri = mapUri.resolve(sourceMap.urls[entry.sourceUrlId]);
-        Position targetPosition = new Position(line.line, entry.column);
         Position sourcePosition =
             new Position(entry.sourceLine, entry.sourceColumn);
         String name = sourceMap.names[entry.sourceNameId];
@@ -143,8 +143,8 @@
           if (!element.hasNode) return null;
 
           var begin = element.node.getBeginToken().charOffset;
-          var end = element.node.getEndToken();
-          end = end.charOffset + end.charCount;
+          var endToken = element.node.getEndToken();
+          int end = endToken.charOffset + endToken.charCount;
           return new Interval(
               positionFromOffset(begin), positionFromOffset(end));
         }
@@ -161,7 +161,7 @@
 
           if (element is MemberElement) {
             MemberElement member = element;
-            member.nestedClosures.forEach((closure) {
+            member.nestedClosures.forEach((dynamic closure) {
               var localFunction = closure.expression;
               Interval interval = intervalFromElement(localFunction);
               if (interval != null &&
@@ -174,7 +174,8 @@
           return element;
         }
 
-        void match(AstElement element) {
+        void match(Element _element) {
+          AstElement element = _element;
           Interval interval = intervalFromElement(element);
           if (interval != null && interval.contains(sourcePosition)) {
             AstElement innerElement = findInnermost(element);
@@ -207,7 +208,7 @@
           }
         }
 
-        compilationUnit.forEachLocalMember((AstElement element) {
+        compilationUnit.forEachLocalMember((Element element) {
           if (element.isClass) {
             ClassElement classElement = element;
             classElement.forEachLocalMember(match);
diff --git a/tests/compiler/dart2js/source_mapping_test.dart b/tests/compiler/dart2js/source_mapping_test.dart
index bc7928f..d3b8edf 100644
--- a/tests/compiler/dart2js/source_mapping_test.dart
+++ b/tests/compiler/dart2js/source_mapping_test.dart
@@ -23,6 +23,8 @@
     // TODO(floitsch): the outputBuffers are only accessible in the full
     // emitter.
     full.Emitter fullEmitter = backend.emitter.emitter;
+    // CodeOutput isn't assignable to CodeBuffer.
+    // ignore: RETURN_OF_INVALID_TYPE
     return fullEmitter.outputBuffers[compiler.deferredLoadTask.mainOutputUnit];
   });
 }
diff --git a/tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart b/tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart
index be230b5..c1526ee 100644
--- a/tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart
+++ b/tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart
@@ -45,7 +45,7 @@
   counter++;
 }
 
-var toplevelField = () {
+dynamic toplevelField = () {
   counter++;
 };
 
@@ -66,7 +66,7 @@
     counter++;
   }
 
-  var superField = () {
+  dynamic superField = () {
     counter++;
   };
 
@@ -82,7 +82,7 @@
     counter++;
   }
 
-  static var staticField = () {
+  static dynamic staticField = () {
     counter++;
   };
 
@@ -98,7 +98,7 @@
     counter++;
   }
 
-  var instanceField = () {
+  dynamic instanceField = () {
     counter++;
   };
 
diff --git a/tests/compiler/dart2js/sourcemaps/diff_view.dart b/tests/compiler/dart2js/sourcemaps/diff_view.dart
index f84b8c5..b0b2b697 100644
--- a/tests/compiler/dart2js/sourcemaps/diff_view.dart
+++ b/tests/compiler/dart2js/sourcemaps/diff_view.dart
@@ -8,7 +8,6 @@
 import 'dart:convert';
 import 'dart:io';
 
-import 'package:compiler/src/common.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/diagnostics/invariant.dart';
 import 'package:compiler/src/elements/elements.dart';
@@ -16,7 +15,6 @@
 import 'package:compiler/src/io/source_information.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/js/js.dart' as js;
-import 'package:compiler/src/js/js_debug.dart';
 
 import 'diff.dart';
 import 'html_parts.dart';
@@ -147,7 +145,7 @@
   }
 
   @override
-  encodeLineAnnotation(CodeSource lineAnnotation) {
+  encodeLineAnnotation(covariant CodeSource lineAnnotation) {
     if (lineAnnotation != null) {
       return lineAnnotation.toJson();
     }
diff --git a/tests/compiler/dart2js/sourcemaps/html_parts.dart b/tests/compiler/dart2js/sourcemaps/html_parts.dart
index 2691a09..d02e3e5 100644
--- a/tests/compiler/dart2js/sourcemaps/html_parts.dart
+++ b/tests/compiler/dart2js/sourcemaps/html_parts.dart
@@ -162,6 +162,7 @@
         case HtmlPartKind.LINE_NUMBER:
           return LineNumber.fromJson(json, strategy);
       }
+      return null;
     }
   }
 }
@@ -319,12 +320,6 @@
         tail = subsequentCode.substring(1);
       }
 
-      void addForSpan(AnnotationData data) {
-        htmlParts.add(new TagPart(data.tag,
-            properties: data.properties,
-            content: [new HtmlText(subsequentCode)]));
-      }
-
       if (annotationData != null && annotationDataForSpan != null) {
         htmlParts.add(new TagPart(annotationDataForSpan.tag,
             properties: annotationDataForSpan.properties,
diff --git a/tests/compiler/dart2js/sourcemaps/lax_json.dart b/tests/compiler/dart2js/sourcemaps/lax_json.dart
index fb79973..405ecfb 100644
--- a/tests/compiler/dart2js/sourcemaps/lax_json.dart
+++ b/tests/compiler/dart2js/sourcemaps/lax_json.dart
@@ -37,8 +37,6 @@
   static final List<int> FALSE = 'false'.codeUnits;
   static final int N = 'n'.codeUnits.single;
   static final List<int> NULL = 'null'.codeUnits;
-  static final int _0 = '0'.codeUnits.single;
-  static final int _9 = '9'.codeUnits.single;
   static final int B = 'b'.codeUnits.single;
   static final int R = 'r'.codeUnits.single;
   static final int U = 'u'.codeUnits.single;
diff --git a/tests/compiler/dart2js/sourcemaps/mapping_test.dart b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
index 4d84ed0..a0cbf91 100644
--- a/tests/compiler/dart2js/sourcemaps/mapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
@@ -3,21 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
-import 'package:compiler/src/apiimpl.dart';
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:expect/expect.dart';
 import 'package:source_maps/source_maps.dart';
-import 'package:source_maps/src/utils.dart';
 
 import '../annotated_code_helper.dart';
 import '../memory_compiler.dart';
-import '../source_map_validator_helper.dart';
 
 const List<String> TESTS = const <String>[
   '''
diff --git a/tests/compiler/dart2js/sourcemaps/nomapping_test.dart b/tests/compiler/dart2js/sourcemaps/nomapping_test.dart
index fea30b4..04b493d 100644
--- a/tests/compiler/dart2js/sourcemaps/nomapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/nomapping_test.dart
@@ -3,21 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
-import 'package:compiler/src/apiimpl.dart';
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:expect/expect.dart';
 import 'package:source_maps/source_maps.dart';
-import 'package:source_maps/src/utils.dart';
 
-import '../annotated_code_helper.dart';
 import '../memory_compiler.dart';
-import '../source_map_validator_helper.dart';
 
 const List<String> TESTS = const <String>[
   '''
diff --git a/tests/compiler/dart2js/sourcemaps/output_structure.dart b/tests/compiler/dart2js/sourcemaps/output_structure.dart
index 648973a..9f0bccb 100644
--- a/tests/compiler/dart2js/sourcemaps/output_structure.dart
+++ b/tests/compiler/dart2js/sourcemaps/output_structure.dart
@@ -5,7 +5,7 @@
 library sourcemap.output_structure;
 
 import 'dart:math' as Math;
-import 'html_parts.dart' show Annotation, CodeLine, JsonStrategy;
+import 'html_parts.dart' show CodeLine, JsonStrategy;
 
 // Constants used to identify the subsection of the JavaScript output. These
 // are specifically for the unminified full_emitter output.
@@ -183,7 +183,6 @@
 
     String readHeader(CodeLine line) {
       String code = line.code;
-      String ssaLineHeader;
       if (code.startsWith(HEAD)) {
         return code.substring(HEAD.length);
       } else if (code.startsWith(TAIL)) {
@@ -323,6 +322,7 @@
           ..to = to
           ..codeSource = codeSource;
     }
+    throw "Unhandled: $kind";
   }
 }
 
diff --git a/tests/compiler/dart2js/sourcemaps/save.dart b/tests/compiler/dart2js/sourcemaps/save.dart
index 4c2c296..90324fb 100644
--- a/tests/compiler/dart2js/sourcemaps/save.dart
+++ b/tests/compiler/dart2js/sourcemaps/save.dart
@@ -44,7 +44,6 @@
 
 SingleMapping convertFromHumanReadableSourceMap(String json) {
   Map inputMap = lazon.decode(json);
-  String file = inputMap['file'];
   Map urls = inputMap['sources'];
   List<String> sources = new List<String>.filled(urls.length, null);
   urls.forEach((String index, String url) {
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart
index 0fee7e2..b570775 100644
--- a/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart
@@ -11,7 +11,6 @@
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/util/util.dart';
 import 'source_mapping_tester.dart';
-import 'sourcemap_helper.dart';
 import 'sourcemap_html_helper.dart';
 import 'sourcemap_html_templates.dart';
 
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index 31bc0a2..9b6e386 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -9,10 +9,8 @@
 import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/apiimpl.dart' as api;
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/null_compiler_output.dart' show NullSink;
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/helpers/helpers.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/io/code_output.dart';
 import 'package:compiler/src/io/source_file.dart';
@@ -23,7 +21,6 @@
 import 'package:compiler/src/js/js_source_mapping.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/source_file_provider.dart';
-import 'package:kernel/ast.dart' show Location;
 import '../memory_compiler.dart';
 import '../output_collector.dart';
 
@@ -325,7 +322,7 @@
           ..addAll(options));
 
     JavaScriptBackend backend = compiler.backend;
-    var handler = compiler.handler;
+    dynamic handler = compiler.handler;
     SourceFileProvider sourceFileProvider = handler.provider;
     sourceFileManager =
         new ProviderSourceFileManager(sourceFileProvider, outputProvider);
@@ -339,8 +336,8 @@
     Map<Element, SourceMapInfo> elementSourceMapInfos =
         <Element, SourceMapInfo>{};
     if (perElement) {
-      backend.generatedCode
-          .forEach((MemberElement element, js.Expression node) {
+      backend.generatedCode.forEach((_element, js.Expression node) {
+        MemberElement element = _element;
         RecordedSourceInformationProcess subProcess =
             strategy.subProcessForNode(node);
         if (subProcess == null) {
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
index 6a39556..bcaae6f 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
@@ -109,9 +109,9 @@
 }
 
 abstract class CssColorScheme {
-  String singleLocationToCssColor(var id);
+  String singleLocationToCssColor(int id);
 
-  String multiLocationToCssColor(List ids);
+  String multiLocationToCssColor(List<int> ids);
 
   bool get showLocationAsSpan;
 }
@@ -123,12 +123,13 @@
 
   CustomColorScheme(
       {this.showLocationAsSpan: false,
-      String this.single(var id),
-      String this.multi(List ids)});
+      String this.single(int id),
+      String this.multi(List<int> ids)});
 
-  String singleLocationToCssColor(var id) => single != null ? single(id) : null;
+  String singleLocationToCssColor(int id) => single != null ? single(id) : null;
 
-  String multiLocationToCssColor(List ids) => multi != null ? multi(ids) : null;
+  String multiLocationToCssColor(List<int> ids) =>
+      multi != null ? multi(ids) : null;
 }
 
 class PatternCssColorScheme implements CssColorScheme {
@@ -225,11 +226,11 @@
 class ElementScheme {
   const ElementScheme();
 
-  String getName(var id, Set ids) => null;
-  String getHref(var id, Set ids) => null;
-  String onClick(var id, Set ids) => null;
-  String onMouseOver(var id, Set ids) => null;
-  String onMouseOut(var id, Set ids) => null;
+  String getName(int id, Set<int> ids) => null;
+  String getHref(int id, Set<int> ids) => null;
+  String onClick(int id, Set<int> ids) => null;
+  String onMouseOver(int id, Set<int> ids) => null;
+  String onMouseOut(int id, Set<int> ids) => null;
 }
 
 class HighlightLinkScheme implements ElementScheme {
@@ -427,8 +428,6 @@
 /// Computes the HTML information for the [info].
 SourceMapHtmlInfo createHtmlInfo(
     SourceLocationCollection collection, SourceMapInfo info) {
-  js.Node node = info.node;
-  String code = info.code;
   String name = info.name;
   SourceLocationCollection subcollection =
       new SourceLocationCollection(collection);
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
index c9c871c..5d6191a 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -3,12 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
-import 'package:compiler/src/apiimpl.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:expect/expect.dart';
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index 41e2003..127c0e7 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -8,7 +8,7 @@
 import "package:async_helper/async_helper.dart";
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
-import "package:compiler/src/elements/elements.dart" show Element, ClassElement;
+import "package:compiler/src/elements/elements.dart" show ClassElement;
 
 void main() {
   testInterfaceSubtype();
diff --git a/tests/compiler/dart2js/subtypeset_test.dart b/tests/compiler/dart2js/subtypeset_test.dart
index 418e547..55df06f 100644
--- a/tests/compiler/dart2js/subtypeset_test.dart
+++ b/tests/compiler/dart2js/subtypeset_test.dart
@@ -9,7 +9,7 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'type_test_helper.dart';
-import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
+import 'package:compiler/src/elements/elements.dart' show ClassElement;
 import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/world.dart';
 
diff --git a/tests/compiler/dart2js/tdiv_test.dart b/tests/compiler/dart2js/tdiv_test.dart
index 99d0693..73b6ecf 100644
--- a/tests/compiler/dart2js/tdiv_test.dart
+++ b/tests/compiler/dart2js/tdiv_test.dart
@@ -5,7 +5,6 @@
 library tdiv_test;
 
 import 'dart:async';
-import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'compiler_helper.dart';
 
diff --git a/tests/compiler/dart2js/token_naming_test.dart b/tests/compiler/dart2js/token_naming_test.dart
index 3a3248e..03702d0 100644
--- a/tests/compiler/dart2js/token_naming_test.dart
+++ b/tests/compiler/dart2js/token_naming_test.dart
@@ -14,7 +14,7 @@
   return scope.getNextName();
 }
 
-int main() {
+void main() {
   // Test a normal scope.
   TokenScope scope = new TokenScope();
 
diff --git a/tests/compiler/dart2js/trust_type_annotations2_test.dart b/tests/compiler/dart2js/trust_type_annotations2_test.dart
index f688380..71ad9ca 100644
--- a/tests/compiler/dart2js/trust_type_annotations2_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations2_test.dart
@@ -29,7 +29,7 @@
         memorySourceFiles: MEMORY_SOURCE_FILES,
         options: ['--trust-type-annotations']);
     var compiler = result.compiler;
-    var element = compiler.mainFunction;
+    var element = compiler.frontendStrategy.elementEnvironment.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
     Expect.isTrue(code.contains('+'), code);
   });
diff --git a/tests/compiler/dart2js/trust_type_annotations_test.dart b/tests/compiler/dart2js/trust_type_annotations_test.dart
index b793343..f7a390a 100644
--- a/tests/compiler/dart2js/trust_type_annotations_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations_test.dart
@@ -58,8 +58,7 @@
         checkReturn(String name, TypeMask type) {
           var element = classA.lookupMember(name);
           var mask = typesInferrer.getReturnTypeOfElement(element);
-          Expect.isTrue(type.containsMask(
-              typesInferrer.getReturnTypeOfElement(element), closedWorld));
+          Expect.isTrue(type.containsMask(mask, closedWorld));
         }
 
         checkType(String name, type) {
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 0a3ec86..f2b2952 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/elements/modelx.dart'
-    show ClassElementX, CompilationUnitElementX, ElementX, FunctionElementX;
+    show ClassElementX, CompilationUnitElementX, ElementX;
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/resolution/tree_elements.dart'
     show TreeElements, TreeElementMapping;
@@ -22,7 +22,6 @@
 import 'package:compiler/src/util/util.dart';
 
 import 'mock_compiler.dart';
-import 'options_helper.dart';
 import 'parser_helper.dart';
 
 final MessageKind NOT_ASSIGNABLE = MessageKind.NOT_ASSIGNABLE;
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 35ab04d..b5b0c40 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -54,8 +54,10 @@
   final second;
   Pair(this.first, this.second);
   int get hashCode => first.hashCode * 47 + second.hashCode;
-  bool operator ==(Pair other) =>
-      identical(first, other.first) && identical(second, other.second);
+  bool operator ==(other) =>
+      other is Pair &&
+      identical(first, other.first) &&
+      identical(second, other.second);
 }
 
 class RuleSet {
@@ -750,7 +752,7 @@
     WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
     LibraryElement interceptorsLibrary =
         compiler.resolution.commonElements.interceptorsLibrary;
-    interceptorsLibrary.forEachLocalMember((element) {
+    interceptorsLibrary.forEachLocalMember((dynamic element) {
       if (element.isClass) {
         element.ensureResolved(compiler.resolution);
         impactBuilder
@@ -769,7 +771,7 @@
         .registerTypeUse(new TypeUse.instantiation(patternImplClass.rawType));
     compiler.enqueuer.resolution.applyImpact(impactBuilder);
     backend.onResolutionEnd();
-    compiler.closeResolution();
+    compiler.closeResolution(null);
     ClosedWorld closedWorld =
         compiler.resolutionWorldBuilder.closedWorldForTesting;
 
diff --git a/tests/compiler/dart2js/type_equals_test.dart b/tests/compiler/dart2js/type_equals_test.dart
index 85305e0..06af4de 100644
--- a/tests/compiler/dart2js/type_equals_test.dart
+++ b/tests/compiler/dart2js/type_equals_test.dart
@@ -7,12 +7,12 @@
 import 'package:compiler/src/elements/resolution_types.dart';
 import "compiler_helper.dart";
 
-bool test(compiler, String name1, String name2, {bool expect}) {
+test(compiler, String name1, String name2, {bool expect}) {
   Expect.isTrue((expect != null), 'required parameter "expect" not given');
-  var clazz = findElement(compiler, "Class");
+  dynamic clazz = findElement(compiler, "Class");
   clazz.ensureResolved(compiler.resolution);
-  var element1 = clazz.buildScope().lookup(name1);
-  var element2 = clazz.buildScope().lookup(name2);
+  dynamic element1 = clazz.buildScope().lookup(name1);
+  dynamic element2 = clazz.buildScope().lookup(name2);
   Expect.isNotNull(element1);
   Expect.isNotNull(element2);
   Expect.equals(element1.kind, ElementKind.FUNCTION);
diff --git a/tests/compiler/dart2js/type_inference7_test.dart b/tests/compiler/dart2js/type_inference7_test.dart
index e4ec10f..184903b 100644
--- a/tests/compiler/dart2js/type_inference7_test.dart
+++ b/tests/compiler/dart2js/type_inference7_test.dart
@@ -26,14 +26,14 @@
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
     var closedWorld = typesInferrer.closedWorld;
     var commonMasks = closedWorld.commonMasks;
-    var foo = findElement(compiler, "foo");
+    dynamic foo = findElement(compiler, "foo");
     // Return type is null|bool.
     var mask = typesInferrer.getReturnTypeOfElement(foo);
     Expect.isTrue(mask.isNullable);
     Expect.equals(
         commonMasks.boolType, simplify(mask.nonNullable(), closedWorld));
     // First parameter is uint31|String|bool.
-    var mask1 = typesInferrer.getTypeOfElement(foo.parameters[0]);
+    dynamic mask1 = typesInferrer.getTypeOfElement(foo.parameters[0]);
     Expect.isTrue(mask1.isUnion);
     var expectedTypes = new Set.from(
         [commonMasks.uint31Type, commonMasks.stringType, commonMasks.boolType]);
@@ -57,7 +57,7 @@
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
     var closedWorld = typesInferrer.closedWorld;
     var commonMasks = closedWorld.commonMasks;
-    var foo = findElement(compiler, "foo");
+    dynamic foo = findElement(compiler, "foo");
     // Return type is null.
     var mask = typesInferrer.getReturnTypeOfElement(foo);
     Expect.isTrue(mask.isNullable);
diff --git a/tests/compiler/dart2js/type_inference8_test.dart b/tests/compiler/dart2js/type_inference8_test.dart
index bc629d8..9ae1752 100644
--- a/tests/compiler/dart2js/type_inference8_test.dart
+++ b/tests/compiler/dart2js/type_inference8_test.dart
@@ -7,7 +7,6 @@
 import "package:compiler/src/types/types.dart";
 import "package:expect/expect.dart";
 import 'compiler_helper.dart';
-import 'type_mask_test_helper.dart';
 
 import 'dart:async';
 
@@ -43,7 +42,7 @@
     // 'foo' should always return false
     Expect.equals(falseType, mask);
     // the argument to 'bar' is always false
-    var bar = findElement(compiler, "bar");
+    dynamic bar = findElement(compiler, "bar");
     var barArg = bar.parameters.first;
     var barArgMask = typesInferrer.getTypeOfElement(barArg);
     Expect.equals(falseType, barArgMask);
@@ -83,7 +82,7 @@
     var mask = typesInferrer.getReturnTypeOfElement(element);
     // Can't infer value for foo's return type, it could be either true or false
     Expect.identical(commonMasks.boolType, mask);
-    var bar = findElement(compiler, "bar");
+    dynamic bar = findElement(compiler, "bar");
     var barArg = bar.parameters.first;
     var barArgMask = typesInferrer.getTypeOfElement(barArg);
     // The argument to bar should have the same type as the return type of foo
diff --git a/tests/compiler/dart2js/type_mask2_test.dart b/tests/compiler/dart2js/type_mask2_test.dart
index 4a28dce..6aac3a1 100644
--- a/tests/compiler/dart2js/type_mask2_test.dart
+++ b/tests/compiler/dart2js/type_mask2_test.dart
@@ -8,13 +8,14 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'type_test_helper.dart';
-import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
+import 'package:compiler/src/elements/elements.dart' show ClassElement;
 import 'package:compiler/src/types/types.dart';
 import 'package:compiler/src/world.dart' show ClosedWorld;
 
 isCheckedMode() {
   try {
-    var i = 1;
+    dynamic i = 1;
+    // ignore: UNUSED_LOCAL_VARIABLE
     String s = i;
     return false;
   } catch (e) {
@@ -57,7 +58,7 @@
         'Unexpected flattening of $disjoint: '
         '$flattenResult, expected $flattened.');
   }
-  var union = UnionTypeMask.unionOf(masks, closedWorld);
+  dynamic union = UnionTypeMask.unionOf(masks, closedWorld);
   if (result == null) {
     Expect.isTrue(union is UnionTypeMask,
         'Expected union of $masks to be a union-type: $union.');
@@ -219,8 +220,6 @@
   ClassElement String_ = env.getElement("String");
   ClassElement JSString = closedWorld.commonElements.jsStringClass;
 
-  List<ClassElement> allClasses = <ClassElement>[Object_, String_];
-
   Expect.isFalse(closedWorld.isDirectlyInstantiated(Object_));
   Expect.isTrue(closedWorld.isIndirectlyInstantiated(Object_));
   Expect.isTrue(closedWorld.isInstantiated(Object_));
diff --git a/tests/compiler/dart2js/type_mask_disjoint_test.dart b/tests/compiler/dart2js/type_mask_disjoint_test.dart
index 48d3a98..2aabb34 100644
--- a/tests/compiler/dart2js/type_mask_disjoint_test.dart
+++ b/tests/compiler/dart2js/type_mask_disjoint_test.dart
@@ -36,7 +36,7 @@
 
 Uri uri = new Uri(scheme: 'source');
 var compiler = compilerFor(CODE, uri);
-var world = compiler.resolutionWorldBuilder.closedWorldForTesting;
+dynamic world = compiler.resolutionWorldBuilder.closedWorldForTesting;
 
 main() {
   asyncTest(() => compiler.run(uri).then((_) {
diff --git a/tests/compiler/dart2js/type_mask_test.dart b/tests/compiler/dart2js/type_mask_test.dart
index 2209aad..7da68ac 100644
--- a/tests/compiler/dart2js/type_mask_test.dart
+++ b/tests/compiler/dart2js/type_mask_test.dart
@@ -23,10 +23,10 @@
   var compiler = compilerFor(CODE, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var closedWorld = compiler.resolutionWorldBuilder.closedWorldForTesting;
-        var classA = findElement(compiler, 'A');
-        var classB = findElement(compiler, 'B');
-        var classC = findElement(compiler, 'C');
-        var classD = findElement(compiler, 'D');
+        dynamic classA = findElement(compiler, 'A');
+        dynamic classB = findElement(compiler, 'B');
+        dynamic classC = findElement(compiler, 'C');
+        dynamic classD = findElement(compiler, 'D');
 
         var exactA = new TypeMask.nonNullExact(classA, closedWorld);
         var exactB = new TypeMask.nonNullExact(classB, closedWorld);
diff --git a/tests/compiler/dart2js/type_order_test.dart b/tests/compiler/dart2js/type_order_test.dart
index c74a0ff..91b688b 100644
--- a/tests/compiler/dart2js/type_order_test.dart
+++ b/tests/compiler/dart2js/type_order_test.dart
@@ -9,7 +9,7 @@
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
 import "package:compiler/src/elements/elements.dart"
-    show Element, ClassElement, TypedefElement;
+    show ClassElement, TypedefElement;
 
 void main() {
   asyncTest(() => TypeEnvironment.create(r"""
@@ -20,7 +20,7 @@
       class Y {}
       class Z {}
       """).then((env) {
-        List types = [];
+        var types = <ResolutionDartType>[];
         ResolutionDartType add(ResolutionDartType type) {
           types.add(type);
           return type;
@@ -59,7 +59,7 @@
         ResolutionTypeVariableType CT = add(C_this.typeArguments[0]);
         ResolutionTypeVariableType CS = add(C_this.typeArguments[1]);
 
-        Expect.listEquals([
+        Expect.listEquals(<ResolutionDartType>[
           void_,
           dynamic_,
           A_raw,
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index 0a345a6..a637ee8 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -8,13 +8,12 @@
 import "package:async_helper/async_helper.dart";
 import 'type_test_helper.dart';
 import 'package:compiler/src/elements/resolution_types.dart';
+import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/js/js.dart';
 import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
 import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:compiler/src/js_backend/runtime_types.dart'
     show TypeRepresentationGenerator;
-import 'package:compiler/src/types/types.dart';
-import 'package:compiler/src/universe/world_builder.dart';
 
 void main() {
   testTypeRepresentations();
@@ -44,20 +43,17 @@
       m9(int a, String b, {List<int> c, d}) {}
       m10(void f(int a, [b])) {}
       """).then((env) {
-        var closedWorldRefiner = env.compiler.closeResolution();
+        var elementEnvironment =
+            env.compiler.frontendStrategy.elementEnvironment;
+        var closedWorldRefiner =
+            env.compiler.closeResolution(elementEnvironment.mainFunction);
         var closedWorld = closedWorldRefiner.closedWorld;
-        env.compiler.enqueuer.createCodegenEnqueuer(closedWorld);
-        env.compiler.backend.onCodegenStart(
-            closedWorld,
-            new ElementCodegenWorldBuilderImpl(
-                closedWorld.elementEnvironment,
-                env.compiler.backend.nativeBasicData,
-                closedWorld,
-                const TypeMaskStrategy()));
+        env.compiler.startCodegen(closedWorld);
         TypeRepresentationGenerator typeRepresentation =
             new TypeRepresentationGenerator(env.compiler.backend.namer);
 
-        Expression onVariable(ResolutionTypeVariableType variable) {
+        Expression onVariable(TypeVariableType _variable) {
+          ResolutionTypeVariableType variable = _variable;
           return new VariableUse(variable.name);
         }
 
@@ -109,7 +105,6 @@
         ResolutionTypeVariableType Map_K = Map_.typeVariables[0];
         ResolutionTypeVariableType Map_V = Map_.typeVariables[1];
 
-        ResolutionDartType Object_ = env['Object'];
         ResolutionDartType int_ = env['int'];
         ResolutionDartType String_ = env['String'];
         ResolutionDartType dynamic_ = env['dynamic'];
@@ -130,7 +125,6 @@
         String Map_K_rep = stringify(onVariable(Map_K));
         String Map_V_rep = stringify(onVariable(Map_V));
 
-        String Object_rep = getJsName(Object_.element);
         String int_rep = getJsName(int_.element);
         String String_rep = getJsName(String_.element);
 
@@ -231,56 +225,60 @@
             '[$Map_rep, $int_rep, $String_rep]');
 
         // void m1() {}
-        expect(env.getElement('m1').computeType(env.compiler.resolution),
+        expect(computeType(env.getElement('m1'), env.compiler.resolution),
             '{$func: 1, $retvoid: true}');
 
         // int m2() => 0;
-        expect(env.getElement('m2').computeType(env.compiler.resolution),
+        expect(computeType(env.getElement('m2'), env.compiler.resolution),
             '{$func: 1, $ret: $int_rep}');
 
         // List<int> m3() => null;
-        expect(env.getElement('m3').computeType(env.compiler.resolution),
+        expect(computeType(env.getElement('m3'), env.compiler.resolution),
             '{$func: 1, $ret: [$List_rep, $int_rep]}');
 
         // m4() {}
-        expect(env.getElement('m4').computeType(env.compiler.resolution),
+        expect(computeType(env.getElement('m4'), env.compiler.resolution),
             '{$func: 1}');
 
         // m5(int a, String b) {}
-        expect(env.getElement('m5').computeType(env.compiler.resolution),
+        expect(computeType(env.getElement('m5'), env.compiler.resolution),
             '{$func: 1, $args: [$int_rep, $String_rep]}');
 
         // m6(int a, [String b]) {}
         expect(
-            env.getElement('m6').computeType(env.compiler.resolution),
+            computeType(env.getElement('m6'), env.compiler.resolution),
             '{$func: 1, $args: [$int_rep],'
             ' $opt: [$String_rep]}');
 
         // m7(int a, String b, [List<int> c, d]) {}
         expect(
-            env.getElement('m7').computeType(env.compiler.resolution),
+            computeType(env.getElement('m7'), env.compiler.resolution),
             '{$func: 1,'
             ' $args: [$int_rep, $String_rep],'
             ' $opt: [[$List_rep, $int_rep],,]}');
 
         // m8(int a, {String b}) {}
         expect(
-            env.getElement('m8').computeType(env.compiler.resolution),
+            computeType(env.getElement('m8'), env.compiler.resolution),
             '{$func: 1,'
             ' $args: [$int_rep], $named: {b: $String_rep}}');
 
         // m9(int a, String b, {List<int> c, d}) {}
         expect(
-            env.getElement('m9').computeType(env.compiler.resolution),
+            computeType(env.getElement('m9'), env.compiler.resolution),
             '{$func: 1,'
             ' $args: [$int_rep, $String_rep],'
             ' $named: {c: [$List_rep, $int_rep], d: null}}');
 
         // m10(void f(int a, [b])) {}
         expect(
-            env.getElement('m10').computeType(env.compiler.resolution),
+            computeType(env.getElement('m10'), env.compiler.resolution),
             '{$func: 1, $args:'
             ' [{$func: 1,'
             ' $retvoid: true, $args: [$int_rep], $opt: [,]}]}');
       }));
 }
+
+computeType(element, resolution) {
+  return element.computeType(resolution);
+}
diff --git a/tests/compiler/dart2js/type_substitution_test.dart b/tests/compiler/dart2js/type_substitution_test.dart
index 24d4ebd..fcdae4c 100644
--- a/tests/compiler/dart2js/type_substitution_test.dart
+++ b/tests/compiler/dart2js/type_substitution_test.dart
@@ -11,9 +11,9 @@
 import 'type_test_helper.dart';
 
 ResolutionDartType getType(compiler, String name) {
-  var clazz = findElement(compiler, "Class");
+  dynamic clazz = findElement(compiler, "Class");
   clazz.ensureResolved(compiler.resolution);
-  var element = clazz.buildScope().lookup(name);
+  dynamic element = clazz.buildScope().lookup(name);
   Expect.isNotNull(element);
   Expect.equals(element.kind, ElementKind.FUNCTION);
   element.computeType(compiler.resolution);
@@ -48,8 +48,6 @@
       class E<T> extends A<A<T>> {}
       class F<T, U> extends B<F<T, String>> implements A<F<B<U>, int>> {}
       ''').then((env) {
-        var compiler = env.compiler;
-
         ClassElement A = env.getElement("A");
         ClassElement B = env.getElement("B");
         ClassElement C = env.getElement("C");
@@ -57,7 +55,6 @@
         ClassElement E = env.getElement("E");
         ClassElement F = env.getElement("F");
 
-        ResolutionDartType numType = env['num'];
         ResolutionDartType intType = env['int'];
         ResolutionDartType stringType = env['String'];
 
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 6f51c3b..8250f02 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -91,8 +91,9 @@
   TypeEnvironment._(Compiler this.compiler);
 
   Element getElement(String name) {
-    LibraryElement mainApp = compiler.mainApp;
-    var element = mainApp.find(name);
+    LibraryElement mainApp =
+        compiler.frontendStrategy.elementEnvironment.mainLibrary;
+    dynamic element = mainApp.find(name);
     Expect.isNotNull(element);
     if (element.isClass) {
       element.ensureResolved(compiler.resolution);
@@ -105,7 +106,7 @@
   ClassElement getClass(String name) => getElement(name);
 
   ResolutionDartType getElementType(String name) {
-    var element = getElement(name);
+    dynamic element = getElement(name);
     return element.computeType(compiler.resolution);
   }
 
diff --git a/tests/compiler/dart2js/unparser2_test.dart b/tests/compiler/dart2js/unparser2_test.dart
index d3ede31..458b6f3 100644
--- a/tests/compiler/dart2js/unparser2_test.dart
+++ b/tests/compiler/dart2js/unparser2_test.dart
@@ -102,7 +102,7 @@
   MessageCollector() {
     messages = [];
   }
-  void internalError(node, String reason) {
+  void internalError(node, covariant String reason) {
     messages.add(reason);
     throw reason;
   }
diff --git a/tests/compiler/dart2js/unused_empty_map_test.dart b/tests/compiler/dart2js/unused_empty_map_test.dart
index a8ad30a..62e6e06 100644
--- a/tests/compiler/dart2js/unused_empty_map_test.dart
+++ b/tests/compiler/dart2js/unused_empty_map_test.dart
@@ -23,9 +23,8 @@
 main() {
   asyncTest(() async {
     var collector = new OutputCollector();
-    var result = await runCompiler(
+    await runCompiler(
         memorySourceFiles: TEST_SOURCE, outputProvider: collector);
-    var compiler = result.compiler;
     String generated = collector.getOutput('', OutputType.js);
     Expect.isFalse(generated.contains(HASHMAP_EMPTY_CONSTRUCTOR));
   });
diff --git a/tests/compiler/dart2js/use_checks_test.dart b/tests/compiler/dart2js/use_checks_test.dart
index 4056696..830b372 100644
--- a/tests/compiler/dart2js/use_checks_test.dart
+++ b/tests/compiler/dart2js/use_checks_test.dart
@@ -28,7 +28,7 @@
         memorySourceFiles: MEMORY_SOURCE_FILES,
         options: ['--enable-checked-mode']);
     var compiler = result.compiler;
-    var element = compiler.mainFunction;
+    var element = compiler.frontendStrategy.elementEnvironment.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
     Expect.isTrue(code.contains('+'), code);
   });
diff --git a/tests/compiler/dart2js/value_range3_test.dart b/tests/compiler/dart2js/value_range3_test.dart
index 851a36a..e0f6c5f 100644
--- a/tests/compiler/dart2js/value_range3_test.dart
+++ b/tests/compiler/dart2js/value_range3_test.dart
@@ -26,7 +26,7 @@
   asyncTest(() async {
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
-    var element = compiler.mainFunction;
+    var element = compiler.frontendStrategy.elementEnvironment.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
     Expect.isFalse(code.contains('ioore'));
   });
diff --git a/tests/compiler/dart2js/world_test.dart b/tests/compiler/dart2js/world_test.dart
index a70832f..1a3823a 100644
--- a/tests/compiler/dart2js/world_test.dart
+++ b/tests/compiler/dart2js/world_test.dart
@@ -243,7 +243,7 @@
   ClosedWorld closedWorld = env.closedWorld;
 
   check(String name, {bool hasStrictSubtype, bool hasOnlySubclasses}) {
-    ClassEntity cls = env.getElement(name);
+    ClassElement cls = env.getElement(name);
     Expect.equals(hasStrictSubtype, closedWorld.hasAnyStrictSubtype(cls),
         "Unexpected hasAnyStrictSubtype property on $cls.");
     Expect.equals(hasOnlySubclasses, closedWorld.hasOnlySubclasses(cls),
@@ -541,7 +541,6 @@
       useMockCompiler: false);
   ClosedWorld closedWorld = env.closedWorld;
 
-  ClassElement Object_ = env.getElement("Object");
   ClassElement A = env.getElement("A");
   ClassElement B = env.getElement("B");
   ClassElement C = env.getElement("C");
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 2e8c513..2cab8b2 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -129,9 +129,7 @@
 invalid_annotation2_test/01: Crash # Issue 27394
 invalid_annotation2_test/none: Crash # Issue 27394
 invalid_annotation_test/01: Crash # Issue 27394
-is_check_instanceof_test: RuntimeError # Issue 27394
 lookup_map/dead_entry_through_mirrors_test: Crash # Issue 27394
-lookup_map/generic_type_test: RuntimeError # Issue 27394
 lookup_map/live_entry_through_mirrors_test: Crash # Issue 27394
 lookup_map/live_entry_through_mirrors_used_test: Crash # Issue 27394
 many_fields_test: Crash # Issue 27394
@@ -154,7 +152,6 @@
 mirrors_used_metatargets_test: Crash # Issue 27394
 mirrors_used_native_test: Crash # Issue 27394
 reflect_native_types_test: Crash # Issue 27394
-runtime_type_test: RuntimeError # Issue 27394
 type_argument_factory_nocrash_test: RuntimeError # Issue 27394
 
 [ $compiler == dart2js && $dart2js_with_kernel && $host_checked ]
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 5cf48b9..87f44ca 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -119,7 +119,6 @@
 subclassing_type_test: RuntimeError # Issue 27394
 super_call_test: RuntimeError # Issue 27394
 super_property_test: RuntimeError # Issue 27394
-uninstantiated_type_parameter_test: RuntimeError # Issue 27394
 
 [ $compiler == dart2js && $runtime == d8 && $dart2js_with_kernel ]
 static_methods_test: Crash # Issue 27394
diff --git a/tests/language/language.status b/tests/language/language.status
index 92cbca7..f3741d6 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -46,6 +46,10 @@
 # Skipped temporarily until fixed
 vm/regress_29145_test: Skip # Issue 29145
 
+# Skipped temporaril until Issue 29895 is fixed.
+no_main_test/01: Skip
+main_not_a_function_test/01: Skip
+
 [ $compiler == none || $compiler == precompiler || $compiler == app_jit ]
 dynamic_prefix_core_test/01: RuntimeError # Issue 12478
 multiline_strings_test: Fail # Issue 23020
@@ -142,11 +146,12 @@
 
 [ ($runtime == vm || $runtime == flutter || $runtime == dart_precompiled) && $arch == arm64 ]
 large_class_declaration_test: SkipSlow # Uses too much memory.
+closure_cycles_test: Pass, Slow
 
 [ $compiler == none && ($runtime == dartium || $runtime == drt) && $mode == debug ]
 large_class_declaration_test: SkipSlow # Times out. Issue 20352
 
-[ ($runtime == vm || $runtime == dart_precompiled) && ( $arch == simarm || $arch == arm || $arch == simarmv6 || $arch == armv6 || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
+[ ($runtime == vm || $runtime == dart_precompiled) && ($arch == simmips || $arch == mips) ]
 vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
 vm/unaligned_float_access_literal_index_test: Pass, Crash # Unaligned offset. Issue 22151
 vm/unaligned_float_access_literal_index_test: Pass, Crash # Unaligned offset. Issue 22151
@@ -160,6 +165,8 @@
 
 [ $compiler == precompiler && $runtime == dart_precompiled ]
 vm/regress_27671_test: Skip # Unsupported
+export_double_same_main_test: Skip # Issue 29895
+export_ambiguous_main_negative_test: Skip # Issue 29895
 
 [ $compiler == precompiler && $runtime == dart_precompiled && $mode == debug ]
 regress_29025_test: Crash  # Issue dartbug.com/29331
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 5a579b4..b7cb2c6 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -348,20 +348,16 @@
 deferred_super_dependency_test/01: Crash # Issue 27394
 enum_mirror_test: Crash # Issue 27394
 export_ambiguous_main_negative_test: Crash # Issue 27394
-f_bounded_quantification5_test: RuntimeError # Issue 27394
 final_for_in_variable_test/01: MissingRuntimeError # Issue 27394
 final_param_test/01: MissingRuntimeError # Issue 27394
 final_variable_assignment_test/01: MissingRuntimeError # Issue 27394
 first_class_types_constants_test: RuntimeError # Issue 27394
 first_class_types_test: RuntimeError # Issue 27394
-function_subtype3_test: RuntimeError # Issue 27394
-function_subtype_typearg0_test: RuntimeError # Issue 27394
 generic2_test: RuntimeError # Issue 27394
 generic_field_mixin2_test: Crash # Issue 27394
 generic_field_mixin3_test: Crash # Issue 27394
 generic_field_mixin6_test/01: Crash # Issue 27394
 generic_field_mixin_test: Crash # Issue 27394
-generic_instanceof5_test: RuntimeError # Issue 27394
 generic_instanceof_test: RuntimeError # Issue 27394
 generic_local_functions_test: Crash # Issue 27394
 generic_metadata_test/02: Crash # Issue 27394
@@ -429,7 +425,6 @@
 mixin_invalid_inheritance2_test/02: Crash # Issue 27394
 mixin_invalid_inheritance2_test/03: Crash # Issue 27394
 mixin_lib_extends_field_test: Crash # Issue 27394
-mixin_only_for_rti_test: RuntimeError # Issue 27394
 mixin_proto_test: Crash # Issue 27394
 mixin_regress_11398_test: Crash # Issue 27394
 mixin_super_constructor2_test: Crash # Issue 27394
@@ -498,7 +493,6 @@
 try_catch_syntax_test/13: Crash # Issue 27394
 try_catch_syntax_test/14: Crash # Issue 27394
 try_catch_syntax_test/15: Crash # Issue 27394
-type_argument_substitution_test: RuntimeError # Issue 27394
 type_parameter_test/01: RuntimeError # Issue 27394
 type_parameter_test/02: RuntimeError # Issue 27394
 type_parameter_test/03: RuntimeError # Issue 27394
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index ff00bb3..c03a9a2 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -117,8 +117,6 @@
 external_test/13: MissingRuntimeError # KernelVM bug: Unbound external.
 external_test/20: MissingRuntimeError # KernelVM bug: Unbound external.
 
-large_class_declaration_test: SkipSlow  # KernelVM bug: KernelVM Issue 28312
-
 mixin_forwarding_constructor4_test/01: MissingCompileTimeError # KernelVM bug: Issue 15101
 mixin_forwarding_constructor4_test/02: MissingCompileTimeError # KernelVM bug: Issue 15101
 mixin_forwarding_constructor4_test/03: MissingCompileTimeError # KernelVM bug: Issue 15101
@@ -133,8 +131,6 @@
 evaluation_redirecting_constructor_test: RuntimeError # KernelVM bug: Field initializers evaluated multiple times
 redirecting_constructor_initializer_test: RuntimeError # KernelVM bug: Field initializers evaluated multiple times
 
-vm/regress_27671_test: RuntimeError # KernelVM bug: Problem with checked mode or other VMOptions?
-
 vm/debug_break_enabled_vm_test/01: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/debug_break_enabled_vm_test/none: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 
diff --git a/tests/language/vm/unaligned_float_access_literal_index_test.dart b/tests/language/vm/unaligned_float_access_literal_index_test.dart
index c224dc9..5efdeff 100644
--- a/tests/language/vm/unaligned_float_access_literal_index_test.dart
+++ b/tests/language/vm/unaligned_float_access_literal_index_test.dart
@@ -8,34 +8,34 @@
 
 unalignedFloat32() {
   var bytes = new ByteData(64);
-  bytes.setFloat32(0, 16.25);
-  Expect.equals(16.25, bytes.getFloat32(0));
-  bytes.setFloat32(1, 32.125);
-  Expect.equals(32.125, bytes.getFloat32(1));
-  bytes.setFloat32(2, 16.25);
-  Expect.equals(16.25, bytes.getFloat32(2));
-  bytes.setFloat32(3, 32.125);
-  Expect.equals(32.125, bytes.getFloat32(3));
+  bytes.setFloat32(0, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat32(0, Endianness.HOST_ENDIAN));
+  bytes.setFloat32(1, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat32(1, Endianness.HOST_ENDIAN));
+  bytes.setFloat32(2, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat32(2, Endianness.HOST_ENDIAN));
+  bytes.setFloat32(3, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat32(3, Endianness.HOST_ENDIAN));
 }
 
 unalignedFloat64() {
   var bytes = new ByteData(64);
-  bytes.setFloat64(0, 16.25);
-  Expect.equals(16.25, bytes.getFloat64(0));
-  bytes.setFloat64(1, 32.125);
-  Expect.equals(32.125, bytes.getFloat64(1));
-  bytes.setFloat64(2, 16.25);
-  Expect.equals(16.25, bytes.getFloat64(2));
-  bytes.setFloat64(3, 32.125);
-  Expect.equals(32.125, bytes.getFloat64(3));
-  bytes.setFloat64(4, 16.25);
-  Expect.equals(16.25, bytes.getFloat64(4));
-  bytes.setFloat64(5, 32.125);
-  Expect.equals(32.125, bytes.getFloat64(5));
-  bytes.setFloat64(6, 16.25);
-  Expect.equals(16.25, bytes.getFloat64(6));
-  bytes.setFloat64(7, 32.125);
-  Expect.equals(32.125, bytes.getFloat64(7));
+  bytes.setFloat64(0, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat64(0, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(1, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat64(1, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(2, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat64(2, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(3, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat64(3, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(4, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat64(4, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(5, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat64(5, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(6, 16.25, Endianness.HOST_ENDIAN);
+  Expect.equals(16.25, bytes.getFloat64(6, Endianness.HOST_ENDIAN));
+  bytes.setFloat64(7, 32.125, Endianness.HOST_ENDIAN);
+  Expect.equals(32.125, bytes.getFloat64(7, Endianness.HOST_ENDIAN));
 }
 
 main() {
diff --git a/tests/language/vm/unaligned_float_access_register_index_test.dart b/tests/language/vm/unaligned_float_access_register_index_test.dart
index 334efe5..4042ec3 100644
--- a/tests/language/vm/unaligned_float_access_register_index_test.dart
+++ b/tests/language/vm/unaligned_float_access_register_index_test.dart
@@ -9,16 +9,16 @@
 unalignedFloat32() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 4; i++) {
-    bytes.setFloat32(i, 16.25);
-    Expect.equals(16.25, bytes.getFloat32(i));
+    bytes.setFloat32(i, 16.25, Endianness.HOST_ENDIAN);
+    Expect.equals(16.25, bytes.getFloat32(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedFloat64() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 8; i++) {
-    bytes.setFloat64(i, 16.25);
-    Expect.equals(16.25, bytes.getFloat64(i));
+    bytes.setFloat64(i, 16.25, Endianness.HOST_ENDIAN);
+    Expect.equals(16.25, bytes.getFloat64(i, Endianness.HOST_ENDIAN));
   }
 }
 
diff --git a/tests/language/vm/unaligned_integer_access_literal_index_test.dart b/tests/language/vm/unaligned_integer_access_literal_index_test.dart
index 6373a24..0212f6f 100644
--- a/tests/language/vm/unaligned_integer_access_literal_index_test.dart
+++ b/tests/language/vm/unaligned_integer_access_literal_index_test.dart
@@ -8,82 +8,82 @@
 
 unalignedUint16() {
   var bytes = new ByteData(64);
-  bytes.setUint16(0, 0xABCD);
-  Expect.equals(0xABCD, bytes.getUint16(0));
-  bytes.setUint16(1, 0xBCDE);
-  Expect.equals(0xBCDE, bytes.getUint16(1));
+  bytes.setUint16(0, 0xABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCD, bytes.getUint16(0, Endianness.HOST_ENDIAN));
+  bytes.setUint16(1, 0xBCDE, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDE, bytes.getUint16(1, Endianness.HOST_ENDIAN));
 }
 
 unalignedInt16() {
   var bytes = new ByteData(64);
-  bytes.setInt16(0, -0x1234);
-  Expect.equals(-0x1234, bytes.getInt16(0));
-  bytes.setInt16(1, -0x2345);
-  Expect.equals(-0x2345, bytes.getInt16(1));
+  bytes.setInt16(0, -0x1234, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x1234, bytes.getInt16(0, Endianness.HOST_ENDIAN));
+  bytes.setInt16(1, -0x2345, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x2345, bytes.getInt16(1, Endianness.HOST_ENDIAN));
 }
 
 unalignedUint32() {
   var bytes = new ByteData(64);
-  bytes.setUint32(0, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint32(0));
-  bytes.setUint32(1, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint32(1));
-  bytes.setUint32(2, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint32(2));
-  bytes.setUint32(3, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint32(3));
+  bytes.setUint32(0, 0xABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD, bytes.getUint32(0, Endianness.HOST_ENDIAN));
+  bytes.setUint32(1, 0xBCDEBCDE, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE, bytes.getUint32(1, Endianness.HOST_ENDIAN));
+  bytes.setUint32(2, 0xABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD, bytes.getUint32(2, Endianness.HOST_ENDIAN));
+  bytes.setUint32(3, 0xBCDEBCDE, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE, bytes.getUint32(3, Endianness.HOST_ENDIAN));
 }
 
 unalignedInt32() {
   var bytes = new ByteData(64);
-  bytes.setInt32(0, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt32(0));
-  bytes.setInt32(1, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt32(1));
-  bytes.setInt32(2, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt32(2));
-  bytes.setInt32(3, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt32(3));
+  bytes.setInt32(0, -0x12341234, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234, bytes.getInt32(0, Endianness.HOST_ENDIAN));
+  bytes.setInt32(1, -0x23452345, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345, bytes.getInt32(1, Endianness.HOST_ENDIAN));
+  bytes.setInt32(2, -0x12341234, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234, bytes.getInt32(2, Endianness.HOST_ENDIAN));
+  bytes.setInt32(3, -0x23452345, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345, bytes.getInt32(3, Endianness.HOST_ENDIAN));
 }
 
 unalignedUint64() {
   var bytes = new ByteData(64);
-  bytes.setUint64(0, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint64(0));
-  bytes.setUint64(1, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint64(1));
-  bytes.setUint64(2, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint64(2));
-  bytes.setUint64(3, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint64(3));
-  bytes.setUint64(4, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint64(4));
-  bytes.setUint64(5, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint64(5));
-  bytes.setUint64(6, 0xABCDABCD);
-  Expect.equals(0xABCDABCD, bytes.getUint64(6));
-  bytes.setUint64(7, 0xBCDEBCDE);
-  Expect.equals(0xBCDEBCDE, bytes.getUint64(7));
+  bytes.setUint64(0, 0xABCDABCD12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD12345678, bytes.getUint64(0, Endianness.HOST_ENDIAN));
+  bytes.setUint64(1, 0xBCDEBCDE12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE12345678, bytes.getUint64(1, Endianness.HOST_ENDIAN));
+  bytes.setUint64(2, 0xABCDABCD12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD12345678, bytes.getUint64(2, Endianness.HOST_ENDIAN));
+  bytes.setUint64(3, 0xBCDEBCDE12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE12345678, bytes.getUint64(3, Endianness.HOST_ENDIAN));
+  bytes.setUint64(4, 0xABCDABCD12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD12345678, bytes.getUint64(4, Endianness.HOST_ENDIAN));
+  bytes.setUint64(5, 0xBCDEBCDE12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE12345678, bytes.getUint64(5, Endianness.HOST_ENDIAN));
+  bytes.setUint64(6, 0xABCDABCD12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xABCDABCD12345678, bytes.getUint64(6, Endianness.HOST_ENDIAN));
+  bytes.setUint64(7, 0xBCDEBCDE12345678, Endianness.HOST_ENDIAN);
+  Expect.equals(0xBCDEBCDE12345678, bytes.getUint64(7, Endianness.HOST_ENDIAN));
 }
 
 unalignedInt64() {
   var bytes = new ByteData(64);
-  bytes.setInt64(0, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt64(0));
-  bytes.setInt64(1, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt64(1));
-  bytes.setInt64(2, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt64(2));
-  bytes.setInt64(3, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt64(3));
-  bytes.setInt64(4, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt64(4));
-  bytes.setInt64(5, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt64(5));
-  bytes.setInt64(6, -0x12341234);
-  Expect.equals(-0x12341234, bytes.getInt64(6));
-  bytes.setInt64(7, -0x23452345);
-  Expect.equals(-0x23452345, bytes.getInt64(7));
+  bytes.setInt64(0, -0x12341234ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234ABCDABCD, bytes.getInt64(0, Endianness.HOST_ENDIAN));
+  bytes.setInt64(1, -0x23452345ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345ABCDABCD, bytes.getInt64(1, Endianness.HOST_ENDIAN));
+  bytes.setInt64(2, -0x12341234ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234ABCDABCD, bytes.getInt64(2, Endianness.HOST_ENDIAN));
+  bytes.setInt64(3, -0x23452345ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345ABCDABCD, bytes.getInt64(3, Endianness.HOST_ENDIAN));
+  bytes.setInt64(4, -0x12341234ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234ABCDABCD, bytes.getInt64(4, Endianness.HOST_ENDIAN));
+  bytes.setInt64(5, -0x23452345ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345ABCDABCD, bytes.getInt64(5, Endianness.HOST_ENDIAN));
+  bytes.setInt64(6, -0x12341234ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x12341234ABCDABCD, bytes.getInt64(6, Endianness.HOST_ENDIAN));
+  bytes.setInt64(7, -0x23452345ABCDABCD, Endianness.HOST_ENDIAN);
+  Expect.equals(-0x23452345ABCDABCD, bytes.getInt64(7, Endianness.HOST_ENDIAN));
 }
 
 main() {
diff --git a/tests/language/vm/unaligned_integer_access_register_index_test.dart b/tests/language/vm/unaligned_integer_access_register_index_test.dart
index 7c49cce..58b5076 100644
--- a/tests/language/vm/unaligned_integer_access_register_index_test.dart
+++ b/tests/language/vm/unaligned_integer_access_register_index_test.dart
@@ -9,48 +9,48 @@
 unalignedUint16() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 2; i++) {
-    bytes.setUint16(i, 0xABCD);
-    Expect.equals(0xABCD, bytes.getUint16(i));
+    bytes.setUint16(i, 0xABCD, Endianness.HOST_ENDIAN);
+    Expect.equals(0xABCD, bytes.getUint16(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedInt16() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 2; i++) {
-    bytes.setInt16(i, -0x1234);
-    Expect.equals(-0x1234, bytes.getInt16(i));
+    bytes.setInt16(i, -0x1234, Endianness.HOST_ENDIAN);
+    Expect.equals(-0x1234, bytes.getInt16(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedUint32() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 4; i++) {
-    bytes.setUint32(i, 0xABCDABCD);
-    Expect.equals(0xABCDABCD, bytes.getUint32(i));
+    bytes.setUint32(i, 0xABCDABCD, Endianness.HOST_ENDIAN);
+    Expect.equals(0xABCDABCD, bytes.getUint32(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedInt32() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 4; i++) {
-    bytes.setInt32(i, -0x12341234);
-    Expect.equals(-0x12341234, bytes.getInt32(i));
+    bytes.setInt32(i, -0x12341234, Endianness.HOST_ENDIAN);
+    Expect.equals(-0x12341234, bytes.getInt32(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedUint64() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 8; i++) {
-    bytes.setUint64(i, 0xABCDABCD);
-    Expect.equals(0xABCDABCD, bytes.getUint64(i));
+    bytes.setUint64(i, 0xABCDABCD12345678, Endianness.HOST_ENDIAN);
+    Expect.equals(0xABCDABCD12345678, bytes.getUint64(i, Endianness.HOST_ENDIAN));
   }
 }
 
 unalignedInt64() {
   var bytes = new ByteData(64);
   for (var i = 0; i < 8; i++) {
-    bytes.setInt64(i, -0x12341234);
-    Expect.equals(-0x12341234, bytes.getInt64(i));
+    bytes.setInt64(i, -0x12341234ABCDABCD, Endianness.HOST_ENDIAN);
+    Expect.equals(-0x12341234ABCDABCD, bytes.getInt64(i, Endianness.HOST_ENDIAN));
   }
 }
 
diff --git a/tests/language_strong/super_from_constructor_test.dart b/tests/language_strong/super_from_constructor_test.dart
index 2025aa9..352066a 100644
--- a/tests/language_strong/super_from_constructor_test.dart
+++ b/tests/language_strong/super_from_constructor_test.dart
@@ -6,8 +6,17 @@
 
 final results = [];
 
+int invoke(int f()) => f();
+
 class Base {
+  var f;
+  var z;
+
   m(x) => results.add(x);
+
+  int g() {
+    return 42;
+  }
 }
 
 class C extends Base {
@@ -15,10 +24,18 @@
 
   C(this._iter) {
     _iter.map((x) => super.m(x)).toList();
+    super.f = _iter;
+    z = invoke(super.g);
+  }
+
+  int g() {
+    return -1;
   }
 }
 
 main() {
-  new C([1, 2, 3]);
+  var c = new C([1, 2, 3]);
   Expect.listEquals(results, [1, 2, 3]);
+  Expect.listEquals(c.f, [1, 2, 3]);
+  Expect.equals(42, c.z);
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 0072b5e..be86f4c 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -553,6 +553,7 @@
 mirrors/metadata_allowed_values_test/13: MissingCompileTimeError
 mirrors/metadata_allowed_values_test/14: MissingCompileTimeError
 mirrors/metadata_allowed_values_test/15: Crash
+mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
 mirrors/metadata_allowed_values_test/27: Crash
 mirrors/metadata_constructed_constant_test: Crash
 mirrors/metadata_constructor_arguments_test/04: MissingCompileTimeError
diff --git a/tests/standalone/causal_async_stack_test.dart b/tests/standalone/causal_async_stack_test.dart
new file mode 100644
index 0000000..faebf3e
--- /dev/null
+++ b/tests/standalone/causal_async_stack_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--causal_async_stacks
+
+import "package:expect/expect.dart";
+
+baz() async {
+  throw "Bad!";
+}
+
+bar() async {
+  await baz();
+}
+
+foo() async {
+  await bar();
+}
+
+main() async {
+  try {
+    await foo();
+  } catch (e, st) {
+    Expect.isTrue(st.toString().contains("baz"));
+    Expect.isTrue(st.toString().contains("bar"));
+    Expect.isTrue(st.toString().contains("foo"));
+    Expect.isTrue(st.toString().contains("main"));
+  }
+}
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index 3f22a84..1fd9750 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -17,10 +17,10 @@
  */
 
 import 'package:expect/expect.dart';
-import 'package:path/path.dart';
 import 'dart:async';
 import 'dart:io';
-import '../../../tools/testing/dart/options.dart' as options;
+import '../../../tools/testing/dart/command.dart';
+import '../../../tools/testing/dart/command_output.dart';
 import '../../../tools/testing/dart/path.dart';
 import '../../../tools/testing/dart/test_runner.dart' as runner;
 import '../../../tools/testing/dart/utils.dart';
@@ -127,12 +127,11 @@
 
 class CommandCompletedHandler {
   FileUtils fileUtils;
-  DateTime _expectedTimestamp;
   bool _shouldHaveRun;
 
   CommandCompletedHandler(FileUtils this.fileUtils, bool this._shouldHaveRun);
 
-  void processCompletedTest(runner.CommandOutput output) {
+  void processCompletedTest(CommandOutput output) {
     Expect.isTrue(output.exitCode == 0);
     Expect.isTrue(output.stderr.length == 0);
     if (_shouldHaveRun) {
@@ -146,21 +145,15 @@
   }
 }
 
-runner.Command makeCompilationCommand(String testName, FileUtils fileUtils) {
-  var config = new options.OptionsParser().parse(['--timeout', '2'])[0];
+Command makeCompilationCommand(String testName, FileUtils fileUtils) {
   var createFileScript = Platform.script
       .resolve('skipping_dart2js_compilations_helper.dart')
       .toFilePath();
   var executable = Platform.executable;
   var arguments = [createFileScript, fileUtils.scriptOutputPath.toNativePath()];
   var bootstrapDeps = [Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
-  return runner.CommandBuilder.instance.getCompilationCommand(
-      'dart2js',
-      fileUtils.testJsFilePath.toNativePath(),
-      false,
-      bootstrapDeps,
-      executable,
-      arguments, {});
+  return Command.compilation('dart2js', fileUtils.testJsFilePath.toNativePath(),
+      false, bootstrapDeps, executable, arguments, {});
 }
 
 void main() {
@@ -221,7 +214,7 @@
       var completedHandler = new CommandCompletedHandler(fileUtils, shouldRun);
       var command = makeCompilationCommand(name, fileUtils);
       var process = new runner.RunningProcess(command, 60);
-      return process.run().then((runner.CommandOutput output) {
+      return process.run().then((CommandOutput output) {
         completedHandler.processCompletedTest(output);
       });
     }
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 1fc5aee..d0df216 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -4,6 +4,7 @@
 
 import "dart:io";
 import "dart:async";
+import "../../../tools/testing/dart/command.dart";
 import "../../../tools/testing/dart/configuration.dart";
 import "../../../tools/testing/dart/expectation.dart";
 import "../../../tools/testing/dart/options.dart";
@@ -97,13 +98,12 @@
   TestCase _makeNormalTestCase(name, expectations) {
     var args = packageOptions();
     args.addAll([Platform.script.toFilePath(), name]);
-    var command = CommandBuilder.instance
-        .getProcessCommand('custom', Platform.executable, args, {});
+    var command = Command.process('custom', Platform.executable, args, {});
     return _makeTestCase(name, DEFAULT_TIMEOUT, command, expectations);
   }
 
   _makeCrashTestCase(name, expectations) {
-    var crashCommand = CommandBuilder.instance.getProcessCommand(
+    var crashCommand = Command.process(
         'custom_crash', getProcessTestFileName(), ["0", "0", "1", "1"], {});
     // The crash test sometimes times out. Run it with a large timeout
     // to help diagnose the delay.
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index c7e8b72..0f7505f 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -112,36 +112,7 @@
 *: Skip # Issue 28649
 
 [ $compiler == dart2js ]
-regress_29350_test: MissingCompileTimeError
-number_identity_test: Skip # Bigints and int/double diff. not supported.
-typed_data_test: Skip # dart:typed_data support needed.
-bytedata_test: Skip # dart:typed_data support needed.
-typed_data_view_test: Skip # dart:typed_data support needed.
-typed_data_isolate_test: Skip # dart:typed_data support needed.
-typed_array_int64_uint64_test: Skip # dart:typed_data on dart2js does not support 64-bit ints.
-float_array_test: Skip # dart:typed_data support needed.
-int_array_test: Skip  # dart:typed_data support needed.
-io/web_socket_protocol_processor_test: Skip  # Importing code with external keyword
-int_array_load_elimination_test: Skip  # This is a VM test
-medium_integer_test: RuntimeError, OK # Test fails with JS number semantics: issue 1533.
-io/process_exit_negative_test: Fail, OK # relies on a static error that is a warning now.
-package/package_isolate_test: Skip # spawnUri does not work in dart2js. See issue 3051
-package/package_test: Fail, OK # dart2js does not support 'package:foo.dart' imports
-package/package1_test: Fail, OK # dart2js does not support 'package:foo.dart' imports
-package/scenarios/invalid/*: CompileTimeError  # Negative tests expecting CompileTimeErrors.
-left_shift_bit_and_op_test: Skip # Integers exceed dart2js precision.
-pow_test: Skip # Precision > 53 bits.
-double_smi_comparison_test: Skip # Precision > 53 bits.
-http_launch_test: Skip
-oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
-vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
-issue14236_test: Skip # dart2js does not deal with Script snapshots.
-unboxed_int_converter_test: Skip
-pair_location_remapping_test: Skip
-regress_25335_test: Skip # Int64List not supported.
-deferred_transitive_import_error_test: Skip # Contains intentional errors.
-dart_developer_env_test: SkipByDesign # Unsupported by dart2js
-dart_developer_disabled_env_test: SkipByDesign # Unsupported by dart2js
+*: SkipByDesign
 
 [ $runtime == vm && ($arch == arm || $arch == arm64) ]
 io/file_stream_test: Skip # Issue 26109
@@ -151,28 +122,6 @@
 [ $runtime != vm || $arch == arm || $arch == arm64 || $arch == mips || ($system == windows && $mode == debug) ]
 fragmentation_test: Skip # VM test uses too much memory for small systems.
 
-[ $compiler == dart2js && $jscl ]
-assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
-deoptimization_test: RuntimeError, OK # Requires bigint.
-out_of_memory_test: RuntimeError, OK # d8 handles much larger arrays than Dart VM.
-io/arguments_test: CompileTimeError, OK # Cannot pass arguments to d8.
-
-[ $compiler == dart2js && $runtime == none ]
-io/arguments_test: Fail # DartOptions not supported by dart2js, and issue 14200.
-medium_integer_test: Pass # The test only fails at runtime, not at compilation.
-oom_error_stacktrace_test: Pass # The test only fails at runtime.
-
-[ $compiler == dart2js && $fast_startup ]
-io/dependency_graph_test: CompileTimeError # Imports dart:mirrors
-io/skipping_dart2js_compilations_test: CompileTimeError # Imports dart:mirrors
-io/status_file_parser_test: CompileTimeError # Imports dart:mirrors
-io/test_harness_analyzer_test: CompileTimeError # Imports dart:mirrors
-io/test_runner_test: CompileTimeError # Imports dart:mirrors
-status_expression_test: CompileTimeError # Imports dart:mirrors
-
-[ $compiler == dart2js && $browser ]
-*: Skip
-
 [ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips ]
 out_of_memory_test: Skip # passes on Mac, crashes on Linux
 oom_error_stacktrace_test: Skip # Fails on Linux
@@ -476,6 +425,9 @@
 package/scenarios/invalid/same_package_twice_test: CompileTimeError
 package/scenarios/packages_dir_only/packages_dir_only_test: CompileTimeError
 
+[ $compiler == dartkp ]
+causal_async_stack_test: Fail
+
 [ $runtime == flutter ]
 io/raw_datagram_socket_test: Crash # Flutter Issue 9115
 verbose_gc_to_bmu_test: RuntimeError # Flutter Issue 9115
diff --git a/tests/utils/analysis_options.yaml b/tests/utils/analysis_options.yaml
new file mode 100644
index 0000000..73bed39
--- /dev/null
+++ b/tests/utils/analysis_options.yaml
@@ -0,0 +1,17 @@
+# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+analyzer:
+  strong-mode: true
+
+  language:
+    enableSuperMixins: false
+
+  errors:
+    todo: ignore
+
+    deprecated_member_use: ignore
+
+  exclude:
+    - dummy.dart
diff --git a/tests/utils/dart2js_test.dart b/tests/utils/dart2js_test.dart
index 3a726e8..51c5b12 100644
--- a/tests/utils/dart2js_test.dart
+++ b/tests/utils/dart2js_test.dart
@@ -4,6 +4,7 @@
 
 // Test to ensure that dart2js is free of warnings.
 
+// ignore: UNUSED_IMPORT
 import 'package:compiler/src/dart2js.dart' as dart2js;
 
 void main() {
diff --git a/tools/VERSION b/tools/VERSION
index 9520829..1988e4e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 25
 PATCH 0
-PRERELEASE 1
+PRERELEASE 2
 PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 22476e6..a310b93 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -7,7 +7,7 @@
 vars = {
   # Start of Dartium vars
 
-  "dartium_chromium_commit": "f4176572f643733083b6025ed6d17111f711bbec",
+  "dartium_chromium_commit": "0612beaf1bf21d11b1af52d4c9977caa4c641146",
   "chromium_base_revision": "378081",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index b8c3237..3e81e9b 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -1467,13 +1467,13 @@
     'MediaKeySystemConfiguration': TypeData(clazz='Primitive', dart_type='Map'),
     'DOMTimeStamp': TypeData(clazz='Primitive', dart_type='int', native_type='unsigned long long'),
     'object': TypeData(clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
-    'ObjectArray': TypeData(clazz='Primitive', dart_type='List'),
     'PositionOptions': TypeData(clazz='Primitive', dart_type='Object'),
     # TODO(sra): Come up with some meaningful name so that where this appears in
     # the documentation, the user is made aware that only a limited subset of
     # serializable types are actually permitted.
     'SerializedScriptValue': TypeData(clazz='Primitive', dart_type='dynamic'),
     'sequence': TypeData(clazz='Primitive', dart_type='List'),
+    'sequence<any>': TypeData(clazz='Primitive', dart_type='List'),
     'void': TypeData(clazz='Primitive', dart_type='void'),
 
     'CSSRule': TypeData(clazz='Interface', conversion_includes=['CSSImportRule']),
@@ -1610,7 +1610,8 @@
 
   def _TypeInfo(self, type_name):
     match = re.match(r'(?:sequence<([\w ]+)>|(\w+)\[\])$', type_name)
-    if match:
+    # sequence<any> should not be List<Object>
+    if match and match.group(1) != 'any':
       type_data = TypeData('Sequence')
       if self.HasTypeDef(match.group(1) or match.group(2)):
         # It's a typedef (union)
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
old mode 100755
new mode 100644
index b88db3a..85d711c
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -384,6 +384,16 @@
 
     # Report of union types mapped to any.
 
+    # Remember all the typedefs before we start walking the AST.  Some
+    # IDLs now have typedefs before interfaces.  So we need to remember
+    # to resolve the typedefs.
+    self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef)
+    for typedefName in ast.typedefs:
+      typedef_type = ast.typedefs[typedefName]
+      # Ignore unions and dictionaries for now we just want normal typedefs to resolve our arguments/types.
+      if not(isinstance(typedef_type.idl_type, IdlUnionType)) and not(typedef_type.idl_type.base_type == 'Dictionary'):
+        _addTypedef(IDLTypeDef(typedef_type))
+
     self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
     self.dictionaries = self._convert_all(ast, 'Dictionary', IDLDictionary)
 
@@ -432,10 +442,7 @@
       self.implementsStatements = self._convert_all(ast, 'ImplStmt',
         IDLImplementsStatement)
 
-    # No reason to handle typedef they're already aliased in Blink's AST.
-    self.typeDefs = [] if is_blink else self._convert_all(ast, 'TypeDef', IDLTypeDef)
-
-    # Hack to record typedefs that are unions.
+    # Record typedefs that are unions.
     for typedefName in ast.typedefs:
       typedef_type = ast.typedefs[typedefName]
       if isinstance(typedef_type.idl_type, IdlUnionType):
@@ -443,9 +450,6 @@
       elif typedef_type.idl_type.base_type == 'Dictionary':
         dictionary = IDLDictionary(typedef_type, True)
         self.dictionaries.append(dictionary)
-      else:
-        # All other typedefs we record
-        _addTypedef(IDLTypeDef(typedef_type))
 
     self.enums = self._convert_all(ast, 'Enum', IDLEnum)
 
diff --git a/tools/gardening/bin/bot.dart b/tools/gardening/bin/bot.dart
index 2226637..75c2900 100644
--- a/tools/gardening/bin/bot.dart
+++ b/tools/gardening/bin/bot.dart
@@ -7,8 +7,9 @@
 
 import 'compare_failures.dart' as compare_failures;
 import 'current_summary.dart' as current_summary;
-import 'status_summary.dart' as status_summary;
 import 'find_shard.dart' as find_shard;
+import 'status_summary.dart' as status_summary;
+import 'summary.dart' as summary;
 
 typedef Future MainFunction(List<String> args);
 
@@ -30,6 +31,7 @@
 
 const Map<String, MainFunction> commands = const <String, MainFunction>{
   "help": help,
+  "summary": summary.main,
   "compare-failures": compare_failures.main,
   "current-summary": current_summary.main,
   "status-summary": status_summary.main,
diff --git a/tools/gardening/bin/compare_failures.dart b/tools/gardening/bin/compare_failures.dart
index 42b1925..de88891 100644
--- a/tools/gardening/bin/compare_failures.dart
+++ b/tools/gardening/bin/compare_failures.dart
@@ -57,7 +57,7 @@
 }
 
 /// Creates a [BuildResult] for [buildUri] and, if it contains failures, the
-/// [BuildResult]s for the previous 5 builds.
+/// [BuildResult]s for the previous [runCount] builds.
 Future<List<BuildResult>> readBuildResults(
     BuildbotClient client, BuildUri buildUri, int runCount) async {
   List<BuildResult> summaries = <BuildResult>[];
diff --git a/tools/gardening/bin/summary.dart b/tools/gardening/bin/summary.dart
new file mode 100644
index 0000000..6622d48
--- /dev/null
+++ b/tools/gardening/bin/summary.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/args.dart';
+import 'package:gardening/src/bot.dart';
+import 'package:gardening/src/util.dart';
+
+void help(ArgParser argParser) {
+  print('Summarizes the current status of the build bot.');
+  print('Usage: summary [options]');
+  print('  where options are:');
+  print(argParser.usage);
+}
+
+main(List<String> args) async {
+  ArgParser argParser = createArgParser();
+  ArgResults argResults = argParser.parse(args);
+  processArgResults(argResults);
+  var bot = new Bot(logdog: argResults['logdog']);
+  var recentUris = bot.mostRecentUris;
+  var results = await bot.readResults(recentUris);
+  results.forEach((result) {
+    if (result.hasFailures) {
+      print("${result.buildUri} has failures.");
+    }
+  });
+  bot.close();
+}
diff --git a/tools/gardening/lib/src/bot.dart b/tools/gardening/lib/src/bot.dart
new file mode 100644
index 0000000..c0cce3c
--- /dev/null
+++ b/tools/gardening/lib/src/bot.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'buildbot_data.dart';
+import 'buildbot_structures.dart';
+import 'client.dart';
+import 'util.dart';
+
+class Bot {
+  final bool usesLogdog;
+  final BuildbotClient _client;
+
+  /// Instantiates a Bot.
+  ///
+  /// Bots must be [close]d when they aren't needed anymore.
+  Bot({bool logdog = false})
+      : usesLogdog = logdog,
+        _client =
+            logdog ? new LogdogBuildbotClient() : new HttpBuildbotClient();
+
+  /// Reads the build result of [buildUri] and the [previousCount] earlier
+  /// builds.
+  Future<List<BuildResult>> readHistoricResults(BuildUri buildUri,
+      {int previousCount = 0}) {
+    log("Fetching $buildUri and $previousCount previous builds in parallel");
+    var uris = [buildUri];
+    for (int i = 0; i < previousCount; i++) {
+      buildUri = buildUri.prev();
+      uris.add(buildUri);
+    }
+    return readResults(uris);
+  }
+
+  Future<BuildResult> readResult(BuildUri buildUri) {
+    return _client.readResult(buildUri);
+  }
+
+  Future<List<BuildResult>> readResults(List<BuildUri> buildUris) async {
+    var result = <BuildResult>[];
+    int i = 0;
+    const maxParallel = 20;
+    while (i < buildUris.length) {
+      var end = i + maxParallel;
+      if (end > buildUris.length) end = buildUris.length;
+      var parallelChunk = buildUris.sublist(i, end);
+      log("Fetching ${end - i} uris in parallel");
+      result.addAll(await Future.wait(parallelChunk.map(_client.readResult)));
+      i = end + 1;
+    }
+    return result;
+  }
+
+  /// Returns uris for the most recent build of all build groups.
+  List<BuildUri> get mostRecentUris {
+    List<BuildUri> result = [];
+    for (BuildGroup group in buildGroups) {
+      result.addAll(group.createUris(_client.mostRecentBuildNumber));
+    }
+    return result;
+  }
+
+  /// Closes the bot.
+  void close() => _client.close();
+}
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index e51e843..3ff5d48 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -74,14 +74,18 @@
   exit(1);
 }
 
+const validModes = const ['vm', 'dart2js', 'flutter'];
+String mode;
+bool get forVm => mode == 'vm';
+bool get forFlutter => mode == 'flutter';
+bool get forDart2js => mode == 'dart2js';
+
 Future _main(List<String> argv) async {
-  if (argv.isEmpty) usage('[vm|dart2js]');
-  var mode = argv.first;
-  if (mode != 'vm' && mode != 'dart2js') usage('[vm|dart2js]');
+  if (argv.isEmpty) usage('[${validModes.join('|')}]');
+  mode = argv.first;
+  if (!validModes.contains(mode)) usage('[${validModes.join('|')}]');
   if (argv.length != 5) usage(mode);
 
-  bool forVm = mode == 'vm';
-  bool forDart2js = mode == 'dart2js';
   var input = argv[1];
   var sdkLibIn = path.join(input, 'lib');
   var patchIn = argv[2];
@@ -93,65 +97,102 @@
   // Parse libraries.dart
   var libContents = readInputFile(path.join(
       sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'));
-  if (forVm) libContents = _updateLibraryMetadata(sdkOut, libContents);
-  var sdkLibraries = _getSdkLibraries(libContents, forDart2js);
+  libContents = _updateLibraryMetadata(sdkOut, libContents);
+  var sdkLibraries = _getSdkLibraries(libContents);
 
   Map<String, String> locations = <String, String>{};
 
   // Enumerate core libraries and apply patches
   for (SdkLibrary library in sdkLibraries) {
     if (forDart2js && library.isVmLibrary) continue;
-    if (forVm && library.isDart2JsLibrary) continue;
+    if (!forDart2js && library.isDart2JsLibrary) continue;
     _applyPatch(library, sdkLibIn, patchIn, sdkOut, locations);
   }
 
-  if (forVm) _copyExtraVmLibraries(sdkOut, locations);
+  _copyExtraLibraries(sdkOut, locations);
 
   Uri platform = outDirUri.resolve('platform.dill.tmp');
   Uri outline = outDirUri.resolve('outline.dill');
-  Uri vmserviceIo = outDirUri.resolve('vmservice_io.dill');
   Uri librariesJson = outDirUri.resolve("lib/libraries.json");
   Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile));
 
   await _writeSync(
       librariesJson.toFilePath(), JSON.encode({"libraries": locations}));
 
-  if (forVm) {
+  if (forVm || forFlutter) {
     await fasta.compilePlatform(outDirUri, platform,
-        packages: packages, outlineOutput: outline);
-    await fasta.compile([
-      "--sdk=${outDirUri.toString()}",
-      "--platform=${outline.toString()}",
-      "--packages=${packages.toString()}",
-      "dart:vmservice_io",
-      "-o",
-      vmserviceIo.toString()
-    ]);
+        packages: packages,
+        outlineOutput: outline,
+        backendTarget: forVm ? 'vm_fasta' : 'flutter_fasta');
   } else {
     await dart2js.compilePlatform(outDirUri, platform,
         packages: packages, outlineOutput: outline);
   }
 
+  if (forVm) {
+    var base = path.fromUri(Platform.script);
+    Uri repositoryDir =
+        new Uri.directory(path.dirname(path.dirname(path.absolute(base))));
+    var vmserviceName = 'vmservice_io';
+    Uri vmserviceSdk = repositoryDir.resolve('runtime/bin/vmservice_sdk/');
+    Uri vmserviceUri = outDirUri.resolve('$vmserviceName.dill');
+    // TODO(sigmundch): Specify libraries.json directly instead of "--sdk"
+    // after #29882 is fixed.
+    await fasta.compile([
+      "--sdk=$vmserviceSdk",
+      "--platform=$outline",
+      "--target=vm_fasta",
+      "--packages=$packages",
+      "dart:$vmserviceName",
+      "-o",
+      "$vmserviceUri",
+    ]);
+  }
+
   Uri platformFinalLocation = outDirUri.resolve('platform.dill');
 
-  // To properly regenerate the patched_sdk, patched_dart2js_sdk, and
-  // platform.dill only when necessary, we track dependencies as follows:
-  //  - inputs like the sdk libraries and patch files are covered by the
-  //    extraDependencies argument.
-  //  - this script and its script dependencies are handled by writeDepsFile
-  //    here.
-  //  - the internal platform libraries that may affect how this script
-  //    runs in the VM are discovered by providing the `platform` argument
-  //    below. Regardless of patched_sdk or patched_dart2js_sdk we provide below
-  //    the .dill file of patched_sdk (since the script runs in the VM and not
-  //    in dart2js). At the BUILD.gn level we have a dependency from
-  //    patched_dart2js_sdk to patched_sdk to ensure that file already exists.
+  // We generate a dependency file for GN to properly regenerate the patched sdk
+  // folder, outline.dill and platform.dill files when necessary: either when
+  // the sdk sources change or when this script is updated. In particular:
+  //
+  //  - sdk changes: we track the actual sources we are compiling. If we are
+  //    building the dart2js sdk, this includes the dart2js-specific patch
+  //    files.
+  //
+  //    These files are tracked by [deps] and passed below to [writeDepsFile] in
+  //    the extraDependencies argument.
+  //
+  //  - script updates: we track this script file and any code it imports (even
+  //    sdk libraries). Note that this script runs on the standalone VM, so any
+  //    sdk library used by this script indirectly depends on a VM-specific
+  //    patch file.
+  //
+  //    These set of files is discovered by `writeDepsFile` below, and the
+  //    [platformForDeps] is always the VM-specific `platform.dill` file.
+  //
+  //    TODO(sigmund): we should change this:
+  //      - we should rewrite writeDepsFile: fasta could provide an API to crawl
+  //        the dependencies, but anything that is GN specific, should be on
+  //        this file instead.
+  //
+  //      - We don't need to include sdk dependencies of the script because
+  //        those are already included indirectly (either in [deps] when
+  //        building the sdk for the VM, or via the .GN dependencies in the
+  //        build files for dart2js and flutter).
+  var platformForDeps = platform;
+  var sdkDir = outDirUri;
+  if (forDart2js || forFlutter) {
+    // Note: this would fail if `../patched_sdk/platform.dill` doesn't exist. We
+    // added an explicit dependency in the .GN rules so patched_dart2js_sdk (and
+    // patched_flutter_sdk) depend on patched_sdk to ensure that it exists.
+    platformForDeps = outDirUri.resolve('../patched_sdk/platform.dill');
+    sdkDir = outDirUri.resolve('../patched_sdk/');
+  }
   await fasta.writeDepsFile(Platform.script,
       Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation,
-      sdk: outDirUri,
+      sdk: sdkDir,
       packages: packages,
-      platform:
-          forVm ? platform : outDirUri.resolve('../patched_sdk/platform.dill'),
+      platform: platformForDeps,
       extraDependencies: deps);
 
   await new File.fromUri(platform).rename(platformFinalLocation.toFilePath());
@@ -161,11 +202,9 @@
 /// sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart to include
 /// declarations for vm internal libraries.
 String _updateLibraryMetadata(String sdkOut, String libContents) {
-  // Copy and patch libraries.dart and version
-  libContents = libContents.replaceAll(
-      ' libraries = const {',
-      ''' libraries = const {
-
+  if (!forVm && !forFlutter) return libContents;
+  var extraLibraries = new StringBuffer();
+  extraLibraries.write('''
   "_builtin": const LibraryInfo(
       "_builtin/_builtin.dart",
       categories: "Client,Server",
@@ -177,7 +216,21 @@
       "profiler/profiler.dart",
       maturity: Maturity.DEPRECATED,
       documented: false),
-''');
+  ''');
+
+  if (forFlutter) {
+    extraLibraries.write('''
+      "ui": const LibraryInfo(
+          "ui/ui.dart",
+          categories: "Client,Server",
+          implementation: true,
+          documented: false,
+          platforms: VM_PLATFORM),
+    ''');
+  }
+
+  libContents = libContents.replaceAll(
+      ' libraries = const {', ' libraries = const { $extraLibraries');
   _writeSync(
       path.join(
           sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'),
@@ -185,32 +238,34 @@
   return libContents;
 }
 
-/// Copy internal libraries that are developed under 'runtime/bin/' to the
-/// patched_sdk folder.
-_copyExtraVmLibraries(String sdkOut, Map<String, String> locations) {
+/// Copy internal libraries that are developed outside the sdk folder into the
+/// patched_sdk folder. For the VM< this includes files under 'runtime/bin/',
+/// for flutter, this is includes also the ui library.
+_copyExtraLibraries(String sdkOut, Map<String, String> locations) {
+  if (forDart2js) return;
   var base = path.fromUri(Platform.script);
   var dartDir = path.dirname(path.dirname(path.absolute(base)));
 
-  for (var tuple in [
-    ['_builtin', 'builtin.dart']
-  ]) {
-    var vmLibrary = tuple[0];
-    var dartFile = tuple[1];
+  var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', 'builtin.dart');
+  var builtinLibraryOut = path.join(sdkOut, '_builtin', '_builtin.dart');
+  _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn));
+  locations['_builtin'] = path.join('_builtin', '_builtin.dart');
 
-    // The "dart:_builtin" library is only available for the DartVM.
-    var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile);
-    var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart');
-    _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn));
-    locations[vmLibrary] = path.join(vmLibrary, '${vmLibrary}.dart');
+  if (forFlutter) {
+    // Flutter repo has this layout:
+    //  engine/src/
+    //       dart/
+    //       flutter/
+    var srcDir = path.dirname(path.dirname(path.dirname(path.absolute(base))));
+    var uiLibraryInDir = path.join(srcDir, 'flutter', 'lib', 'ui');
+    for (var file in new Directory(uiLibraryInDir).listSync()) {
+      if (!file.path.endsWith('.dart')) continue;
+      var name = path.basename(file.path);
+      var uiLibraryOut = path.join(sdkOut, 'ui', name);
+      _writeSync(uiLibraryOut, readInputFile(file.path));
+    }
+    locations['ui'] = 'ui/ui.dart';
   }
-
-  for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) {
-    var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file);
-    var libraryOut = path.join(sdkOut, 'vmservice_io', file);
-    _writeSync(libraryOut, readInputFile(libraryIn));
-  }
-  locations["vmservice_io"] = "vmservice_io/vmservice_io.dart";
-  locations["_vmservice"] = "vmservice/vmservice.dart";
 }
 
 _applyPatch(SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut,
@@ -621,8 +676,8 @@
   }
 }
 
-List<SdkLibrary> _getSdkLibraries(String contents, bool useDart2js) {
-  var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(useDart2js);
+List<SdkLibrary> _getSdkLibraries(String contents) {
+  var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(forDart2js);
   parseCompilationUnit(contents).accept(libraryBuilder);
   return libraryBuilder.librariesMap.sdkLibraries;
 }
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
new file mode 100644
index 0000000..e191186
--- /dev/null
+++ b/tools/testing/dart/command.dart
@@ -0,0 +1,609 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
+// CommandOutput.exitCode in subclasses of CommandOutput.
+import 'dart:io' as io;
+
+import 'command_output.dart';
+import 'configuration.dart';
+import 'expectation.dart';
+import 'path.dart';
+import 'utils.dart';
+
+/// A command executed as a step in a test case.
+class Command {
+  static Command contentShell(
+      String executable,
+      String htmlFile,
+      List<String> options,
+      List<String> dartFlags,
+      Map<String, String> environment) {
+    return new ContentShellCommand._(
+        executable, htmlFile, options, dartFlags, environment);
+  }
+
+  static Command browserTest(String url, Configuration configuration,
+      {bool retry}) {
+    return new BrowserTestCommand._(url, configuration, retry);
+  }
+
+  static Command browserHtmlTest(
+      String url, Configuration configuration, List<String> expectedMessages,
+      {bool retry}) {
+    return new BrowserHtmlTestCommand._(
+        url, configuration, expectedMessages, retry);
+  }
+
+  static Command compilation(
+      String displayName,
+      String outputFile,
+      bool neverSkipCompilation,
+      List<Uri> bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environment) {
+    return new CompilationCommand._(
+        displayName,
+        outputFile,
+        neverSkipCompilation,
+        bootstrapDependencies,
+        executable,
+        arguments,
+        environment);
+  }
+
+  static Command kernelCompilation(
+      String outputFile,
+      bool neverSkipCompilation,
+      List<Uri> bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environment) {
+    return new KernelCompilationCommand._(outputFile, neverSkipCompilation,
+        bootstrapDependencies, executable, arguments, environment);
+  }
+
+  static Command analysis(String executable, List<String> arguments,
+      Map<String, String> environmentOverrides) {
+    return new AnalysisCommand._(executable, arguments, environmentOverrides);
+  }
+
+  static Command vm(String executable, List<String> arguments,
+      Map<String, String> environmentOverrides) {
+    return new VmCommand._(executable, arguments, environmentOverrides);
+  }
+
+  static Command vmBatch(String executable, String tester,
+      List<String> arguments, Map<String, String> environmentOverrides,
+      {bool checked: true}) {
+    return new VmBatchCommand._(
+        executable, tester, arguments, environmentOverrides,
+        checked: checked);
+  }
+
+  static Command adbPrecompiled(String precompiledRunner, String processTest,
+      String testDirectory, List<String> arguments, bool useBlobs) {
+    return new AdbPrecompilationCommand._(
+        precompiledRunner, processTest, testDirectory, arguments, useBlobs);
+  }
+
+  static Command jsCommandLine(
+      String displayName, String executable, List<String> arguments,
+      [Map<String, String> environment]) {
+    return new JSCommandlineCommand._(
+        displayName, executable, arguments, environment);
+  }
+
+  static Command process(
+      String displayName, String executable, List<String> arguments,
+      [Map<String, String> environment, String workingDirectory]) {
+    return new ProcessCommand._(
+        displayName, executable, arguments, environment, workingDirectory);
+  }
+
+  static Command copy(String sourceDirectory, String destinationDirectory) {
+    return new CleanDirectoryCopyCommand._(
+        sourceDirectory, destinationDirectory);
+  }
+
+  static Command pub(String pubCommand, String pubExecutable,
+      String pubspecYamlDirectory, String pubCacheDirectory,
+      {List<String> arguments: const <String>[]}) {
+    return new PubCommand._(pubCommand, pubExecutable, pubspecYamlDirectory,
+        pubCacheDirectory, arguments);
+  }
+
+  static Command makeSymlink(String link, String target) {
+    return new MakeSymlinkCommand._(link, target);
+  }
+
+  /// A descriptive name for this command.
+  final String displayName;
+
+  /// Number of times this command *can* be retried.
+  int get maxNumRetries => 2;
+
+  /// Reproduction command.
+  String get reproductionCommand => null;
+
+  /// We compute the Command.hashCode lazily and cache it here, since it might
+  /// be expensive to compute (and hashCode is called often).
+  int _cachedHashCode;
+
+  Command._(this.displayName);
+
+  int get hashCode {
+    if (_cachedHashCode == null) {
+      var builder = new HashCodeBuilder();
+      _buildHashCode(builder);
+      _cachedHashCode = builder.value;
+    }
+    return _cachedHashCode;
+  }
+
+  operator ==(Object other) =>
+      identical(this, other) ||
+      (runtimeType == other.runtimeType && _equal(other as Command));
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    builder.addJson(displayName);
+  }
+
+  bool _equal(covariant Command other) =>
+      hashCode == other.hashCode && displayName == other.displayName;
+
+  String toString() => reproductionCommand;
+
+  Future<bool> get outputIsUpToDate => new Future.value(false);
+}
+
+class ProcessCommand extends Command {
+  /// Path to the executable of this command.
+  String executable;
+
+  /// Command line arguments to the executable.
+  final List<String> arguments;
+
+  /// Environment for the command.
+  final Map<String, String> environmentOverrides;
+
+  /// Working directory for the command.
+  final String workingDirectory;
+
+  ProcessCommand._(String displayName, this.executable, this.arguments,
+      [this.environmentOverrides, this.workingDirectory])
+      : super._(displayName) {
+    if (io.Platform.operatingSystem == 'windows') {
+      // Windows can't handle the first command if it is a .bat file or the like
+      // with the slashes going the other direction.
+      // NOTE: Issue 1306
+      executable = executable.replaceAll('/', '\\');
+    }
+  }
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(executable);
+    builder.addJson(workingDirectory);
+    builder.addJson(arguments);
+    builder.addJson(environmentOverrides);
+  }
+
+  bool _equal(ProcessCommand other) =>
+      super._equal(other) &&
+      executable == other.executable &&
+      deepJsonCompare(arguments, other.arguments) &&
+      workingDirectory == other.workingDirectory &&
+      deepJsonCompare(environmentOverrides, other.environmentOverrides);
+
+  String get reproductionCommand {
+    var env = new StringBuffer();
+    environmentOverrides?.forEach((key, value) =>
+        (io.Platform.operatingSystem == 'windows')
+            ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
+            : env.write('$key=${escapeCommandLineArgument(value)} '));
+    var command = ([executable]..addAll(batchArguments)..addAll(arguments))
+        .map(escapeCommandLineArgument)
+        .join(' ');
+    if (workingDirectory != null) {
+      command = "$command (working directory: $workingDirectory)";
+    }
+    return "$env$command";
+  }
+
+  Future<bool> get outputIsUpToDate => new Future.value(false);
+
+  /// Arguments that are passed to the process when starting batch mode.
+  ///
+  /// In non-batch mode, they should be passed before [arguments].
+  List<String> get batchArguments => const [];
+}
+
+class CompilationCommand extends ProcessCommand {
+  final String _outputFile;
+  final bool _neverSkipCompilation;
+  final List<Uri> _bootstrapDependencies;
+
+  CompilationCommand._(
+      String displayName,
+      this._outputFile,
+      this._neverSkipCompilation,
+      this._bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environmentOverrides)
+      : super._(displayName, executable, arguments, environmentOverrides);
+
+  Future<bool> get outputIsUpToDate {
+    if (_neverSkipCompilation) return new Future.value(false);
+
+    Future<List<Uri>> readDepsFile(String path) {
+      var file = new io.File(new Path(path).toNativePath());
+      if (!file.existsSync()) {
+        return new Future.value(null);
+      }
+      return file.readAsLines().then((List<String> lines) {
+        var dependencies = new List<Uri>();
+        for (var line in lines) {
+          line = line.trim();
+          if (line.length > 0) {
+            dependencies.add(Uri.parse(line));
+          }
+        }
+        return dependencies;
+      });
+    }
+
+    return readDepsFile("$_outputFile.deps").then((dependencies) {
+      if (dependencies != null) {
+        dependencies.addAll(_bootstrapDependencies);
+        var jsOutputLastModified = TestUtils.lastModifiedCache
+            .getLastModified(new Uri(scheme: 'file', path: _outputFile));
+        if (jsOutputLastModified != null) {
+          for (var dependency in dependencies) {
+            var dependencyLastModified =
+                TestUtils.lastModifiedCache.getLastModified(dependency);
+            if (dependencyLastModified == null ||
+                dependencyLastModified.isAfter(jsOutputLastModified)) {
+              return false;
+            }
+          }
+          return true;
+        }
+      }
+      return false;
+    });
+  }
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(_outputFile);
+    builder.addJson(_neverSkipCompilation);
+    builder.addJson(_bootstrapDependencies);
+  }
+
+  bool _equal(CompilationCommand other) =>
+      super._equal(other) &&
+      _outputFile == other._outputFile &&
+      _neverSkipCompilation == other._neverSkipCompilation &&
+      deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
+}
+
+class KernelCompilationCommand extends CompilationCommand {
+  KernelCompilationCommand._(
+      String outputFile,
+      bool neverSkipCompilation,
+      List<Uri> bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environmentOverrides)
+      : super._('dartk', outputFile, neverSkipCompilation,
+            bootstrapDependencies, executable, arguments, environmentOverrides);
+
+  int get maxNumRetries => 1;
+}
+
+/// This is just a Pair(String, Map) class with hashCode and operator ==
+class AddFlagsKey {
+  final String flags;
+  final Map env;
+  AddFlagsKey(this.flags, this.env);
+  // Just use object identity for environment map
+  bool operator ==(Object other) =>
+      other is AddFlagsKey && flags == other.flags && env == other.env;
+  int get hashCode => flags.hashCode ^ env.hashCode;
+}
+
+class ContentShellCommand extends ProcessCommand {
+  ContentShellCommand._(
+      String executable,
+      String htmlFile,
+      List<String> options,
+      List<String> dartFlags,
+      Map<String, String> environmentOverrides)
+      : super._("content_shell", executable, _getArguments(options, htmlFile),
+            _getEnvironment(environmentOverrides, dartFlags));
+
+  // Cache the modified environments in a map from the old environment and
+  // the string of Dart flags to the new environment.  Avoid creating new
+  // environment object for each command object.
+  static Map<AddFlagsKey, Map<String, String>> environments = {};
+
+  static Map<String, String> _getEnvironment(
+      Map<String, String> env, List<String> dartFlags) {
+    var needDartFlags = dartFlags != null && dartFlags.isNotEmpty;
+    if (needDartFlags) {
+      if (env == null) {
+        env = const <String, String>{};
+      }
+      var flags = dartFlags.join(' ');
+      return environments.putIfAbsent(
+          new AddFlagsKey(flags, env),
+          () => new Map<String, String>.from(env)
+            ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'}));
+    }
+    return env;
+  }
+
+  static List<String> _getArguments(List<String> options, String htmlFile) {
+    var arguments = options.toList();
+    arguments.add(htmlFile);
+    return arguments;
+  }
+
+  int get maxNumRetries => 3;
+}
+
+class BrowserTestCommand extends Command {
+  Runtime get browser => configuration.runtime;
+  final String url;
+  final Configuration configuration;
+  final bool retry;
+
+  BrowserTestCommand._(this.url, this.configuration, this.retry)
+      : super._(configuration.runtime.name);
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(browser.name);
+    builder.addJson(url);
+    builder.add(configuration);
+    builder.add(retry);
+  }
+
+  bool _equal(BrowserTestCommand other) =>
+      super._equal(other) &&
+      browser == other.browser &&
+      url == other.url &&
+      identical(configuration, other.configuration) &&
+      retry == other.retry;
+
+  String get reproductionCommand {
+    var parts = [
+      io.Platform.resolvedExecutable,
+      'tools/testing/dart/launch_browser.dart',
+      browser.name,
+      url
+    ];
+    return parts.map(escapeCommandLineArgument).join(' ');
+  }
+
+  int get maxNumRetries => 4;
+}
+
+class BrowserHtmlTestCommand extends BrowserTestCommand {
+  List<String> expectedMessages;
+  BrowserHtmlTestCommand._(String url, Configuration configuration,
+      this.expectedMessages, bool retry)
+      : super._(url, configuration, retry);
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(expectedMessages);
+  }
+
+  bool _equal(BrowserHtmlTestCommand other) =>
+      super._equal(other) &&
+      identical(expectedMessages, other.expectedMessages);
+}
+
+class AnalysisCommand extends ProcessCommand {
+  AnalysisCommand._(String executable, List<String> arguments,
+      Map<String, String> environmentOverrides)
+      : super._('dart2analyzer', executable, arguments, environmentOverrides);
+}
+
+class VmCommand extends ProcessCommand {
+  VmCommand._(String executable, List<String> arguments,
+      Map<String, String> environmentOverrides)
+      : super._('vm', executable, arguments, environmentOverrides);
+}
+
+class VmBatchCommand extends ProcessCommand implements VmCommand {
+  final String dartFile;
+  final bool checked;
+
+  VmBatchCommand._(String executable, String dartFile, List<String> arguments,
+      Map<String, String> environmentOverrides,
+      {this.checked: true})
+      : this.dartFile = dartFile,
+        super._('vm-batch', executable, arguments, environmentOverrides);
+
+  @override
+  List<String> get batchArguments =>
+      checked ? ['--checked', dartFile] : [dartFile];
+
+  @override
+  bool _equal(VmBatchCommand other) {
+    return super._equal(other) &&
+        dartFile == other.dartFile &&
+        checked == other.checked;
+  }
+
+  @override
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(dartFile);
+    builder.addJson(checked);
+  }
+}
+
+class AdbPrecompilationCommand extends Command {
+  final String precompiledRunnerFilename;
+  final String processTestFilename;
+  final String precompiledTestDirectory;
+  final List<String> arguments;
+  final bool useBlobs;
+
+  AdbPrecompilationCommand._(
+      this.precompiledRunnerFilename,
+      this.processTestFilename,
+      this.precompiledTestDirectory,
+      this.arguments,
+      this.useBlobs)
+      : super._("adb_precompilation");
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.add(precompiledRunnerFilename);
+    builder.add(precompiledTestDirectory);
+    builder.add(arguments);
+    builder.add(useBlobs);
+  }
+
+  bool _equal(AdbPrecompilationCommand other) =>
+      super._equal(other) &&
+      precompiledRunnerFilename == other.precompiledRunnerFilename &&
+      useBlobs == other.useBlobs &&
+      arguments == other.arguments &&
+      precompiledTestDirectory == other.precompiledTestDirectory;
+
+  String toString() => 'Steps to push precompiled runner and precompiled code '
+      'to an attached device. Uses (and requires) adb.';
+}
+
+class JSCommandlineCommand extends ProcessCommand {
+  JSCommandlineCommand._(
+      String displayName, String executable, List<String> arguments,
+      [Map<String, String> environmentOverrides = null])
+      : super._(displayName, executable, arguments, environmentOverrides);
+}
+
+class PubCommand extends ProcessCommand {
+  final String command;
+
+  PubCommand._(String pubCommand, String pubExecutable,
+      String pubspecYamlDirectory, String pubCacheDirectory, List<String> args)
+      : command = pubCommand,
+        super._(
+            'pub_$pubCommand',
+            new io.File(pubExecutable).absolute.path,
+            [pubCommand]..addAll(args),
+            {'PUB_CACHE': pubCacheDirectory},
+            pubspecYamlDirectory);
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(command);
+  }
+
+  bool _equal(PubCommand other) =>
+      super._equal(other) && command == other.command;
+}
+
+/// [ScriptCommand]s are executed by dart code.
+abstract class ScriptCommand extends Command {
+  ScriptCommand._(String displayName) : super._(displayName);
+
+  Future<ScriptCommandOutputImpl> run();
+}
+
+class CleanDirectoryCopyCommand extends ScriptCommand {
+  final String _sourceDirectory;
+  final String _destinationDirectory;
+
+  CleanDirectoryCopyCommand._(this._sourceDirectory, this._destinationDirectory)
+      : super._('dir_copy');
+
+  String get reproductionCommand =>
+      "Copying '$_sourceDirectory' to '$_destinationDirectory'.";
+
+  Future<ScriptCommandOutputImpl> run() {
+    var watch = new Stopwatch()..start();
+
+    var destination = new io.Directory(_destinationDirectory);
+
+    return destination.exists().then((bool exists) {
+      Future cleanDirectoryFuture;
+      if (exists) {
+        cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory);
+      } else {
+        cleanDirectoryFuture = new Future.value(null);
+      }
+      return cleanDirectoryFuture.then((_) {
+        return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory);
+      });
+    }).then((_) {
+      return new ScriptCommandOutputImpl(
+          this, Expectation.pass, "", watch.elapsed);
+    }).catchError((error) {
+      return new ScriptCommandOutputImpl(
+          this, Expectation.fail, "An error occured: $error.", watch.elapsed);
+    });
+  }
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(_sourceDirectory);
+    builder.addJson(_destinationDirectory);
+  }
+
+  bool _equal(CleanDirectoryCopyCommand other) =>
+      super._equal(other) &&
+      _sourceDirectory == other._sourceDirectory &&
+      _destinationDirectory == other._destinationDirectory;
+}
+
+/// Makes a symbolic link to another directory.
+class MakeSymlinkCommand extends ScriptCommand {
+  String _link;
+  String _target;
+
+  MakeSymlinkCommand._(this._link, this._target) : super._('make_symlink');
+
+  String get reproductionCommand =>
+      "Make symbolic link '$_link' (target: $_target)'.";
+
+  Future<ScriptCommandOutputImpl> run() {
+    var watch = new Stopwatch()..start();
+    var targetFile = new io.Directory(_target);
+    return targetFile.exists().then((bool targetExists) {
+      if (!targetExists) {
+        throw new Exception("Target '$_target' does not exist");
+      }
+      var link = new io.Link(_link);
+
+      return link.exists().then((bool exists) {
+        if (exists) return link.delete();
+      }).then((_) => link.create(_target));
+    }).then((_) {
+      return new ScriptCommandOutputImpl(
+          this, Expectation.pass, "", watch.elapsed);
+    }).catchError((error) {
+      return new ScriptCommandOutputImpl(
+          this, Expectation.fail, "An error occured: $error.", watch.elapsed);
+    });
+  }
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(_link);
+    builder.addJson(_target);
+  }
+
+  bool _equal(MakeSymlinkCommand other) =>
+      super._equal(other) && _link == other._link && _target == other._target;
+}
diff --git a/tools/testing/dart/command_output.dart b/tools/testing/dart/command_output.dart
new file mode 100644
index 0000000..fc2bc10
--- /dev/null
+++ b/tools/testing/dart/command_output.dart
@@ -0,0 +1,909 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
+// CommandOutput.exitCode in subclasses of CommandOutput.
+import 'dart:io' as io;
+
+import 'browser_controller.dart';
+import 'command.dart';
+import 'configuration.dart';
+import 'expectation.dart';
+import 'test_runner.dart';
+import 'utils.dart';
+
+/**
+ * CommandOutput records the output of a completed command: the process's exit
+ * code, the standard output and standard error, whether the process timed out,
+ * and the time the process took to run.  It does not contain a pointer to the
+ * [TestCase] this is the output of, so some functions require the test case
+ * to be passed as an argument.
+ */
+abstract class CommandOutput {
+  Command get command;
+
+  Expectation result(TestCase testCase);
+
+  bool get hasCrashed;
+
+  bool get hasTimedOut;
+
+  bool didFail(TestCase testCase);
+
+  bool hasFailed(TestCase testCase);
+
+  bool get canRunDependendCommands;
+
+  bool get successful; // otherwise we might to retry running
+
+  Duration get time;
+
+  int get exitCode;
+
+  int get pid;
+
+  List<int> get stdout;
+
+  List<int> get stderr;
+
+  List<String> get diagnostics;
+
+  bool get compilationSkipped;
+}
+
+class CommandOutputImpl extends UniqueObject implements CommandOutput {
+  Command command;
+  int exitCode;
+
+  bool timedOut;
+  List<int> stdout;
+  List<int> stderr;
+  Duration time;
+  List<String> diagnostics;
+  bool compilationSkipped;
+  int pid;
+
+  /**
+   * A flag to indicate we have already printed a warning about ignoring the VM
+   * crash, to limit the amount of output produced per test.
+   */
+  bool alreadyPrintedWarning = false;
+
+  CommandOutputImpl(
+      Command this.command,
+      int this.exitCode,
+      bool this.timedOut,
+      List<int> this.stdout,
+      List<int> this.stderr,
+      Duration this.time,
+      bool this.compilationSkipped,
+      int this.pid) {
+    diagnostics = [];
+  }
+
+  Expectation result(TestCase testCase) {
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasFailed(testCase)) return Expectation.fail;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+    return Expectation.pass;
+  }
+
+  bool get hasCrashed {
+    // dart2js exits with code 253 in case of unhandled exceptions.
+    // The dart binary exits with code 253 in case of an API error such
+    // as an invalid snapshot file.
+    // In either case an exit code of 253 is considered a crash.
+    if (exitCode == 253) return true;
+    if (io.Platform.operatingSystem == 'windows') {
+      // The VM uses std::abort to terminate on asserts.
+      // std::abort terminates with exit code 3 on Windows.
+      if (exitCode == 3 || exitCode == CRASHING_BROWSER_EXITCODE) {
+        return !timedOut;
+      }
+      // If a program receives an uncaught system exception, the program
+      // terminates with the exception code as exit code.
+      // The 0x3FFFFF00 mask here tries to determine if an exception indicates
+      // a crash of the program.
+      // System exception codes can be found in 'winnt.h', for example
+      // "#define STATUS_ACCESS_VIOLATION  ((DWORD) 0xC0000005)"
+      return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0));
+    }
+    return !timedOut && ((exitCode < 0));
+  }
+
+  bool get hasTimedOut => timedOut;
+
+  bool didFail(TestCase testCase) {
+    return (exitCode != 0 && !hasCrashed);
+  }
+
+  bool get canRunDependendCommands {
+    // FIXME(kustermann): We may need to change this
+    return !hasTimedOut && exitCode == 0;
+  }
+
+  bool get successful {
+    // FIXME(kustermann): We may need to change this
+    return !hasTimedOut && exitCode == 0;
+  }
+
+  // Reverse result of a negative test.
+  bool hasFailed(TestCase testCase) {
+    return testCase.isNegative ? !didFail(testCase) : didFail(testCase);
+  }
+
+  bool get hasNonUtf8 => exitCode == NON_UTF_FAKE_EXITCODE;
+
+  Expectation _negateOutcomeIfNegativeTest(
+      Expectation outcome, bool isNegative) {
+    if (!isNegative) return outcome;
+    if (outcome == Expectation.ignore) return outcome;
+    if (outcome.canBeOutcomeOf(Expectation.fail)) {
+      return Expectation.pass;
+    }
+    return Expectation.fail;
+  }
+}
+
+class ContentShellCommandOutputImpl extends CommandOutputImpl {
+  // Although tests are reported as passing, content shell sometimes exits with
+  // a nonzero exitcode which makes our dartium builders extremely falky.
+  // See: http://dartbug.com/15139.
+  // TODO(rnystrom): Is this still needed? The underlying bug is closed.
+  static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022;
+  static bool isWindows = io.Platform.operatingSystem == 'windows';
+  static bool _failedBecauseOfFlakyInfrastructure(
+      Command command, bool timedOut, List<int> stderrBytes) {
+    // If the browser test failed, it may have been because content shell
+    // and the virtual framebuffer X server didn't hook up, or it crashed with
+    // a core dump. Sometimes content shell crashes after it has set the stdout
+    // to PASS, so we have to do this check first.
+    // Content shell also fails with a broken pipe message: Issue 26739
+    var zygoteCrash =
+        new RegExp(r"ERROR:zygote_linux\.cc\(\d+\)] write: Broken pipe");
+    var stderr = decodeUtf8(stderrBytes);
+    // TODO(7564): See http://dartbug.com/7564
+    // This may not be happening anymore.  Test by removing this suppression.
+    if (stderr.contains(MESSAGE_CANNOT_OPEN_DISPLAY) ||
+        stderr.contains(MESSAGE_FAILED_TO_RUN_COMMAND)) {
+      DebugLogger.warning(
+          "Warning: Failure because of missing XDisplay. Test ignored");
+      return true;
+    }
+    // TODO(26739): See http://dartbug.com/26739
+    if (zygoteCrash.hasMatch(stderr)) {
+      DebugLogger.warning("Warning: Failure because of content_shell "
+          "zygote crash. Test ignored");
+      return true;
+    }
+    return false;
+  }
+
+  bool _infraFailure;
+
+  ContentShellCommandOutputImpl(
+      Command command,
+      int exitCode,
+      bool timedOut,
+      List<int> stdout,
+      List<int> stderr,
+      Duration time,
+      bool compilationSkipped)
+      : _infraFailure =
+            _failedBecauseOfFlakyInfrastructure(command, timedOut, stderr),
+        super(command, exitCode, timedOut, stdout, stderr, time,
+            compilationSkipped, 0);
+
+  Expectation result(TestCase testCase) {
+    if (_infraFailure) {
+      return Expectation.ignore;
+    }
+
+    // Handle crashes and timeouts first
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    var outcome = _getOutcome();
+
+    if (testCase.hasRuntimeError) {
+      if (!outcome.canBeOutcomeOf(Expectation.runtimeError)) {
+        return Expectation.missingRuntimeError;
+      }
+    }
+    if (testCase.isNegative) {
+      if (outcome.canBeOutcomeOf(Expectation.fail)) return Expectation.pass;
+      return Expectation.fail;
+    }
+    return outcome;
+  }
+
+  bool get successful => canRunDependendCommands;
+
+  bool get canRunDependendCommands {
+    // We cannot rely on the exit code of content_shell as a method to
+    // determine if we were successful or not.
+    return super.canRunDependendCommands && !didFail(null);
+  }
+
+  bool get hasCrashed {
+    return super.hasCrashed || _rendererCrashed;
+  }
+
+  Expectation _getOutcome() {
+    if (_browserTestFailure) {
+      return Expectation.runtimeError;
+    }
+    return Expectation.pass;
+  }
+
+  bool get _rendererCrashed =>
+      decodeUtf8(super.stdout).contains("#CRASHED - rendere");
+
+  bool get _browserTestFailure {
+    // Browser tests fail unless stdout contains
+    // 'Content-Type: text/plain' followed by 'PASS'.
+    bool hasContentType = false;
+    var stdoutLines = decodeUtf8(super.stdout).split("\n");
+    var containsFail = false;
+    var containsPass = false;
+    for (String line in stdoutLines) {
+      switch (line) {
+        case 'Content-Type: text/plain':
+          hasContentType = true;
+          break;
+        case 'FAIL':
+          if (hasContentType) {
+            containsFail = true;
+          }
+          break;
+        case 'PASS':
+          if (hasContentType) {
+            containsPass = true;
+          }
+          break;
+      }
+    }
+    if (hasContentType) {
+      if (containsFail && containsPass) {
+        DebugLogger.warning("Test had 'FAIL' and 'PASS' in stdout. ($command)");
+      }
+      if (!containsFail && !containsPass) {
+        DebugLogger.warning("Test had neither 'FAIL' nor 'PASS' in stdout. "
+            "($command)");
+        return true;
+      }
+      if (containsFail) {
+        return true;
+      }
+      assert(containsPass);
+      if (exitCode != 0) {
+        var message = "All tests passed, but exitCode != 0. "
+            "Actual exitcode: $exitCode. "
+            "($command)";
+        DebugLogger.warning(message);
+        diagnostics.add(message);
+      }
+      return (!hasCrashed &&
+          exitCode != 0 &&
+          (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE));
+    }
+    DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. "
+        "($command).");
+    return true;
+  }
+}
+
+class HTMLBrowserCommandOutputImpl extends ContentShellCommandOutputImpl {
+  HTMLBrowserCommandOutputImpl(
+      Command command,
+      int exitCode,
+      bool timedOut,
+      List<int> stdout,
+      List<int> stderr,
+      Duration time,
+      bool compilationSkipped)
+      : super(command, exitCode, timedOut, stdout, stderr, time,
+            compilationSkipped);
+
+  bool didFail(TestCase testCase) {
+    return _getOutcome() != Expectation.pass;
+  }
+
+  bool get _browserTestFailure {
+    // We should not need to convert back and forward.
+    var output = decodeUtf8(super.stdout);
+    if (output.contains("FAIL")) return true;
+    return !output.contains("PASS");
+  }
+}
+
+class BrowserTestJsonResult {
+  static const ALLOWED_TYPES = const [
+    'sync_exception',
+    'window_onerror',
+    'script_onerror',
+    'window_compilationerror',
+    'print',
+    'message_received',
+    'dom',
+    'debug'
+  ];
+
+  final Expectation outcome;
+  final String htmlDom;
+  final List<dynamic> events;
+
+  BrowserTestJsonResult(this.outcome, this.htmlDom, this.events);
+
+  static BrowserTestJsonResult parseFromString(String content) {
+    void validate(String assertion, bool value) {
+      if (!value) {
+        throw "InvalidFormat sent from browser driving page: $assertion:\n\n"
+            "$content";
+      }
+    }
+
+    try {
+      var events = JSON.decode(content);
+      if (events != null) {
+        validate("Message must be a List", events is List);
+
+        var messagesByType = <String, List<String>>{};
+        ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]);
+
+        for (var entry in events) {
+          validate("An entry must be a Map", entry is Map);
+
+          var type = entry['type'];
+          var value = entry['value'] as String;
+          var timestamp = entry['timestamp'];
+
+          validate("'type' of an entry must be a String", type is String);
+          validate("'type' has to be in $ALLOWED_TYPES.",
+              ALLOWED_TYPES.contains(type));
+          validate(
+              "'timestamp' of an entry must be a number", timestamp is num);
+
+          messagesByType[type].add(value);
+        }
+        validate("The message must have exactly one 'dom' entry.",
+            messagesByType['dom'].length == 1);
+
+        var dom = messagesByType['dom'][0];
+        if (dom.endsWith('\n')) {
+          dom = '$dom\n';
+        }
+
+        return new BrowserTestJsonResult(
+            _getOutcome(messagesByType), dom, events as List<dynamic>);
+      }
+    } catch (error) {
+      // If something goes wrong, we know the content was not in the correct
+      // JSON format. So we can't parse it.
+      // The caller is responsible for falling back to the old way of
+      // determining if a test failed.
+    }
+
+    return null;
+  }
+
+  static Expectation _getOutcome(Map<String, List<String>> messagesByType) {
+    occured(String type) => messagesByType[type].length > 0;
+    searchForMsg(List<String> types, String message) {
+      return types.any((type) => messagesByType[type].contains(message));
+    }
+
+    // FIXME(kustermann,ricow): I think this functionality doesn't work in
+    // test_controller.js: So far I haven't seen anything being reported on
+    // "window.compilationerror"
+    if (occured('window_compilationerror')) {
+      return Expectation.compileTimeError;
+    }
+
+    if (occured('sync_exception') ||
+        occured('window_onerror') ||
+        occured('script_onerror')) {
+      return Expectation.runtimeError;
+    }
+
+    if (messagesByType['dom'][0].contains('FAIL')) {
+      return Expectation.runtimeError;
+    }
+
+    // We search for these messages in 'print' and 'message_received' because
+    // the unittest implementation posts these messages using
+    // "window.postMessage()" instead of the normal "print()" them.
+
+    var isAsyncTest = searchForMsg(
+        ['print', 'message_received'], 'unittest-suite-wait-for-done');
+    var isAsyncSuccess =
+        searchForMsg(['print', 'message_received'], 'unittest-suite-success') ||
+            searchForMsg(['print', 'message_received'], 'unittest-suite-done');
+
+    if (isAsyncTest) {
+      if (isAsyncSuccess) {
+        return Expectation.pass;
+      }
+      return Expectation.runtimeError;
+    }
+
+    var mainStarted =
+        searchForMsg(['print', 'message_received'], 'dart-calling-main');
+    var mainDone =
+        searchForMsg(['print', 'message_received'], 'dart-main-done');
+
+    if (mainStarted && mainDone) {
+      return Expectation.pass;
+    }
+    return Expectation.fail;
+  }
+}
+
+class BrowserCommandOutputImpl extends CommandOutputImpl
+    with UnittestSuiteMessagesMixin {
+  BrowserTestOutput _result;
+  Expectation _rawOutcome;
+
+  factory BrowserCommandOutputImpl(Command command, BrowserTestOutput result) {
+    String indent(String string, int numSpaces) {
+      var spaces = new List.filled(numSpaces, ' ').join('');
+      return string
+          .replaceAll('\r\n', '\n')
+          .split('\n')
+          .map((line) => "$spaces$line")
+          .join('\n');
+    }
+
+    String stdout = "";
+    String stderr = "";
+    Expectation outcome;
+
+    var parsedResult =
+        BrowserTestJsonResult.parseFromString(result.lastKnownMessage);
+    if (parsedResult != null) {
+      outcome = parsedResult.outcome;
+    } else {
+      // Old way of determining whether a test failed or passed.
+      if (result.lastKnownMessage.contains("FAIL")) {
+        outcome = Expectation.runtimeError;
+      } else if (result.lastKnownMessage.contains("PASS")) {
+        outcome = Expectation.pass;
+      } else {
+        outcome = Expectation.runtimeError;
+      }
+    }
+
+    if (result.didTimeout) {
+      if (result.delayUntilTestStarted != null) {
+        stderr = "This test timed out. The delay until the test actually "
+            "started was: ${result.delayUntilTestStarted}.";
+      } else {
+        stderr = "This test has not notified test.py that it started running.";
+      }
+    }
+
+    if (parsedResult != null) {
+      stdout = "events:\n${indent(prettifyJson(parsedResult.events), 2)}\n\n";
+    } else {
+      stdout = "message:\n${indent(result.lastKnownMessage, 2)}\n\n";
+    }
+
+    stderr = '$stderr\n\n'
+        'BrowserOutput while running the test (* EXPERIMENTAL *):\n'
+        'BrowserOutput.stdout:\n'
+        '${indent(result.browserOutput.stdout.toString(), 2)}\n'
+        'BrowserOutput.stderr:\n'
+        '${indent(result.browserOutput.stderr.toString(), 2)}\n'
+        '\n';
+    return new BrowserCommandOutputImpl._internal(
+        command, result, outcome, encodeUtf8(stdout), encodeUtf8(stderr));
+  }
+
+  BrowserCommandOutputImpl._internal(Command command, BrowserTestOutput result,
+      this._rawOutcome, List<int> stdout, List<int> stderr)
+      : super(command, 0, result.didTimeout, stdout, stderr, result.duration,
+            false, 0) {
+    _result = result;
+  }
+
+  Expectation result(TestCase testCase) {
+    // Handle timeouts first
+    if (_result.didTimeout) {
+      if (testCase.configuration.runtime == Runtime.ie11) {
+        // TODO(28955): See http://dartbug.com/28955
+        DebugLogger.warning("Timeout of ie11 on test ${testCase.displayName}");
+        return Expectation.ignore;
+      }
+      return Expectation.timeout;
+    }
+
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    // Multitests are handled specially
+    if (testCase.hasRuntimeError) {
+      if (_rawOutcome == Expectation.runtimeError) return Expectation.pass;
+      return Expectation.missingRuntimeError;
+    }
+
+    return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative);
+  }
+}
+
+class AnalysisCommandOutputImpl extends CommandOutputImpl {
+  // An error line has 8 fields that look like:
+  // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
+  final int ERROR_LEVEL = 0;
+  final int ERROR_TYPE = 1;
+  final int FILENAME = 3;
+  final int FORMATTED_ERROR = 7;
+
+  AnalysisCommandOutputImpl(
+      Command command,
+      int exitCode,
+      bool timedOut,
+      List<int> stdout,
+      List<int> stderr,
+      Duration time,
+      bool compilationSkipped)
+      : super(command, exitCode, timedOut, stdout, stderr, time,
+            compilationSkipped, 0);
+
+  Expectation result(TestCase testCase) {
+    // TODO(kustermann): If we run the analyzer not in batch mode, make sure
+    // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
+    // no errors)
+
+    // Handle crashes and timeouts first
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    // Get the errors/warnings from the analyzer
+    List<String> errors = [];
+    List<String> warnings = [];
+    parseAnalyzerOutput(errors, warnings);
+
+    // Handle errors / missing errors
+    if (testCase.expectCompileError) {
+      if (errors.length > 0) {
+        return Expectation.pass;
+      }
+      return Expectation.missingCompileTimeError;
+    }
+    if (errors.length > 0) {
+      return Expectation.compileTimeError;
+    }
+
+    // Handle static warnings / missing static warnings
+    if (testCase.hasStaticWarning) {
+      if (warnings.length > 0) {
+        return Expectation.pass;
+      }
+      return Expectation.missingStaticWarning;
+    }
+    if (warnings.length > 0) {
+      return Expectation.staticWarning;
+    }
+
+    assert(errors.length == 0 && warnings.length == 0);
+    assert(!testCase.hasCompileError && !testCase.hasStaticWarning);
+    return Expectation.pass;
+  }
+
+  void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) {
+    // Parse a line delimited by the | character using \ as an escape character
+    // like:  FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
+    List<String> splitMachineError(String line) {
+      StringBuffer field = new StringBuffer();
+      List<String> result = [];
+      bool escaped = false;
+      for (var i = 0; i < line.length; i++) {
+        var c = line[i];
+        if (!escaped && c == '\\') {
+          escaped = true;
+          continue;
+        }
+        escaped = false;
+        if (c == '|') {
+          result.add(field.toString());
+          field = new StringBuffer();
+          continue;
+        }
+        field.write(c);
+      }
+      result.add(field.toString());
+      return result;
+    }
+
+    for (String line in decodeUtf8(super.stderr).split("\n")) {
+      if (line.length == 0) continue;
+      List<String> fields = splitMachineError(line);
+      // We only consider errors/warnings for files of interest.
+      if (fields.length > FORMATTED_ERROR) {
+        if (fields[ERROR_LEVEL] == 'ERROR') {
+          outErrors.add(fields[FORMATTED_ERROR]);
+        } else if (fields[ERROR_LEVEL] == 'WARNING') {
+          outWarnings.add(fields[FORMATTED_ERROR]);
+        }
+        // OK to Skip error output that doesn't match the machine format
+      }
+    }
+  }
+}
+
+class VmCommandOutputImpl extends CommandOutputImpl
+    with UnittestSuiteMessagesMixin {
+  static const DART_VM_EXITCODE_DFE_ERROR = 252;
+  static const DART_VM_EXITCODE_COMPILE_TIME_ERROR = 254;
+  static const DART_VM_EXITCODE_UNCAUGHT_EXCEPTION = 255;
+
+  VmCommandOutputImpl(Command command, int exitCode, bool timedOut,
+      List<int> stdout, List<int> stderr, Duration time, int pid)
+      : super(command, exitCode, timedOut, stdout, stderr, time, false, pid);
+
+  Expectation result(TestCase testCase) {
+    // Handle crashes and timeouts first
+    if (exitCode == DART_VM_EXITCODE_DFE_ERROR) return Expectation.dartkCrash;
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    // Multitests are handled specially
+    if (testCase.expectCompileError) {
+      if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
+        return Expectation.pass;
+      }
+      return Expectation.missingCompileTimeError;
+    }
+    if (testCase.hasRuntimeError) {
+      // TODO(kustermann): Do we consider a "runtimeError" only an uncaught
+      // exception or does any nonzero exit code fullfil this requirement?
+      if (exitCode != 0) {
+        return Expectation.pass;
+      }
+      return Expectation.missingRuntimeError;
+    }
+
+    // The actual outcome depends on the exitCode
+    Expectation outcome;
+    if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
+      outcome = Expectation.compileTimeError;
+    } else if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
+      outcome = Expectation.runtimeError;
+    } else if (exitCode != 0) {
+      // This is a general fail, in case we get an unknown nonzero exitcode.
+      outcome = Expectation.fail;
+    } else {
+      outcome = Expectation.pass;
+    }
+    outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
+    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+  }
+}
+
+class CompilationCommandOutputImpl extends CommandOutputImpl {
+  static const DART2JS_EXITCODE_CRASH = 253;
+
+  CompilationCommandOutputImpl(
+      Command command,
+      int exitCode,
+      bool timedOut,
+      List<int> stdout,
+      List<int> stderr,
+      Duration time,
+      bool compilationSkipped)
+      : super(command, exitCode, timedOut, stdout, stderr, time,
+            compilationSkipped, 0);
+
+  Expectation result(TestCase testCase) {
+    // Handle general crash/timeout detection.
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) {
+      bool isWindows = io.Platform.operatingSystem == 'windows';
+      bool isBrowserTestCase =
+          testCase.commands.any((command) => command is BrowserTestCommand);
+      // TODO(26060) Dart2js batch mode hangs on Windows under heavy load.
+      return (isWindows && isBrowserTestCase)
+          ? Expectation.ignore
+          : Expectation.timeout;
+    }
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    // Handle dart2js specific crash detection
+    if (exitCode == DART2JS_EXITCODE_CRASH ||
+        exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_COMPILE_TIME_ERROR ||
+        exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
+      return Expectation.crash;
+    }
+
+    // Multitests are handled specially
+    if (testCase.expectCompileError) {
+      // Nonzero exit code of the compiler means compilation failed
+      // TODO(kustermann): Do we have a special exit code in that case???
+      if (exitCode != 0) {
+        return Expectation.pass;
+      }
+      return Expectation.missingCompileTimeError;
+    }
+
+    // TODO(kustermann): This is a hack, remove it
+    if (testCase.hasRuntimeError && testCase.commands.length > 1) {
+      // We expected to run the test, but we got an compile time error.
+      // If the compilation succeeded, we wouldn't be in here!
+      assert(exitCode != 0);
+      return Expectation.compileTimeError;
+    }
+
+    Expectation outcome =
+        exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
+    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+  }
+}
+
+class KernelCompilationCommandOutputImpl extends CompilationCommandOutputImpl {
+  KernelCompilationCommandOutputImpl(
+      Command command,
+      int exitCode,
+      bool timedOut,
+      List<int> stdout,
+      List<int> stderr,
+      Duration time,
+      bool compilationSkipped)
+      : super(command, exitCode, timedOut, stdout, stderr, time,
+            compilationSkipped);
+
+  bool get canRunDependendCommands {
+    // See [BatchRunnerProcess]: 0 means success, 1 means compile-time error.
+    // TODO(asgerf): When the frontend supports it, continue running even if
+    //   there were compile-time errors. See kernel_sdk issue #18.
+    return !hasCrashed && !timedOut && exitCode == 0;
+  }
+
+  Expectation result(TestCase testCase) {
+    Expectation result = super.result(testCase);
+    if (result.canBeOutcomeOf(Expectation.crash)) {
+      return Expectation.dartkCrash;
+    } else if (result.canBeOutcomeOf(Expectation.timeout)) {
+      return Expectation.dartkTimeout;
+    } else if (result.canBeOutcomeOf(Expectation.compileTimeError)) {
+      return Expectation.dartkCompileTimeError;
+    }
+    return result;
+  }
+
+  // If the compiler was able to produce a Kernel IR file we want to run the
+  // result on the Dart VM.  We therefore mark the [KernelCompilationCommand] as
+  // successful.
+  // => This ensures we test that the DartVM produces correct CompileTime errors
+  //    as it is supposed to for our test suites.
+  bool get successful => canRunDependendCommands;
+}
+
+class JsCommandlineOutputImpl extends CommandOutputImpl
+    with UnittestSuiteMessagesMixin {
+  JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut,
+      List<int> stdout, List<int> stderr, Duration time)
+      : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
+
+  Expectation result(TestCase testCase) {
+    // Handle crashes and timeouts first
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    if (testCase.hasRuntimeError) {
+      if (exitCode != 0) return Expectation.pass;
+      return Expectation.missingRuntimeError;
+    }
+
+    var outcome = exitCode == 0 ? Expectation.pass : Expectation.runtimeError;
+    outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
+    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+  }
+}
+
+class PubCommandOutputImpl extends CommandOutputImpl {
+  PubCommandOutputImpl(PubCommand command, int exitCode, bool timedOut,
+      List<int> stdout, List<int> stderr, Duration time)
+      : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
+
+  Expectation result(TestCase testCase) {
+    // Handle crashes and timeouts first
+    if (hasCrashed) return Expectation.crash;
+    if (hasTimedOut) return Expectation.timeout;
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+
+    if (exitCode == 0) {
+      return Expectation.pass;
+    } else if ((command as PubCommand).command == 'get') {
+      return Expectation.pubGetError;
+    } else {
+      return Expectation.fail;
+    }
+  }
+}
+
+class ScriptCommandOutputImpl extends CommandOutputImpl {
+  final Expectation _result;
+
+  ScriptCommandOutputImpl(ScriptCommand command, this._result,
+      String scriptExecutionInformation, Duration time)
+      : super(command, 0, false, [], [], time, false, 0) {
+    var lines = scriptExecutionInformation.split("\n");
+    diagnostics.addAll(lines);
+  }
+
+  Expectation result(TestCase testCase) => _result;
+
+  bool get canRunDependendCommands => _result == Expectation.pass;
+
+  bool get successful => _result == Expectation.pass;
+}
+
+CommandOutput createCommandOutput(Command command, int exitCode, bool timedOut,
+    List<int> stdout, List<int> stderr, Duration time, bool compilationSkipped,
+    [int pid = 0]) {
+  if (command is ContentShellCommand) {
+    return new ContentShellCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  } else if (command is BrowserTestCommand) {
+    return new HTMLBrowserCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  } else if (command is AnalysisCommand) {
+    return new AnalysisCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  } else if (command is VmCommand) {
+    return new VmCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, pid);
+  } else if (command is KernelCompilationCommand) {
+    return new KernelCompilationCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  } else if (command is AdbPrecompilationCommand) {
+    return new VmCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, pid);
+  } else if (command is CompilationCommand) {
+    if (command.displayName == 'precompiler' ||
+        command.displayName == 'app_jit') {
+      return new VmCommandOutputImpl(
+          command, exitCode, timedOut, stdout, stderr, time, pid);
+    }
+    return new CompilationCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  } else if (command is JSCommandlineCommand) {
+    return new JsCommandlineOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time);
+  } else if (command is PubCommand) {
+    return new PubCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time);
+  }
+
+  return new CommandOutputImpl(command, exitCode, timedOut, stdout, stderr,
+      time, compilationSkipped, pid);
+}
+
+class UnittestSuiteMessagesMixin {
+  bool _isAsyncTest(String testOutput) {
+    return testOutput.contains("unittest-suite-wait-for-done");
+  }
+
+  bool _isAsyncTestSuccessful(String testOutput) {
+    return testOutput.contains("unittest-suite-success");
+  }
+
+  Expectation _negateOutcomeIfIncompleteAsyncTest(
+      Expectation outcome, String testOutput) {
+    // If this is an asynchronous test and the asynchronous operation didn't
+    // complete successfully, it's outcome is Expectation.FAIL.
+    // TODO: maybe we should introduce a AsyncIncomplete marker or so
+    if (outcome == Expectation.pass) {
+      if (_isAsyncTest(testOutput) && !_isAsyncTestSuccessful(testOutput)) {
+        return Expectation.fail;
+      }
+    }
+    return outcome;
+  }
+}
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index c6367d8..1be5f2b 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -4,9 +4,9 @@
 
 import 'dart:io';
 
+import 'command.dart';
 import 'configuration.dart';
 import 'runtime_configuration.dart';
-import 'test_runner.dart';
 import 'test_suite.dart';
 import 'utils.dart';
 
@@ -143,12 +143,8 @@
 
   List<Uri> bootstrapDependencies(String buildDir) => const <Uri>[];
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     return new CommandArtifact([], null, null);
   }
 
@@ -202,7 +198,7 @@
     List<String> args = [];
     if (useDfe) {
       args.add('--dfe=${buildDir}/gen/kernel-service.dart.snapshot');
-      args.add('--platform=${buildDir}/patched_sdk/platform.dill');
+      args.add('--kernel-binaries=${buildDir}/patched_sdk');
     }
     if (isChecked) {
       args.add('--enable_asserts');
@@ -239,12 +235,8 @@
     return 'tools/dartk_wrappers/dartk$executableScriptSuffix';
   }
 
-  CompilationCommand computeCompilationCommand(
-      String outputFileName,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeCompilationCommand(String outputFileName, String buildDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     Iterable<String> extraArguments = [
       '--sdk',
       '$buildDir/patched_sdk',
@@ -256,8 +248,7 @@
       '--out',
       outputFileName
     ].where((x) => x != null);
-    return commandBuilder.getKernelCompilationCommand(
-        'dartk',
+    return Command.kernelCompilation(
         outputFileName,
         true,
         bootstrapDependencies(buildDir),
@@ -266,15 +257,11 @@
         environmentOverrides);
   }
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
-    return new CommandArtifact(<Command>[
-      computeCompilationCommand('$tempDir/out.dill', buildDir,
-          CommandBuilder.instance, arguments, environmentOverrides)
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
+    return new CommandArtifact([
+      computeCompilationCommand(
+          '$tempDir/out.dill', buildDir, arguments, environmentOverrides)
     ], '$tempDir/out.dill', 'application/dart');
   }
 
@@ -351,12 +338,8 @@
 
   ComposedCompilerConfiguration(this.pipelineCommands) : super._subclass();
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> globalArguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> globalArguments, Map<String, String> environmentOverrides) {
     List<Command> allCommands = [];
 
     // The first compilation command is as usual.
@@ -364,7 +347,7 @@
     CommandArtifact artifact = pipelineCommands[0]
         .compilerConfiguration
         .computeCompilationArtifact(
-            buildDir, tempDir, commandBuilder, arguments, environmentOverrides);
+            buildDir, tempDir, arguments, environmentOverrides);
     allCommands.addAll(artifact.commands);
 
     // The following compilation commands are based on the output of the
@@ -374,7 +357,7 @@
 
       arguments = pc.extractArguments(globalArguments, artifact.filename);
       artifact = pc.compilerConfiguration.computeCompilationArtifact(
-          buildDir, tempDir, commandBuilder, arguments, environmentOverrides);
+          buildDir, tempDir, arguments, environmentOverrides);
 
       allCommands.addAll(artifact.commands);
     }
@@ -489,16 +472,12 @@
     }
   }
 
-  CompilationCommand computeCompilationCommand(
-      String outputFileName,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeCompilationCommand(String outputFileName, String buildDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     arguments = arguments.toList();
     arguments.add('--out=$outputFileName');
 
-    return commandBuilder.getCompilationCommand(
+    return Command.compilation(
         moniker,
         outputFileName,
         !useSdk,
@@ -550,16 +529,12 @@
     return multiplier;
   }
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     var compilerArguments = arguments.toList()..addAll(extraDart2jsOptions);
     return new CommandArtifact([
-      this.computeCompilationCommand('$tempDir/out.js', buildDir,
-          CommandBuilder.instance, compilerArguments, environmentOverrides)
+      computeCompilationCommand(
+          '$tempDir/out.js', buildDir, compilerArguments, environmentOverrides)
     ], '$tempDir/out.js', 'application/javascript');
   }
 
@@ -603,31 +578,23 @@
     return multiplier;
   }
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     var commands = new List<Command>();
-    commands.add(this.computeCompilationCommand(tempDir, buildDir,
-        CommandBuilder.instance, arguments, environmentOverrides));
+    commands.add(this.computeCompilationCommand(
+        tempDir, buildDir, arguments, environmentOverrides));
     if (!useBlobs) {
-      commands.add(this.computeAssembleCommand(tempDir, buildDir,
-          CommandBuilder.instance, arguments, environmentOverrides));
-      commands.add(this.computeRemoveAssemblyCommand(tempDir, buildDir,
-          CommandBuilder.instance, arguments, environmentOverrides));
+      commands.add(this.computeAssembleCommand(
+          tempDir, buildDir, arguments, environmentOverrides));
+      commands.add(this.computeRemoveAssemblyCommand(
+          tempDir, buildDir, arguments, environmentOverrides));
     }
     return new CommandArtifact(
         commands, '$tempDir', 'application/dart-precompiled');
   }
 
-  CompilationCommand computeCompilationCommand(
-      String tempDir,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeCompilationCommand(String tempDir, String buildDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     String exec;
     if (isAndroid) {
       if (arch == Architecture.arm) {
@@ -641,7 +608,7 @@
     var args = <String>[];
     if (useDfe) {
       args.add('--dfe=utils/kernel-service/kernel-service.dart');
-      args.add('--platform=${buildDir}/patched_sdk/platform.dill');
+      args.add('--kernel-binaries=${buildDir}/patched_sdk');
     }
     args.add("--snapshot-kind=app-aot");
     if (useBlobs) {
@@ -655,16 +622,12 @@
     }
     args.addAll(arguments);
 
-    return commandBuilder.getCompilationCommand('precompiler', tempDir, !useSdk,
+    return Command.compilation('precompiler', tempDir, !useSdk,
         bootstrapDependencies(buildDir), exec, args, environmentOverrides);
   }
 
-  CompilationCommand computeAssembleCommand(
-      String tempDir,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeAssembleCommand(String tempDir, String buildDir,
+      List arguments, Map<String, String> environmentOverrides) {
     String cc, shared, ldFlags;
     if (isAndroid) {
       var ndk = "third_party/android_tools/ndk";
@@ -726,29 +689,19 @@
     args.add('$tempDir/out.aotsnapshot');
     args.add('$tempDir/out.S');
 
-    return commandBuilder.getCompilationCommand('assemble', tempDir, !useSdk,
+    return Command.compilation('assemble', tempDir, !useSdk,
         bootstrapDependencies(buildDir), exec, args, environmentOverrides);
   }
 
   // This step reduces the amount of space needed to run the precompilation
   // tests by 60%.
-  CompilationCommand computeRemoveAssemblyCommand(
-      String tempDir,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeRemoveAssemblyCommand(String tempDir, String buildDir,
+      List arguments, Map<String, String> environmentOverrides) {
     var exec = 'rm';
     var args = ['$tempDir/out.S'];
 
-    return commandBuilder.getCompilationCommand(
-        'remove_assembly',
-        tempDir,
-        !useSdk,
-        bootstrapDependencies(buildDir),
-        exec,
-        args,
-        environmentOverrides);
+    return Command.compilation('remove_assembly', tempDir, !useSdk,
+        bootstrapDependencies(buildDir), exec, args, environmentOverrides);
   }
 
   List<String> filterVmOptions(List<String> vmOptions) {
@@ -814,31 +767,23 @@
     return multiplier;
   }
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     var snapshot = "$tempDir/out.jitsnapshot";
-    return new CommandArtifact(<Command>[
-      this.computeCompilationCommand(tempDir, buildDir, CommandBuilder.instance,
-          arguments, environmentOverrides)
+    return new CommandArtifact([
+      computeCompilationCommand(
+          tempDir, buildDir, arguments, environmentOverrides)
     ], snapshot, 'application/dart-snapshot');
   }
 
-  CompilationCommand computeCompilationCommand(
-      String tempDir,
-      String buildDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  Command computeCompilationCommand(String tempDir, String buildDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     var exec = "$buildDir/dart";
     var snapshot = "$tempDir/out.jitsnapshot";
     var args = ["--snapshot=$snapshot", "--snapshot-kind=app-jit"];
     args.addAll(arguments);
 
-    return commandBuilder.getCompilationCommand('app_jit', tempDir, !useSdk,
+    return Command.compilation('app_jit', tempDir, !useSdk,
         bootstrapDependencies(buildDir), exec, args, environmentOverrides);
   }
 
@@ -912,12 +857,8 @@
     return '$prefix/dartanalyzer$suffix';
   }
 
-  CommandArtifact computeCompilationArtifact(
-      String buildDir,
-      String tempDir,
-      CommandBuilder commandBuilder,
-      List<String> arguments,
-      Map<String, String> environmentOverrides) {
+  CommandArtifact computeCompilationArtifact(String buildDir, String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
     arguments = arguments.toList();
     if (isChecked || isStrong) {
       arguments.add('--enable_type_checks');
@@ -926,9 +867,8 @@
       arguments.add('--strong');
     }
     return new CommandArtifact([
-      commandBuilder.getAnalysisCommand('dart2analyzer',
-          computeCompilerPath(buildDir), arguments, environmentOverrides,
-          flavor: 'dart2analyzer')
+      Command.analysis(
+          computeCompilerPath(buildDir), arguments, environmentOverrides)
     ], null, null); // Since this is not a real compilation, no artifacts are
     // produced.
   }
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index dab39bf..58791fe 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -526,7 +526,7 @@
         return const [Runtime.none];
       case Compiler.appJit:
       case Compiler.dartk:
-        return const [Runtime.vm, Runtime.selfCheck, Runtime.none];
+        return const [Runtime.vm, Runtime.selfCheck];
       case Compiler.precompiler:
       case Compiler.dartkp:
         return const [Runtime.dartPrecompiled];
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 033a4d5..73b9a86 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -4,12 +4,12 @@
 
 import 'dart:io';
 
+import 'command.dart';
 import 'compiler_configuration.dart';
 import 'configuration.dart';
 // TODO(ahe): Remove this import, we can precompute all the values required
 // from TestSuite once the refactoring is complete.
 import 'test_suite.dart';
-import 'test_runner.dart';
 import 'utils.dart';
 
 /// Describes the commands to run a given test case or its compiled output.
@@ -82,7 +82,6 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -101,7 +100,6 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -128,14 +126,13 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
     // TODO(ahe): Avoid duplication of this method between d8 and jsshell.
     checkArtifact(artifact);
-    return <Command>[
-      commandBuilder.getJSCommandlineCommand(
+    return [
+      Command.jsCommandLine(
           moniker, suite.d8FileName, arguments, environmentOverrides)
     ];
   }
@@ -151,13 +148,12 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
     checkArtifact(artifact);
-    return <Command>[
-      commandBuilder.getJSCommandlineCommand(
+    return [
+      Command.jsCommandLine(
           moniker, suite.jsShellFileName, arguments, environmentOverrides)
     ];
   }
@@ -226,7 +222,6 @@
 class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -238,9 +233,7 @@
       throw "Dart VM cannot run files of type '$type'.";
     }
     String executable = suite.dartVmBinaryFileName;
-    return <Command>[
-      commandBuilder.getVmCommand(executable, arguments, environmentOverrides)
-    ];
+    return [Command.vm(executable, arguments, environmentOverrides)];
   }
 }
 
@@ -248,7 +241,6 @@
 class StandaloneFlutterEngineConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -261,9 +253,7 @@
     }
     String executable = suite.flutterEngineBinaryFileName;
     var args = <String>['--non-interactive']..addAll(arguments);
-    return <Command>[
-      commandBuilder.getVmCommand(executable, args, environmentOverrides)
-    ];
+    return [Command.vm(executable, args, environmentOverrides)];
   }
 }
 
@@ -273,7 +263,6 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -283,8 +272,8 @@
       throw "dart_precompiled cannot run files of type '$type'.";
     }
 
-    return <Command>[
-      commandBuilder.getVmCommand(
+    return [
+      Command.vm(
           suite.dartPrecompiledBinaryFileName, arguments, environmentOverrides)
     ];
   }
@@ -301,7 +290,6 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -313,8 +301,8 @@
 
     String precompiledRunner = suite.dartPrecompiledBinaryFileName;
     String processTest = suite.processTestBinaryFileName;
-    return <Command>[
-      commandBuilder.getAdbPrecompiledCommand(
+    return [
+      Command.adbPrecompiled(
           precompiledRunner, processTest, script, arguments, useBlobs)
     ];
   }
@@ -338,13 +326,12 @@
 
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
     String executable = suite.dartVmBinaryFileName;
     return selfCheckers
-        .map((String tester) => commandBuilder.getVmBatchCommand(
+        .map((String tester) => Command.vmBatch(
             executable, tester, arguments, environmentOverrides,
             checked: suite.configuration.isChecked))
         .toList();
@@ -360,7 +347,6 @@
 class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
       TestSuite suite,
-      CommandBuilder commandBuilder,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index f1a21f2..e4de583 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -5,6 +5,8 @@
 import 'dart:convert' show JSON;
 import 'dart:io';
 
+import 'command.dart';
+import 'command_output.dart';
 import 'configuration.dart';
 import 'expectation.dart';
 import 'path.dart';
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 145e3dd..ec13aea 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -19,10 +19,11 @@
 
 import 'android.dart';
 import 'browser_controller.dart';
+import 'command.dart';
+import 'command_output.dart';
 import 'configuration.dart';
 import 'dependency_graph.dart' as dgraph;
 import 'expectation.dart';
-import 'path.dart';
 import 'runtime_configuration.dart';
 import 'test_progress.dart';
 import 'test_suite.dart';
@@ -52,670 +53,6 @@
   'NO_PROXY'
 ];
 
-/** A command executed as a step in a test case. */
-class Command {
-  /** A descriptive name for this command. */
-  String displayName;
-
-  /** Number of times this command *can* be retried */
-  int get maxNumRetries => 2;
-
-  /** Reproduction command */
-  String get reproductionCommand => null;
-
-  // We compute the Command.hashCode lazily and cache it here, since it might
-  // be expensive to compute (and hashCode is called often).
-  int _cachedHashCode;
-
-  Command._(this.displayName);
-
-  int get hashCode {
-    if (_cachedHashCode == null) {
-      var builder = new HashCodeBuilder();
-      _buildHashCode(builder);
-      _cachedHashCode = builder.value;
-    }
-    return _cachedHashCode;
-  }
-
-  operator ==(Object other) =>
-      identical(this, other) ||
-      (runtimeType == other.runtimeType && _equal(other as Command));
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    builder.addJson(displayName);
-  }
-
-  bool _equal(covariant Command other) =>
-      hashCode == other.hashCode && displayName == other.displayName;
-
-  String toString() => reproductionCommand;
-
-  Future<bool> get outputIsUpToDate => new Future.value(false);
-}
-
-class ProcessCommand extends Command {
-  /** Path to the executable of this command. */
-  String executable;
-
-  /** Command line arguments to the executable. */
-  List<String> arguments;
-
-  /** Environment for the command */
-  Map<String, String> environmentOverrides;
-
-  /** Working directory for the command */
-  final String workingDirectory;
-
-  ProcessCommand._(String displayName, this.executable, this.arguments,
-      [this.environmentOverrides = null, this.workingDirectory = null])
-      : super._(displayName) {
-    if (io.Platform.operatingSystem == 'windows') {
-      // Windows can't handle the first command if it is a .bat file or the like
-      // with the slashes going the other direction.
-      // NOTE: Issue 1306
-      executable = executable.replaceAll('/', '\\');
-    }
-  }
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(executable);
-    builder.addJson(workingDirectory);
-    builder.addJson(arguments);
-    builder.addJson(environmentOverrides);
-  }
-
-  bool _equal(ProcessCommand other) =>
-      super._equal(other) &&
-      executable == other.executable &&
-      deepJsonCompare(arguments, other.arguments) &&
-      workingDirectory == other.workingDirectory &&
-      deepJsonCompare(environmentOverrides, other.environmentOverrides);
-
-  String get reproductionCommand {
-    var env = new StringBuffer();
-    environmentOverrides?.forEach((key, value) =>
-        (io.Platform.operatingSystem == 'windows')
-            ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
-            : env.write('$key=${escapeCommandLineArgument(value)} '));
-    var command = ([executable]..addAll(batchArguments)..addAll(arguments))
-        .map(escapeCommandLineArgument)
-        .join(' ');
-    if (workingDirectory != null) {
-      command = "$command (working directory: $workingDirectory)";
-    }
-    return "$env$command";
-  }
-
-  Future<bool> get outputIsUpToDate => new Future.value(false);
-
-  /// Arguments that are passed to the process when starting batch mode.
-  ///
-  /// In non-batch mode, they should be passed before [arguments].
-  List<String> get batchArguments => const [];
-}
-
-class CompilationCommand extends ProcessCommand {
-  final String _outputFile;
-  final bool _neverSkipCompilation;
-  final List<Uri> _bootstrapDependencies;
-
-  CompilationCommand._(
-      String displayName,
-      this._outputFile,
-      this._neverSkipCompilation,
-      this._bootstrapDependencies,
-      String executable,
-      List<String> arguments,
-      Map<String, String> environmentOverrides)
-      : super._(displayName, executable, arguments, environmentOverrides);
-
-  Future<bool> get outputIsUpToDate {
-    if (_neverSkipCompilation) return new Future.value(false);
-
-    Future<List<Uri>> readDepsFile(String path) {
-      var file = new io.File(new Path(path).toNativePath());
-      if (!file.existsSync()) {
-        return new Future.value(null);
-      }
-      return file.readAsLines().then((List<String> lines) {
-        var dependencies = new List<Uri>();
-        for (var line in lines) {
-          line = line.trim();
-          if (line.length > 0) {
-            dependencies.add(Uri.parse(line));
-          }
-        }
-        return dependencies;
-      });
-    }
-
-    return readDepsFile("$_outputFile.deps").then((dependencies) {
-      if (dependencies != null) {
-        dependencies.addAll(_bootstrapDependencies);
-        var jsOutputLastModified = TestUtils.lastModifiedCache
-            .getLastModified(new Uri(scheme: 'file', path: _outputFile));
-        if (jsOutputLastModified != null) {
-          for (var dependency in dependencies) {
-            var dependencyLastModified =
-                TestUtils.lastModifiedCache.getLastModified(dependency);
-            if (dependencyLastModified == null ||
-                dependencyLastModified.isAfter(jsOutputLastModified)) {
-              return false;
-            }
-          }
-          return true;
-        }
-      }
-      return false;
-    });
-  }
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(_outputFile);
-    builder.addJson(_neverSkipCompilation);
-    builder.addJson(_bootstrapDependencies);
-  }
-
-  bool _equal(CompilationCommand other) =>
-      super._equal(other) &&
-      _outputFile == other._outputFile &&
-      _neverSkipCompilation == other._neverSkipCompilation &&
-      deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
-}
-
-class KernelCompilationCommand extends CompilationCommand {
-  KernelCompilationCommand._(
-      String displayName,
-      String outputFile,
-      bool neverSkipCompilation,
-      List<Uri> bootstrapDependencies,
-      String executable,
-      List<String> arguments,
-      Map<String, String> environmentOverrides)
-      : super._(displayName, outputFile, neverSkipCompilation,
-            bootstrapDependencies, executable, arguments, environmentOverrides);
-
-  int get maxNumRetries => 1;
-}
-
-/// This is just a Pair(String, Map) class with hashCode and operator ==
-class AddFlagsKey {
-  final String flags;
-  final Map env;
-  AddFlagsKey(this.flags, this.env);
-  // Just use object identity for environment map
-  bool operator ==(Object other) =>
-      other is AddFlagsKey && flags == other.flags && env == other.env;
-  int get hashCode => flags.hashCode ^ env.hashCode;
-}
-
-class ContentShellCommand extends ProcessCommand {
-  ContentShellCommand._(
-      String executable,
-      String htmlFile,
-      List<String> options,
-      List<String> dartFlags,
-      Map<String, String> environmentOverrides)
-      : super._("content_shell", executable, _getArguments(options, htmlFile),
-            _getEnvironment(environmentOverrides, dartFlags));
-
-  // Cache the modified environments in a map from the old environment and
-  // the string of Dart flags to the new environment.  Avoid creating new
-  // environment object for each command object.
-  static Map<AddFlagsKey, Map<String, String>> environments = {};
-
-  static Map<String, String> _getEnvironment(
-      Map<String, String> env, List<String> dartFlags) {
-    var needDartFlags = dartFlags != null && dartFlags.isNotEmpty;
-    if (needDartFlags) {
-      if (env == null) {
-        env = const <String, String>{};
-      }
-      var flags = dartFlags.join(' ');
-      return environments.putIfAbsent(
-          new AddFlagsKey(flags, env),
-          () => new Map<String, String>.from(env)
-            ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'}));
-    }
-    return env;
-  }
-
-  static List<String> _getArguments(List<String> options, String htmlFile) {
-    var arguments = options.toList();
-    arguments.add(htmlFile);
-    return arguments;
-  }
-
-  int get maxNumRetries => 3;
-}
-
-class BrowserTestCommand extends Command {
-  Runtime get browser => configuration.runtime;
-  final String url;
-  final Configuration configuration;
-  final bool retry;
-
-  BrowserTestCommand._(this.url, this.configuration, this.retry)
-      : super._(configuration.runtime.name);
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(browser.name);
-    builder.addJson(url);
-    builder.add(configuration);
-    builder.add(retry);
-  }
-
-  bool _equal(BrowserTestCommand other) =>
-      super._equal(other) &&
-      browser == other.browser &&
-      url == other.url &&
-      identical(configuration, other.configuration) &&
-      retry == other.retry;
-
-  String get reproductionCommand {
-    var parts = [
-      io.Platform.resolvedExecutable,
-      'tools/testing/dart/launch_browser.dart',
-      browser.name,
-      url
-    ];
-    return parts.map(escapeCommandLineArgument).join(' ');
-  }
-
-  int get maxNumRetries => 4;
-}
-
-class BrowserHtmlTestCommand extends BrowserTestCommand {
-  List<String> expectedMessages;
-  BrowserHtmlTestCommand._(String url, Configuration configuration,
-      this.expectedMessages, bool retry)
-      : super._(url, configuration, retry);
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(expectedMessages);
-  }
-
-  bool _equal(BrowserHtmlTestCommand other) =>
-      super._equal(other) &&
-      identical(expectedMessages, other.expectedMessages);
-}
-
-class AnalysisCommand extends ProcessCommand {
-  final String flavor;
-
-  AnalysisCommand._(this.flavor, String displayName, String executable,
-      List<String> arguments, Map<String, String> environmentOverrides)
-      : super._(displayName, executable, arguments, environmentOverrides);
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(flavor);
-  }
-
-  bool _equal(AnalysisCommand other) =>
-      super._equal(other) && flavor == other.flavor;
-}
-
-class VmCommand extends ProcessCommand {
-  VmCommand._(String executable, List<String> arguments,
-      Map<String, String> environmentOverrides)
-      : super._("vm", executable, arguments, environmentOverrides);
-}
-
-class VmBatchCommand extends ProcessCommand implements VmCommand {
-  final String dartFile;
-  final bool checked;
-
-  VmBatchCommand._(String executable, String dartFile, List<String> arguments,
-      Map<String, String> environmentOverrides,
-      {this.checked: true})
-      : this.dartFile = dartFile,
-        super._('vm-batch', executable, arguments, environmentOverrides);
-
-  @override
-  List<String> get batchArguments =>
-      checked ? ['--checked', dartFile] : [dartFile];
-
-  @override
-  bool _equal(VmBatchCommand other) {
-    return super._equal(other) &&
-        dartFile == other.dartFile &&
-        checked == other.checked;
-  }
-
-  @override
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(dartFile);
-    builder.addJson(checked);
-  }
-}
-
-class AdbPrecompilationCommand extends Command {
-  final String precompiledRunnerFilename;
-  final String processTestFilename;
-  final String precompiledTestDirectory;
-  final List<String> arguments;
-  final bool useBlobs;
-
-  AdbPrecompilationCommand._(
-      this.precompiledRunnerFilename,
-      this.processTestFilename,
-      this.precompiledTestDirectory,
-      this.arguments,
-      this.useBlobs)
-      : super._("adb_precompilation");
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.add(precompiledRunnerFilename);
-    builder.add(precompiledTestDirectory);
-    builder.add(arguments);
-    builder.add(useBlobs);
-  }
-
-  bool _equal(AdbPrecompilationCommand other) =>
-      super._equal(other) &&
-      precompiledRunnerFilename == other.precompiledRunnerFilename &&
-      useBlobs == other.useBlobs &&
-      arguments == other.arguments &&
-      precompiledTestDirectory == other.precompiledTestDirectory;
-
-  String toString() => 'Steps to push precompiled runner and precompiled code '
-      'to an attached device. Uses (and requires) adb.';
-}
-
-class JSCommandlineCommand extends ProcessCommand {
-  JSCommandlineCommand._(
-      String displayName, String executable, List<String> arguments,
-      [Map<String, String> environmentOverrides = null])
-      : super._(displayName, executable, arguments, environmentOverrides);
-}
-
-class PubCommand extends ProcessCommand {
-  final String command;
-
-  PubCommand._(String pubCommand, String pubExecutable,
-      String pubspecYamlDirectory, String pubCacheDirectory, List<String> args)
-      : command = pubCommand,
-        super._(
-            'pub_$pubCommand',
-            new io.File(pubExecutable).absolute.path,
-            [pubCommand]..addAll(args),
-            {'PUB_CACHE': pubCacheDirectory},
-            pubspecYamlDirectory);
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(command);
-  }
-
-  bool _equal(PubCommand other) =>
-      super._equal(other) && command == other.command;
-}
-
-/* [ScriptCommand]s are executed by dart code. */
-abstract class ScriptCommand extends Command {
-  ScriptCommand._(String displayName) : super._(displayName);
-
-  Future<ScriptCommandOutputImpl> run();
-}
-
-class CleanDirectoryCopyCommand extends ScriptCommand {
-  final String _sourceDirectory;
-  final String _destinationDirectory;
-
-  CleanDirectoryCopyCommand._(this._sourceDirectory, this._destinationDirectory)
-      : super._('dir_copy');
-
-  String get reproductionCommand =>
-      "Copying '$_sourceDirectory' to '$_destinationDirectory'.";
-
-  Future<ScriptCommandOutputImpl> run() {
-    var watch = new Stopwatch()..start();
-
-    var destination = new io.Directory(_destinationDirectory);
-
-    return destination.exists().then((bool exists) {
-      Future cleanDirectoryFuture;
-      if (exists) {
-        cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory);
-      } else {
-        cleanDirectoryFuture = new Future.value(null);
-      }
-      return cleanDirectoryFuture.then((_) {
-        return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory);
-      });
-    }).then((_) {
-      return new ScriptCommandOutputImpl(
-          this, Expectation.pass, "", watch.elapsed);
-    }).catchError((error) {
-      return new ScriptCommandOutputImpl(
-          this, Expectation.fail, "An error occured: $error.", watch.elapsed);
-    });
-  }
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(_sourceDirectory);
-    builder.addJson(_destinationDirectory);
-  }
-
-  bool _equal(CleanDirectoryCopyCommand other) =>
-      super._equal(other) &&
-      _sourceDirectory == other._sourceDirectory &&
-      _destinationDirectory == other._destinationDirectory;
-}
-
-/*
- * [MakeSymlinkCommand] makes a symbolic link to another directory.
- */
-class MakeSymlinkCommand extends ScriptCommand {
-  String _link;
-  String _target;
-
-  MakeSymlinkCommand._(this._link, this._target) : super._('make_symlink');
-
-  String get reproductionCommand =>
-      "Make symbolic link '$_link' (target: $_target)'.";
-
-  Future<ScriptCommandOutputImpl> run() {
-    var watch = new Stopwatch()..start();
-    var targetFile = new io.Directory(_target);
-    return targetFile.exists().then((bool targetExists) {
-      if (!targetExists) {
-        throw new Exception("Target '$_target' does not exist");
-      }
-      var link = new io.Link(_link);
-
-      return link.exists().then((bool exists) {
-        if (exists) return link.delete();
-      }).then((_) => link.create(_target));
-    }).then((_) {
-      return new ScriptCommandOutputImpl(
-          this, Expectation.pass, "", watch.elapsed);
-    }).catchError((error) {
-      return new ScriptCommandOutputImpl(
-          this, Expectation.fail, "An error occured: $error.", watch.elapsed);
-    });
-  }
-
-  void _buildHashCode(HashCodeBuilder builder) {
-    super._buildHashCode(builder);
-    builder.addJson(_link);
-    builder.addJson(_target);
-  }
-
-  bool _equal(MakeSymlinkCommand other) =>
-      super._equal(other) && _link == other._link && _target == other._target;
-}
-
-class CommandBuilder {
-  static final CommandBuilder instance = new CommandBuilder._();
-
-  bool _cleared = false;
-  final _cachedCommands = new Map<Command, Command>();
-
-  CommandBuilder._();
-
-  void clearCommandCache() {
-    _cachedCommands.clear();
-    _cleared = true;
-  }
-
-  ContentShellCommand getContentShellCommand(
-      String executable,
-      String htmlFile,
-      List<String> options,
-      List<String> dartFlags,
-      Map<String, String> environment) {
-    ContentShellCommand command = new ContentShellCommand._(
-        executable, htmlFile, options, dartFlags, environment);
-    return _getUniqueCommand(command);
-  }
-
-  BrowserTestCommand getBrowserTestCommand(
-      String url, Configuration configuration, bool retry) {
-    var command = new BrowserTestCommand._(url, configuration, retry);
-    return _getUniqueCommand(command);
-  }
-
-  BrowserHtmlTestCommand getBrowserHtmlTestCommand(String url,
-      Configuration configuration, List<String> expectedMessages, bool retry) {
-    var command = new BrowserHtmlTestCommand._(
-        url, configuration, expectedMessages, retry);
-    return _getUniqueCommand(command);
-  }
-
-  CompilationCommand getCompilationCommand(
-      String displayName,
-      String outputFile,
-      bool neverSkipCompilation,
-      List<Uri> bootstrapDependencies,
-      String executable,
-      List<String> arguments,
-      Map<String, String> environment) {
-    var command = new CompilationCommand._(
-        displayName,
-        outputFile,
-        neverSkipCompilation,
-        bootstrapDependencies,
-        executable,
-        arguments,
-        environment);
-    return _getUniqueCommand(command);
-  }
-
-  CompilationCommand getKernelCompilationCommand(
-      String displayName,
-      String outputFile,
-      bool neverSkipCompilation,
-      List<Uri> bootstrapDependencies,
-      String executable,
-      List<String> arguments,
-      Map<String, String> environment) {
-    var command = new KernelCompilationCommand._(
-        displayName,
-        outputFile,
-        neverSkipCompilation,
-        bootstrapDependencies,
-        executable,
-        arguments,
-        environment);
-    return _getUniqueCommand(command);
-  }
-
-  AnalysisCommand getAnalysisCommand(String displayName, String executable,
-      List<String> arguments, Map<String, String> environmentOverrides,
-      {String flavor: 'dart2analyzer'}) {
-    var command = new AnalysisCommand._(
-        flavor, displayName, executable, arguments, environmentOverrides);
-    return _getUniqueCommand(command);
-  }
-
-  VmCommand getVmCommand(String executable, List<String> arguments,
-      Map<String, String> environmentOverrides) {
-    var command = new VmCommand._(executable, arguments, environmentOverrides);
-    return _getUniqueCommand(command);
-  }
-
-  VmBatchCommand getVmBatchCommand(String executable, String tester,
-      List<String> arguments, Map<String, String> environmentOverrides,
-      {bool checked: true}) {
-    var command = new VmBatchCommand._(
-        executable, tester, arguments, environmentOverrides,
-        checked: checked);
-    return _getUniqueCommand(command);
-  }
-
-  AdbPrecompilationCommand getAdbPrecompiledCommand(
-      String precompiledRunner,
-      String processTest,
-      String testDirectory,
-      List<String> arguments,
-      bool useBlobs) {
-    var command = new AdbPrecompilationCommand._(
-        precompiledRunner, processTest, testDirectory, arguments, useBlobs);
-    return _getUniqueCommand(command);
-  }
-
-  Command getJSCommandlineCommand(
-      String displayName, String executable, List<String> arguments,
-      [Map<String, String> environment]) {
-    var command = new JSCommandlineCommand._(
-        displayName, executable, arguments, environment);
-    return _getUniqueCommand(command);
-  }
-
-  Command getProcessCommand(
-      String displayName, String executable, List<String> arguments,
-      [Map<String, String> environment, String workingDirectory]) {
-    var command = new ProcessCommand._(
-        displayName, executable, arguments, environment, workingDirectory);
-    return _getUniqueCommand(command);
-  }
-
-  Command getCopyCommand(String sourceDirectory, String destinationDirectory) {
-    var command =
-        new CleanDirectoryCopyCommand._(sourceDirectory, destinationDirectory);
-    return _getUniqueCommand(command);
-  }
-
-  Command getPubCommand(String pubCommand, String pubExecutable,
-      String pubspecYamlDirectory, String pubCacheDirectory,
-      {List<String> arguments: const <String>[]}) {
-    var command = new PubCommand._(pubCommand, pubExecutable,
-        pubspecYamlDirectory, pubCacheDirectory, arguments);
-    return _getUniqueCommand(command);
-  }
-
-  Command getMakeSymlinkCommand(String link, String target) {
-    return _getUniqueCommand(new MakeSymlinkCommand._(link, target));
-  }
-
-  T _getUniqueCommand<T extends Command>(T command) {
-    // All Command classes implement hashCode and operator==.
-    // We check if this command has already been built.
-    //  If so, we return the cached one. Otherwise we
-    // store the one given as [command] argument.
-    if (_cleared) {
-      throw new Exception(
-          "CommandBuilder.get[type]Command called after cache cleared");
-    }
-    var cachedCommand = _cachedCommands[command];
-    if (cachedCommand != null) {
-      return cachedCommand as T;
-    }
-    _cachedCommands[command] = command;
-    return command;
-  }
-}
-
 /**
  * TestCase contains all the information needed to run a test and evaluate
  * its output.  Running a test involves starting a separate process, with
@@ -761,6 +98,9 @@
   TestCase(this.displayName, this.commands, this.configuration,
       this.expectedOutcomes,
       {bool isNegative: false, TestInformation info}) {
+    // A test case should do something.
+    assert(commands.isNotEmpty);
+
     if (isNegative || displayName.contains("negative_test")) {
       _expectations |= IS_NEGATIVE;
     }
@@ -886,906 +226,6 @@
   String get testingUrl => _testingUrl;
 }
 
-class UnittestSuiteMessagesMixin {
-  bool _isAsyncTest(String testOutput) {
-    return testOutput.contains("unittest-suite-wait-for-done");
-  }
-
-  bool _isAsyncTestSuccessful(String testOutput) {
-    return testOutput.contains("unittest-suite-success");
-  }
-
-  Expectation _negateOutcomeIfIncompleteAsyncTest(
-      Expectation outcome, String testOutput) {
-    // If this is an asynchronous test and the asynchronous operation didn't
-    // complete successfully, it's outcome is Expectation.FAIL.
-    // TODO: maybe we should introduce a AsyncIncomplete marker or so
-    if (outcome == Expectation.pass) {
-      if (_isAsyncTest(testOutput) && !_isAsyncTestSuccessful(testOutput)) {
-        return Expectation.fail;
-      }
-    }
-    return outcome;
-  }
-}
-
-/**
- * CommandOutput records the output of a completed command: the process's exit
- * code, the standard output and standard error, whether the process timed out,
- * and the time the process took to run.  It does not contain a pointer to the
- * [TestCase] this is the output of, so some functions require the test case
- * to be passed as an argument.
- */
-abstract class CommandOutput {
-  Command get command;
-
-  Expectation result(TestCase testCase);
-
-  bool get hasCrashed;
-
-  bool get hasTimedOut;
-
-  bool didFail(TestCase testCase);
-
-  bool hasFailed(TestCase testCase);
-
-  bool get canRunDependendCommands;
-
-  bool get successful; // otherwise we might to retry running
-
-  Duration get time;
-
-  int get exitCode;
-
-  int get pid;
-
-  List<int> get stdout;
-
-  List<int> get stderr;
-
-  List<String> get diagnostics;
-
-  bool get compilationSkipped;
-}
-
-class CommandOutputImpl extends UniqueObject implements CommandOutput {
-  Command command;
-  int exitCode;
-
-  bool timedOut;
-  List<int> stdout;
-  List<int> stderr;
-  Duration time;
-  List<String> diagnostics;
-  bool compilationSkipped;
-  int pid;
-
-  /**
-   * A flag to indicate we have already printed a warning about ignoring the VM
-   * crash, to limit the amount of output produced per test.
-   */
-  bool alreadyPrintedWarning = false;
-
-  CommandOutputImpl(
-      Command this.command,
-      int this.exitCode,
-      bool this.timedOut,
-      List<int> this.stdout,
-      List<int> this.stderr,
-      Duration this.time,
-      bool this.compilationSkipped,
-      int this.pid) {
-    diagnostics = [];
-  }
-
-  Expectation result(TestCase testCase) {
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasFailed(testCase)) return Expectation.fail;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-    return Expectation.pass;
-  }
-
-  bool get hasCrashed {
-    // dart2js exits with code 253 in case of unhandled exceptions.
-    // The dart binary exits with code 253 in case of an API error such
-    // as an invalid snapshot file.
-    // In either case an exit code of 253 is considered a crash.
-    if (exitCode == 253) return true;
-    if (io.Platform.operatingSystem == 'windows') {
-      // The VM uses std::abort to terminate on asserts.
-      // std::abort terminates with exit code 3 on Windows.
-      if (exitCode == 3 || exitCode == CRASHING_BROWSER_EXITCODE) {
-        return !timedOut;
-      }
-      // If a program receives an uncaught system exception, the program
-      // terminates with the exception code as exit code.
-      // The 0x3FFFFF00 mask here tries to determine if an exception indicates
-      // a crash of the program.
-      // System exception codes can be found in 'winnt.h', for example
-      // "#define STATUS_ACCESS_VIOLATION  ((DWORD) 0xC0000005)"
-      return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0));
-    }
-    return !timedOut && ((exitCode < 0));
-  }
-
-  bool get hasTimedOut => timedOut;
-
-  bool didFail(TestCase testCase) {
-    return (exitCode != 0 && !hasCrashed);
-  }
-
-  bool get canRunDependendCommands {
-    // FIXME(kustermann): We may need to change this
-    return !hasTimedOut && exitCode == 0;
-  }
-
-  bool get successful {
-    // FIXME(kustermann): We may need to change this
-    return !hasTimedOut && exitCode == 0;
-  }
-
-  // Reverse result of a negative test.
-  bool hasFailed(TestCase testCase) {
-    return testCase.isNegative ? !didFail(testCase) : didFail(testCase);
-  }
-
-  bool get hasNonUtf8 => exitCode == NON_UTF_FAKE_EXITCODE;
-
-  Expectation _negateOutcomeIfNegativeTest(
-      Expectation outcome, bool isNegative) {
-    if (!isNegative) return outcome;
-    if (outcome == Expectation.ignore) return outcome;
-    if (outcome.canBeOutcomeOf(Expectation.fail)) {
-      return Expectation.pass;
-    }
-    return Expectation.fail;
-  }
-}
-
-class ContentShellCommandOutputImpl extends CommandOutputImpl {
-  // Although tests are reported as passing, content shell sometimes exits with
-  // a nonzero exitcode which makes our dartium builders extremely falky.
-  // See: http://dartbug.com/15139.
-  // TODO(rnystrom): Is this still needed? The underlying bug is closed.
-  static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022;
-  static bool isWindows = io.Platform.operatingSystem == 'windows';
-  static bool _failedBecauseOfFlakyInfrastructure(
-      Command command, bool timedOut, List<int> stderrBytes) {
-    // If the browser test failed, it may have been because content shell
-    // and the virtual framebuffer X server didn't hook up, or it crashed with
-    // a core dump. Sometimes content shell crashes after it has set the stdout
-    // to PASS, so we have to do this check first.
-    // Content shell also fails with a broken pipe message: Issue 26739
-    var zygoteCrash =
-        new RegExp(r"ERROR:zygote_linux\.cc\(\d+\)] write: Broken pipe");
-    var stderr = decodeUtf8(stderrBytes);
-    // TODO(7564): See http://dartbug.com/7564
-    // This may not be happening anymore.  Test by removing this suppression.
-    if (stderr.contains(MESSAGE_CANNOT_OPEN_DISPLAY) ||
-        stderr.contains(MESSAGE_FAILED_TO_RUN_COMMAND)) {
-      DebugLogger.warning(
-          "Warning: Failure because of missing XDisplay. Test ignored");
-      return true;
-    }
-    // TODO(26739): See http://dartbug.com/26739
-    if (zygoteCrash.hasMatch(stderr)) {
-      DebugLogger.warning("Warning: Failure because of content_shell "
-          "zygote crash. Test ignored");
-      return true;
-    }
-    return false;
-  }
-
-  bool _infraFailure;
-
-  ContentShellCommandOutputImpl(
-      Command command,
-      int exitCode,
-      bool timedOut,
-      List<int> stdout,
-      List<int> stderr,
-      Duration time,
-      bool compilationSkipped)
-      : _infraFailure =
-            _failedBecauseOfFlakyInfrastructure(command, timedOut, stderr),
-        super(command, exitCode, timedOut, stdout, stderr, time,
-            compilationSkipped, 0);
-
-  Expectation result(TestCase testCase) {
-    if (_infraFailure) {
-      return Expectation.ignore;
-    }
-
-    // Handle crashes and timeouts first
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    var outcome = _getOutcome();
-
-    if (testCase.hasRuntimeError) {
-      if (!outcome.canBeOutcomeOf(Expectation.runtimeError)) {
-        return Expectation.missingRuntimeError;
-      }
-    }
-    if (testCase.isNegative) {
-      if (outcome.canBeOutcomeOf(Expectation.fail)) return Expectation.pass;
-      return Expectation.fail;
-    }
-    return outcome;
-  }
-
-  bool get successful => canRunDependendCommands;
-
-  bool get canRunDependendCommands {
-    // We cannot rely on the exit code of content_shell as a method to
-    // determine if we were successful or not.
-    return super.canRunDependendCommands && !didFail(null);
-  }
-
-  bool get hasCrashed {
-    return super.hasCrashed || _rendererCrashed;
-  }
-
-  Expectation _getOutcome() {
-    if (_browserTestFailure) {
-      return Expectation.runtimeError;
-    }
-    return Expectation.pass;
-  }
-
-  bool get _rendererCrashed =>
-      decodeUtf8(super.stdout).contains("#CRASHED - rendere");
-
-  bool get _browserTestFailure {
-    // Browser tests fail unless stdout contains
-    // 'Content-Type: text/plain' followed by 'PASS'.
-    bool hasContentType = false;
-    var stdoutLines = decodeUtf8(super.stdout).split("\n");
-    var containsFail = false;
-    var containsPass = false;
-    for (String line in stdoutLines) {
-      switch (line) {
-        case 'Content-Type: text/plain':
-          hasContentType = true;
-          break;
-        case 'FAIL':
-          if (hasContentType) {
-            containsFail = true;
-          }
-          break;
-        case 'PASS':
-          if (hasContentType) {
-            containsPass = true;
-          }
-          break;
-      }
-    }
-    if (hasContentType) {
-      if (containsFail && containsPass) {
-        DebugLogger.warning("Test had 'FAIL' and 'PASS' in stdout. ($command)");
-      }
-      if (!containsFail && !containsPass) {
-        DebugLogger.warning("Test had neither 'FAIL' nor 'PASS' in stdout. "
-            "($command)");
-        return true;
-      }
-      if (containsFail) {
-        return true;
-      }
-      assert(containsPass);
-      if (exitCode != 0) {
-        var message = "All tests passed, but exitCode != 0. "
-            "Actual exitcode: $exitCode. "
-            "($command)";
-        DebugLogger.warning(message);
-        diagnostics.add(message);
-      }
-      return (!hasCrashed &&
-          exitCode != 0 &&
-          (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE));
-    }
-    DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. "
-        "($command).");
-    return true;
-  }
-}
-
-// TODO(29869): Remove this class after verifying it isn't used.
-class HTMLBrowserCommandOutputImpl extends ContentShellCommandOutputImpl {
-  HTMLBrowserCommandOutputImpl(
-      Command command,
-      int exitCode,
-      bool timedOut,
-      List<int> stdout,
-      List<int> stderr,
-      Duration time,
-      bool compilationSkipped)
-      : super(command, exitCode, timedOut, stdout, stderr, time,
-            compilationSkipped);
-
-  bool didFail(TestCase testCase) {
-    return _getOutcome() != Expectation.pass;
-  }
-
-  bool get _browserTestFailure {
-    // We should not need to convert back and forward.
-    var output = decodeUtf8(super.stdout);
-    if (output.contains("FAIL")) return true;
-    return !output.contains("PASS");
-  }
-}
-
-class BrowserTestJsonResult {
-  static const ALLOWED_TYPES = const [
-    'sync_exception',
-    'window_onerror',
-    'script_onerror',
-    'window_compilationerror',
-    'print',
-    'message_received',
-    'dom',
-    'debug'
-  ];
-
-  final Expectation outcome;
-  final String htmlDom;
-  final List<dynamic> events;
-
-  BrowserTestJsonResult(this.outcome, this.htmlDom, this.events);
-
-  static BrowserTestJsonResult parseFromString(String content) {
-    void validate(String assertion, bool value) {
-      if (!value) {
-        throw "InvalidFormat sent from browser driving page: $assertion:\n\n"
-            "$content";
-      }
-    }
-
-    try {
-      var events = JSON.decode(content);
-      if (events != null) {
-        validate("Message must be a List", events is List);
-
-        var messagesByType = <String, List<String>>{};
-        ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]);
-
-        for (var entry in events) {
-          validate("An entry must be a Map", entry is Map);
-
-          var type = entry['type'];
-          var value = entry['value'] as String;
-          var timestamp = entry['timestamp'];
-
-          validate("'type' of an entry must be a String", type is String);
-          validate("'type' has to be in $ALLOWED_TYPES.",
-              ALLOWED_TYPES.contains(type));
-          validate(
-              "'timestamp' of an entry must be a number", timestamp is num);
-
-          messagesByType[type].add(value);
-        }
-        validate("The message must have exactly one 'dom' entry.",
-            messagesByType['dom'].length == 1);
-
-        var dom = messagesByType['dom'][0];
-        if (dom.endsWith('\n')) {
-          dom = '$dom\n';
-        }
-
-        return new BrowserTestJsonResult(
-            _getOutcome(messagesByType), dom, events as List<dynamic>);
-      }
-    } catch (error) {
-      // If something goes wrong, we know the content was not in the correct
-      // JSON format. So we can't parse it.
-      // The caller is responsible for falling back to the old way of
-      // determining if a test failed.
-    }
-
-    return null;
-  }
-
-  static Expectation _getOutcome(Map<String, List<String>> messagesByType) {
-    occured(String type) => messagesByType[type].length > 0;
-    searchForMsg(List<String> types, String message) {
-      return types.any((type) => messagesByType[type].contains(message));
-    }
-
-    // FIXME(kustermann,ricow): I think this functionality doesn't work in
-    // test_controller.js: So far I haven't seen anything being reported on
-    // "window.compilationerror"
-    if (occured('window_compilationerror')) {
-      return Expectation.compileTimeError;
-    }
-
-    if (occured('sync_exception') ||
-        occured('window_onerror') ||
-        occured('script_onerror')) {
-      return Expectation.runtimeError;
-    }
-
-    if (messagesByType['dom'][0].contains('FAIL')) {
-      return Expectation.runtimeError;
-    }
-
-    // We search for these messages in 'print' and 'message_received' because
-    // the unittest implementation posts these messages using
-    // "window.postMessage()" instead of the normal "print()" them.
-
-    var isAsyncTest = searchForMsg(
-        ['print', 'message_received'], 'unittest-suite-wait-for-done');
-    var isAsyncSuccess =
-        searchForMsg(['print', 'message_received'], 'unittest-suite-success') ||
-            searchForMsg(['print', 'message_received'], 'unittest-suite-done');
-
-    if (isAsyncTest) {
-      if (isAsyncSuccess) {
-        return Expectation.pass;
-      }
-      return Expectation.runtimeError;
-    }
-
-    var mainStarted =
-        searchForMsg(['print', 'message_received'], 'dart-calling-main');
-    var mainDone =
-        searchForMsg(['print', 'message_received'], 'dart-main-done');
-
-    if (mainStarted && mainDone) {
-      return Expectation.pass;
-    }
-    return Expectation.fail;
-  }
-}
-
-class BrowserControllerTestOutcome extends CommandOutputImpl
-    with UnittestSuiteMessagesMixin {
-  BrowserTestOutput _result;
-  Expectation _rawOutcome;
-
-  factory BrowserControllerTestOutcome(
-      Command command, BrowserTestOutput result) {
-    String indent(String string, int numSpaces) {
-      var spaces = new List.filled(numSpaces, ' ').join('');
-      return string
-          .replaceAll('\r\n', '\n')
-          .split('\n')
-          .map((line) => "$spaces$line")
-          .join('\n');
-    }
-
-    String stdout = "";
-    String stderr = "";
-    Expectation outcome;
-
-    var parsedResult =
-        BrowserTestJsonResult.parseFromString(result.lastKnownMessage);
-    if (parsedResult != null) {
-      outcome = parsedResult.outcome;
-    } else {
-      // Old way of determining whether a test failed or passed.
-      if (result.lastKnownMessage.contains("FAIL")) {
-        outcome = Expectation.runtimeError;
-      } else if (result.lastKnownMessage.contains("PASS")) {
-        outcome = Expectation.pass;
-      } else {
-        outcome = Expectation.runtimeError;
-      }
-    }
-
-    if (result.didTimeout) {
-      if (result.delayUntilTestStarted != null) {
-        stderr = "This test timed out. The delay until the test actually "
-            "started was: ${result.delayUntilTestStarted}.";
-      } else {
-        stderr = "This test has not notified test.py that it started running.";
-      }
-    }
-
-    if (parsedResult != null) {
-      stdout = "events:\n${indent(prettifyJson(parsedResult.events), 2)}\n\n";
-    } else {
-      stdout = "message:\n${indent(result.lastKnownMessage, 2)}\n\n";
-    }
-
-    stderr = '$stderr\n\n'
-        'BrowserOutput while running the test (* EXPERIMENTAL *):\n'
-        'BrowserOutput.stdout:\n'
-        '${indent(result.browserOutput.stdout.toString(), 2)}\n'
-        'BrowserOutput.stderr:\n'
-        '${indent(result.browserOutput.stderr.toString(), 2)}\n'
-        '\n';
-    return new BrowserControllerTestOutcome._internal(
-        command, result, outcome, encodeUtf8(stdout), encodeUtf8(stderr));
-  }
-
-  BrowserControllerTestOutcome._internal(
-      Command command,
-      BrowserTestOutput result,
-      this._rawOutcome,
-      List<int> stdout,
-      List<int> stderr)
-      : super(command, 0, result.didTimeout, stdout, stderr, result.duration,
-            false, 0) {
-    _result = result;
-  }
-
-  Expectation result(TestCase testCase) {
-    // Handle timeouts first
-    if (_result.didTimeout) {
-      if (testCase.configuration.runtime == Runtime.ie11) {
-        // TODO(28955): See http://dartbug.com/28955
-        DebugLogger.warning("Timeout of ie11 on test ${testCase.displayName}");
-        return Expectation.ignore;
-      }
-      return Expectation.timeout;
-    }
-
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    // Multitests are handled specially
-    if (testCase.hasRuntimeError) {
-      if (_rawOutcome == Expectation.runtimeError) return Expectation.pass;
-      return Expectation.missingRuntimeError;
-    }
-
-    return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative);
-  }
-}
-
-class AnalysisCommandOutputImpl extends CommandOutputImpl {
-  // An error line has 8 fields that look like:
-  // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
-  final int ERROR_LEVEL = 0;
-  final int ERROR_TYPE = 1;
-  final int FILENAME = 3;
-  final int FORMATTED_ERROR = 7;
-
-  AnalysisCommandOutputImpl(
-      Command command,
-      int exitCode,
-      bool timedOut,
-      List<int> stdout,
-      List<int> stderr,
-      Duration time,
-      bool compilationSkipped)
-      : super(command, exitCode, timedOut, stdout, stderr, time,
-            compilationSkipped, 0);
-
-  Expectation result(TestCase testCase) {
-    // TODO(kustermann): If we run the analyzer not in batch mode, make sure
-    // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
-    // no errors)
-
-    // Handle crashes and timeouts first
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    // Get the errors/warnings from the analyzer
-    List<String> errors = [];
-    List<String> warnings = [];
-    parseAnalyzerOutput(errors, warnings);
-
-    // Handle errors / missing errors
-    if (testCase.expectCompileError) {
-      if (errors.length > 0) {
-        return Expectation.pass;
-      }
-      return Expectation.missingCompileTimeError;
-    }
-    if (errors.length > 0) {
-      return Expectation.compileTimeError;
-    }
-
-    // Handle static warnings / missing static warnings
-    if (testCase.hasStaticWarning) {
-      if (warnings.length > 0) {
-        return Expectation.pass;
-      }
-      return Expectation.missingStaticWarning;
-    }
-    if (warnings.length > 0) {
-      return Expectation.staticWarning;
-    }
-
-    assert(errors.length == 0 && warnings.length == 0);
-    assert(!testCase.hasCompileError && !testCase.hasStaticWarning);
-    return Expectation.pass;
-  }
-
-  void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) {
-    // Parse a line delimited by the | character using \ as an escape character
-    // like:  FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
-    List<String> splitMachineError(String line) {
-      StringBuffer field = new StringBuffer();
-      List<String> result = [];
-      bool escaped = false;
-      for (var i = 0; i < line.length; i++) {
-        var c = line[i];
-        if (!escaped && c == '\\') {
-          escaped = true;
-          continue;
-        }
-        escaped = false;
-        if (c == '|') {
-          result.add(field.toString());
-          field = new StringBuffer();
-          continue;
-        }
-        field.write(c);
-      }
-      result.add(field.toString());
-      return result;
-    }
-
-    for (String line in decodeUtf8(super.stderr).split("\n")) {
-      if (line.length == 0) continue;
-      List<String> fields = splitMachineError(line);
-      // We only consider errors/warnings for files of interest.
-      if (fields.length > FORMATTED_ERROR) {
-        if (fields[ERROR_LEVEL] == 'ERROR') {
-          outErrors.add(fields[FORMATTED_ERROR]);
-        } else if (fields[ERROR_LEVEL] == 'WARNING') {
-          outWarnings.add(fields[FORMATTED_ERROR]);
-        }
-        // OK to Skip error output that doesn't match the machine format
-      }
-    }
-  }
-}
-
-class VmCommandOutputImpl extends CommandOutputImpl
-    with UnittestSuiteMessagesMixin {
-  static const DART_VM_EXITCODE_DFE_ERROR = 252;
-  static const DART_VM_EXITCODE_COMPILE_TIME_ERROR = 254;
-  static const DART_VM_EXITCODE_UNCAUGHT_EXCEPTION = 255;
-
-  VmCommandOutputImpl(Command command, int exitCode, bool timedOut,
-      List<int> stdout, List<int> stderr, Duration time, int pid)
-      : super(command, exitCode, timedOut, stdout, stderr, time, false, pid);
-
-  Expectation result(TestCase testCase) {
-    // Handle crashes and timeouts first
-    if (exitCode == DART_VM_EXITCODE_DFE_ERROR) return Expectation.dartkCrash;
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    // Multitests are handled specially
-    if (testCase.expectCompileError) {
-      if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
-        return Expectation.pass;
-      }
-      return Expectation.missingCompileTimeError;
-    }
-    if (testCase.hasRuntimeError) {
-      // TODO(kustermann): Do we consider a "runtimeError" only an uncaught
-      // exception or does any nonzero exit code fullfil this requirement?
-      if (exitCode != 0) {
-        return Expectation.pass;
-      }
-      return Expectation.missingRuntimeError;
-    }
-
-    // The actual outcome depends on the exitCode
-    Expectation outcome;
-    if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
-      outcome = Expectation.compileTimeError;
-    } else if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
-      outcome = Expectation.runtimeError;
-    } else if (exitCode != 0) {
-      // This is a general fail, in case we get an unknown nonzero exitcode.
-      outcome = Expectation.fail;
-    } else {
-      outcome = Expectation.pass;
-    }
-    outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
-    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
-  }
-}
-
-class CompilationCommandOutputImpl extends CommandOutputImpl {
-  static const DART2JS_EXITCODE_CRASH = 253;
-
-  CompilationCommandOutputImpl(
-      Command command,
-      int exitCode,
-      bool timedOut,
-      List<int> stdout,
-      List<int> stderr,
-      Duration time,
-      bool compilationSkipped)
-      : super(command, exitCode, timedOut, stdout, stderr, time,
-            compilationSkipped, 0);
-
-  Expectation result(TestCase testCase) {
-    // Handle general crash/timeout detection.
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) {
-      bool isWindows = io.Platform.operatingSystem == 'windows';
-      bool isBrowserTestCase =
-          testCase.commands.any((command) => command is BrowserTestCommand);
-      // TODO(26060) Dart2js batch mode hangs on Windows under heavy load.
-      return (isWindows && isBrowserTestCase)
-          ? Expectation.ignore
-          : Expectation.timeout;
-    }
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    // Handle dart2js specific crash detection
-    if (exitCode == DART2JS_EXITCODE_CRASH ||
-        exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_COMPILE_TIME_ERROR ||
-        exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
-      return Expectation.crash;
-    }
-
-    // Multitests are handled specially
-    if (testCase.expectCompileError) {
-      // Nonzero exit code of the compiler means compilation failed
-      // TODO(kustermann): Do we have a special exit code in that case???
-      if (exitCode != 0) {
-        return Expectation.pass;
-      }
-      return Expectation.missingCompileTimeError;
-    }
-
-    // TODO(kustermann): This is a hack, remove it
-    if (testCase.hasRuntimeError && testCase.commands.length > 1) {
-      // We expected to run the test, but we got an compile time error.
-      // If the compilation succeeded, we wouldn't be in here!
-      assert(exitCode != 0);
-      return Expectation.compileTimeError;
-    }
-
-    Expectation outcome =
-        exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
-    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
-  }
-}
-
-class KernelCompilationCommandOutputImpl extends CompilationCommandOutputImpl {
-  KernelCompilationCommandOutputImpl(
-      Command command,
-      int exitCode,
-      bool timedOut,
-      List<int> stdout,
-      List<int> stderr,
-      Duration time,
-      bool compilationSkipped)
-      : super(command, exitCode, timedOut, stdout, stderr, time,
-            compilationSkipped);
-
-  bool get canRunDependendCommands {
-    // See [BatchRunnerProcess]: 0 means success, 1 means compile-time error.
-    // TODO(asgerf): When the frontend supports it, continue running even if
-    //   there were compile-time errors. See kernel_sdk issue #18.
-    return !hasCrashed && !timedOut && exitCode == 0;
-  }
-
-  Expectation result(TestCase testCase) {
-    Expectation result = super.result(testCase);
-    if (result.canBeOutcomeOf(Expectation.crash)) {
-      return Expectation.dartkCrash;
-    } else if (result.canBeOutcomeOf(Expectation.timeout)) {
-      return Expectation.dartkTimeout;
-    } else if (result.canBeOutcomeOf(Expectation.compileTimeError)) {
-      return Expectation.dartkCompileTimeError;
-    }
-    return result;
-  }
-
-  // If the compiler was able to produce a Kernel IR file we want to run the
-  // result on the Dart VM.  We therefore mark the [KernelCompilationCommand] as
-  // successful.
-  // => This ensures we test that the DartVM produces correct CompileTime errors
-  //    as it is supposed to for our test suites.
-  bool get successful => canRunDependendCommands;
-}
-
-class JsCommandlineOutputImpl extends CommandOutputImpl
-    with UnittestSuiteMessagesMixin {
-  JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut,
-      List<int> stdout, List<int> stderr, Duration time)
-      : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
-
-  Expectation result(TestCase testCase) {
-    // Handle crashes and timeouts first
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    if (testCase.hasRuntimeError) {
-      if (exitCode != 0) return Expectation.pass;
-      return Expectation.missingRuntimeError;
-    }
-
-    var outcome = exitCode == 0 ? Expectation.pass : Expectation.runtimeError;
-    outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
-    return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
-  }
-}
-
-class PubCommandOutputImpl extends CommandOutputImpl {
-  PubCommandOutputImpl(PubCommand command, int exitCode, bool timedOut,
-      List<int> stdout, List<int> stderr, Duration time)
-      : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
-
-  Expectation result(TestCase testCase) {
-    // Handle crashes and timeouts first
-    if (hasCrashed) return Expectation.crash;
-    if (hasTimedOut) return Expectation.timeout;
-    if (hasNonUtf8) return Expectation.nonUtf8Error;
-
-    if (exitCode == 0) {
-      return Expectation.pass;
-    } else if ((command as PubCommand).command == 'get') {
-      return Expectation.pubGetError;
-    } else {
-      return Expectation.fail;
-    }
-  }
-}
-
-class ScriptCommandOutputImpl extends CommandOutputImpl {
-  final Expectation _result;
-
-  ScriptCommandOutputImpl(ScriptCommand command, this._result,
-      String scriptExecutionInformation, Duration time)
-      : super(command, 0, false, [], [], time, false, 0) {
-    var lines = scriptExecutionInformation.split("\n");
-    diagnostics.addAll(lines);
-  }
-
-  Expectation result(TestCase testCase) => _result;
-
-  bool get canRunDependendCommands => _result == Expectation.pass;
-
-  bool get successful => _result == Expectation.pass;
-}
-
-CommandOutput createCommandOutput(Command command, int exitCode, bool timedOut,
-    List<int> stdout, List<int> stderr, Duration time, bool compilationSkipped,
-    [int pid = 0]) {
-  if (command is ContentShellCommand) {
-    return new ContentShellCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-  } else if (command is BrowserTestCommand) {
-    return new HTMLBrowserCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-  } else if (command is AnalysisCommand) {
-    return new AnalysisCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-  } else if (command is VmCommand) {
-    return new VmCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, pid);
-  } else if (command is KernelCompilationCommand) {
-    return new KernelCompilationCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-  } else if (command is AdbPrecompilationCommand) {
-    return new VmCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, pid);
-  } else if (command is CompilationCommand) {
-    if (command.displayName == 'precompiler' ||
-        command.displayName == 'app_jit') {
-      return new VmCommandOutputImpl(
-          command, exitCode, timedOut, stdout, stderr, time, pid);
-    }
-    return new CompilationCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-  } else if (command is JSCommandlineCommand) {
-    return new JsCommandlineOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time);
-  } else if (command is PubCommand) {
-    return new PubCommandOutputImpl(
-        command, exitCode, timedOut, stdout, stderr, time);
-  }
-
-  return new CommandOutputImpl(command, exitCode, timedOut, stdout, stderr,
-      time, compilationSkipped, pid);
-}
-
 /**
  * An OutputLog records the output from a test, but truncates it if
  * it is longer than MAX_HEAD characters, and just keeps the head and
@@ -2738,8 +1178,8 @@
       return _getBatchRunner("dart2js")
           .runCommand("dart2js", command, timeout, command.arguments);
     } else if (command is AnalysisCommand && globalConfiguration.batch) {
-      return _getBatchRunner(command.flavor)
-          .runCommand(command.flavor, command, timeout, command.arguments);
+      return _getBatchRunner(command.displayName)
+          .runCommand(command.displayName, command, timeout, command.arguments);
     } else if (command is ScriptCommand) {
       return command.run();
     } else if (command is AdbPrecompilationCommand) {
@@ -2860,8 +1300,7 @@
     var completer = new Completer<CommandOutput>();
 
     var callback = (BrowserTestOutput output) {
-      completer
-          .complete(new BrowserControllerTestOutcome(browserCommand, output));
+      completer.complete(new BrowserCommandOutputImpl(browserCommand, output));
     };
 
     BrowserTest browserTest;
@@ -3208,10 +1647,6 @@
     testCaseEnqueuer.enqueueTestSuites(testSuites);
   }
 
-  void freeEnqueueingStructures() {
-    CommandBuilder.instance.clearCommandCache();
-  }
-
   void eventFinishedTestCase(TestCase testCase) {
     for (var listener in _eventListener) {
       listener.done(testCase);
@@ -3225,7 +1660,6 @@
   }
 
   void eventAllTestsKnown() {
-    freeEnqueueingStructures();
     for (var listener in _eventListener) {
       listener.allTestsKnown();
     }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 59a3ba6..73d30b1 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -16,6 +16,7 @@
 import 'dart:io';
 
 import 'browser_test.dart';
+import 'command.dart';
 import 'compiler_configuration.dart';
 import 'configuration.dart';
 import 'drt_updater.dart';
@@ -475,7 +476,7 @@
 
     args.add(testName);
 
-    var command = CommandBuilder.instance.getProcessCommand(
+    var command = Command.process(
         'run_vm_unittest', targetRunnerPath, args, environmentOverrides);
     enqueueNewTestCase(
         new TestCase(constructedName, [command], configuration, expectations));
@@ -894,11 +895,7 @@
 
     CommandArtifact compilationArtifact =
         compilerConfiguration.computeCompilationArtifact(
-            buildDir,
-            tempDir,
-            CommandBuilder.instance,
-            compileTimeArguments,
-            environmentOverrides);
+            buildDir, tempDir, compileTimeArguments, environmentOverrides);
     if (!configuration.skipCompilation) {
       commands.addAll(compilationArtifact.commands);
     }
@@ -921,11 +918,7 @@
 
     return commands
       ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
-          this,
-          CommandBuilder.instance,
-          compilationArtifact,
-          runtimeArguments,
-          environmentOverrides));
+          this, compilationArtifact, runtimeArguments, environmentOverrides));
   }
 
   CreateTest makeTestCaseCreator(Map<String, dynamic> optionsFromFile) {
@@ -1208,15 +1201,11 @@
           dartFlags.addAll(vmOptions);
         }
 
-        commandSet.add(CommandBuilder.instance.getContentShellCommand(
-            contentShellFilename,
-            fullHtmlPath,
-            contentShellOptions,
-            dartFlags,
-            environmentOverrides));
+        commandSet.add(Command.contentShell(contentShellFilename, fullHtmlPath,
+            contentShellOptions, dartFlags, environmentOverrides));
       } else {
-        commandSet.add(CommandBuilder.instance.getBrowserTestCommand(
-            fullHtmlPath, configuration, !isNegative(info)));
+        commandSet.add(Command.browserTest(fullHtmlPath, configuration,
+            retry: !isNegative(info)));
       }
 
       // Create BrowserTestCase and queue it.
@@ -1295,8 +1284,9 @@
 
     var htmlPath = _createUrlPathFromFile(new Path(htmlFile.toFilePath()));
     var fullHtmlPath = _getUriForBrowserTest(htmlPath, null).toString();
-    commands.add(CommandBuilder.instance.getBrowserHtmlTestCommand(
-        fullHtmlPath, configuration, info.expectedMessages, !isNegative(info)));
+    commands.add(Command.browserHtmlTest(
+        fullHtmlPath, configuration, info.expectedMessages,
+        retry: !isNegative(info)));
     var testDisplayName = '$suiteName/$testName';
     var testCase = new BrowserTestCase(testDisplayName, commands, configuration,
         expectations, info, isNegative(info), fullHtmlPath);
@@ -1325,14 +1315,8 @@
     var options = optionsFromFile['sharedOptions'] as List<String>;
     if (options != null) args.addAll(options);
 
-    return CommandBuilder.instance.getCompilationCommand(
-        Compiler.dart2js.name,
-        outputFile,
-        !useSdk,
-        dart2JsBootstrapDependencies,
-        compilerPath,
-        args,
-        environmentOverrides);
+    return Command.compilation(Compiler.dart2js.name, outputFile, !useSdk,
+        dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides);
   }
 
   /** Helper to create a Polymer deploy command for a single HTML file. */
@@ -1352,7 +1336,7 @@
       ..add('.svn');
     if (configuration.isCsp) args.add('--csp');
 
-    return CommandBuilder.instance.getProcessCommand(
+    return Command.process(
         'polymer_deploy', dartVmBinaryFileName, args, environmentOverrides);
   }
 
@@ -1736,8 +1720,7 @@
       var fullPath = _createUrlPathFromFile(customHtmlPath);
 
       var commands = [
-        CommandBuilder.instance
-            .getBrowserTestCommand(fullPath, configuration, !isNegative(info))
+        Command.browserTest(fullPath, configuration, retry: !isNegative(info))
       ];
       var testDisplayName = '$suiteName/$testName';
       enqueueNewTestCase(new BrowserTestCase(