Version 2.7.0-dev.1.0

Merge commit 'ffbd2eb7eebf569b8aefd970cf59851aaf2869a3' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b3736f..6707c5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,8 +41,83 @@
 
 ### Language
 
-*   **[IN PREVIEW]** [Static extension members][]: A new language feature allowing
-    specially declared static functions to be invoked
+* **Breaking Change**: [Static extension members][] are accessible when
+imported with a prefix (issue [671][]). In the extension method **preview**
+launch, importing a library with a prefix hid all extension members in
+addition to hiding the extension name, thereby making them inaccessible
+in the importing library except via the explicit override syntax. Based
+on user feedback, we have changed this to make extensions methods accessible
+even when imported with a prefix.
+
+    ```dart
+      // "thing.dart"
+      class Thing {
+      }
+      extension Show on Thing {
+        void show() {
+          print("This is a thing");
+        }
+     }
+     // "client.dart"
+     import "thing.dart" as p;
+     void test() {
+       p.Thing().show(); // Previously an error, now resolves to Show.show
+     }
+    ```
+
+[Static extension members]: https://github.com/dart-lang/language/blob/master/accepted/2.6/static-extension-members/feature-specification.md
+[671]: https://github.com/dart-lang/language/issues/671
+
+### Core libraries
+
+#### `dart:io`
+
+* **Breaking change**: Added `IOOverrides.serverSocketBind` to aid in writing
+  tests that wish to mock `ServerSocket.bind`.
+
+### Dart VM
+
+* New fields added to existing instances by a reload will now be initialized
+lazily, as if the field was a late field. This makes the initialization order
+program-defined, whereas previously it was undefined.
+
+### Tools
+
+#### Linter
+
+The Linter was updated to `0.1.103`, which includes:
+
+* updates to `prefer_relative_imports` to use a faster and more robust way to check for self-package references
+* updates to our approach to checking for `lib` dir contents (speeding up `avoid_renaming_method_parameters` and
+  making `prefer_relative_imports` and `public_member_api_docs` amenable to internal package formats -- w/o pubspecs)
+
+#### Pub
+
+* `pub get` generates [`.dart_tools/package_config.json`](https://github.com/dart-lang/language/blob/62c036cc41b10fb543102d2f73ee132d1e2b2a0e/accepted/future-releases/language-versioning/package-config-file-v2.md)
+  in addition to `.packages` to support language versioning.
+
+* `pub publish` now warns about the old flutter plugin registration format.
+
+* `pub publish` now warns about the `author` field in pubspec.yaml being.
+  obsolete.
+
+* Show a proper error message when `git` is not installed.
+
+## 2.6.1 - 2019-11-11
+
+This is a patch release that reduces dart2js memory usage (issue [27883][]),
+improves stability on arm64 (issue [39090][]) and updates the Dart FFI
+documentation.
+
+[27883]: https://github.com/dart-lang/sdk/issues/27883
+[39090]: https://github.com/dart-lang/sdk/issues/39090
+
+## 2.6.0 - 2019-11-05
+
+### Language
+
+*   **[IN PREVIEW]** [Static extension members][]: A new language feature
+    allowing specially declared static functions to be invoked
     like instance members on expressions of appropriate static types
     is available in preview.
 
@@ -133,7 +208,7 @@
     for accessing the value in native memory and `[]` and `[]=` for indexed access.
     The method `asExternalTypedData` has been replaced with `asTypedList` extension
     methods. And finally, `Structs` do no longer have a type argument and are
-    accessed the extension member `.ref` on `Pointer`.
+    accessed using the extension member `.ref` on `Pointer`.
     These changes makes the code using `dart:ffi` much more concise.
 *   **Breaking change**: The memory management has been removed (`Pointer.allocate`
     and `Pointer.free`). Instead, memory management is available in
@@ -142,7 +217,7 @@
     instead.
 *   Faster memory load and stores.
 *   The dartanalyzer (commandline and IDEs) now reports `dart:ffi` static errors.
-*   Callbacks are now supported in AOT (ahead-of-time) compiled code.
+*   Callbacks are now supported in AOT (ahead-of-time) compiled code.
 
 ### Dart for the Web
 
diff --git a/DEPS b/DEPS
index 7614351..4c62d63 100644
--- a/DEPS
+++ b/DEPS
@@ -54,7 +54,7 @@
   "gperftools_revision": "e9ab4c53041ac62feefbbb076d326e9a77dd1567",
 
   # Revisions of /third_party/* dependencies.
-  "args_tag": "1.5.0",
+  "args_tag": "1.5.2",
   "async_tag": "2.0.8",
   "bazel_worker_tag": "v0.1.22",
   "benchmark_harness_tag": "81641290dea44c34138a109a37e215482f405f81",
@@ -84,8 +84,7 @@
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
   "dart_style_tag": "1.3.2",  # Please see the note above before updating.
 
-  "args_tag" : "1.5.2",
-  "dartdoc_tag" : "v0.29.0",
+  "dartdoc_tag" : "v0.29.1",
   "ffi_tag": "ea88d71b043ee14b268c3aedff14e9eb32e20959",
   "fixnum_tag": "0.10.9",
   "glob_tag": "1.1.7",
@@ -118,7 +117,7 @@
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
   "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
-  "pub_rev": "80ac76400ff58fde3c5a335d860d196c3febe837",
+  "pub_rev": "d15067931a6b671a1c9dcc98b5923347676269cf",
   "pub_semver_tag": "1.4.2",
   "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
@@ -176,14 +175,14 @@
   Var("dart_root") + "/tools/sdks": {
       "packages": [{
           "package": "dart/dart-sdk/${{platform}}",
-          "version": "version:2.6.0-dev.4.0",
+          "version": "version:2.6.0",
       }],
       "dep_type": "cipd",
   },
   Var("dart_root") + "/third_party/d8": {
       "packages": [{
           "package": "dart/d8",
-          "version": "version:7.5.149",
+          "version": "version:7.8.279",
       }],
       "dep_type": "cipd",
   },
@@ -427,7 +426,7 @@
     "packages": [
       {
         "package": "dart/language_model",
-        "version": "9fJQZ0TrnAGQKrEtuL3-AXbUfPzYxqpN_OBHr9P4hE4C",
+        "version": "lIRt14qoA1Cocb8j3yw_Fx5cfYou2ddam6ArBm4AI6QC",
       }
     ],
     "dep_type": "cipd",
@@ -468,7 +467,7 @@
     "packages": [
       {
         "package": "dart/cfe/dart2js_dills",
-        "version": "binary_version:36",
+        "version": "binary_version:29_36",
       }
     ],
     "dep_type": "cipd",
diff --git a/benchmarks/IsolateJson/dart/IsolateJson.dart b/benchmarks/IsolateJson/dart/IsolateJson.dart
new file mode 100644
index 0000000..bdc7988
--- /dev/null
+++ b/benchmarks/IsolateJson/dart/IsolateJson.dart
@@ -0,0 +1,131 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart' show BenchmarkBase;
+import 'package:meta/meta.dart';
+
+class JsonDecodingBenchmark {
+  JsonDecodingBenchmark(this.name,
+      {@required this.sample, @required this.numTasks});
+
+  Future<void> report() async {
+    final stopwatch = Stopwatch()..start();
+    final decodedFutures = <Future>[];
+    for (int i = 0; i < numTasks; i++) {
+      decodedFutures.add(decodeJson(sample));
+    }
+    await Future.wait(decodedFutures);
+
+    print("$name(RunTime): ${stopwatch.elapsedMicroseconds} us.");
+  }
+
+  final String name;
+  final Uint8List sample;
+  final int numTasks;
+}
+
+Uint8List createSampleJson(final size) {
+  final list = List.generate(size, (i) => i);
+  final map = <dynamic, dynamic>{};
+  for (int i = 0; i < size; i++) {
+    map['$i'] = list;
+  }
+  return utf8.encode(json.encode(map));
+}
+
+class JsonDecodeRequest {
+  final SendPort sendPort;
+  final Uint8List encodedJson;
+  const JsonDecodeRequest(this.sendPort, this.encodedJson);
+}
+
+Future<Map> decodeJson(Uint8List encodedJson) async {
+  final port = ReceivePort();
+  final inbox = StreamIterator<dynamic>(port);
+  final workerExitedPort = ReceivePort();
+  await Isolate.spawn(
+      jsonDecodingIsolate, JsonDecodeRequest(port.sendPort, encodedJson),
+      onExit: workerExitedPort.sendPort);
+  await inbox.moveNext();
+  final decodedJson = inbox.current;
+  await workerExitedPort.first;
+  port.close();
+  return decodedJson;
+}
+
+Future<void> jsonDecodingIsolate(JsonDecodeRequest request) async {
+  request.sendPort.send(json.decode(utf8.decode(request.encodedJson)));
+}
+
+class SyncJsonDecodingBenchmark extends BenchmarkBase {
+  SyncJsonDecodingBenchmark(String name,
+      {@required this.sample, @required this.iterations})
+      : super(name);
+
+  @override
+  void run() {
+    int l = 0;
+    for (int i = 0; i < iterations; i++) {
+      final Map map = json.decode(utf8.decode(sample));
+      l += map.length;
+    }
+    assert(l > 0);
+  }
+
+  final Uint8List sample;
+  final int iterations;
+}
+
+class BenchmarkConfig {
+  BenchmarkConfig(this.suffix, this.sample);
+
+  final String suffix;
+  final Uint8List sample;
+}
+
+Future<void> main() async {
+  final jsonString =
+      File('benchmarks/IsolateJson/dart/sample.json').readAsStringSync();
+  final json250KB = utf8.encode(jsonString); // 294356 bytes
+  final decoded = json.decode(utf8.decode(json250KB));
+  final decoded1MB = <dynamic, dynamic>{
+    "1": decoded["1"],
+    "2": decoded["1"],
+    "3": decoded["1"],
+    "4": decoded["1"],
+  };
+  final json1MB = utf8.encode(json.encode(decoded1MB)); // 1177397 bytes
+  decoded["1"] = (decoded["1"] as List).sublist(0, 200);
+  final json100KB = utf8.encode(json.encode(decoded)); // 104685 bytes
+  decoded["1"] = (decoded["1"] as List).sublist(0, 100);
+  final json50KB = utf8.encode(json.encode(decoded)); // 51760 bytes
+
+  final configs = <BenchmarkConfig>[
+    BenchmarkConfig("50KB", json50KB),
+    BenchmarkConfig("100KB", json100KB),
+    BenchmarkConfig("250KB", json250KB),
+    BenchmarkConfig("1MB", json1MB),
+  ];
+
+  for (BenchmarkConfig config in configs) {
+    for (final iterations in <int>[1, 4]) {
+      await JsonDecodingBenchmark(
+              "IsolateJson.Decode${config.suffix}x$iterations",
+              sample: config.sample,
+              numTasks: iterations)
+          .report();
+      SyncJsonDecodingBenchmark(
+              "IsolateJson.SyncDecode${config.suffix}x$iterations",
+              sample: config.sample,
+              iterations: iterations)
+          .report();
+    }
+  }
+}
diff --git a/benchmarks/IsolateJson/dart/sample.json b/benchmarks/IsolateJson/dart/sample.json
new file mode 100644
index 0000000..8d3888c
--- /dev/null
+++ b/benchmarks/IsolateJson/dart/sample.json
@@ -0,0 +1 @@
+{"1":[{"1":{"1":"https://images.pexels.com/photos/733416/pexels-photo-733416.jpeg?cs=srgb&dl=animal-dog-pet-733416.jpg&fm=jpg","3":4608,"4":3456},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQw3eEZzgfnJWrfcDcwVIMy_Y1V5XoFESHax7oIlPzSQxJ-9s4o4A","3":200,"4":149},"3":{"1":"Pexels","2":"https://www.pexels.com/search/dog/","3":"Dog images · Pexels · Free Stock Photos","4":"You can find photos of bulldogs, retrievers, beagles and of course puppies.","10":"SguaQKdRqRdlsC"},"5":{"1":"lLLVuSKOKaBoUui"}},{"1":{"1":"http://www.petmd.com/sites/default/files/Dogs-and-vomiting.jpg","3":590,"4":428},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTC2-E8GsGxryTokj2Djx33PcWpZAMYjiQRoIDS31Ux-ENHEWH","3":200,"4":144},"3":{"1":"PetMD","2":"https://www.petmd.com/dog/conditions/digestive/different-types-dog-vomit-and-what-they-indicate","3":"Different Types of Dog Vomit, and What They Indicate | petMD","4":"Different Types of Dog Vomit, and What They Indicate","10":"rgVRJtKOVXpdLe"},"5":{"1":"xUEbAsVXOsAMkMO"}},{"1":{"1":"https://images.pexels.com/photos/356378/pexels-photo-356378.jpeg?auto=compress&cs=tinysrgb&h=350","3":525,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcToY88EZcEUA-UgqGCQVzuvR-8YxpK8RzNKMdd4KyeleCu35qyw","3":200,"4":133},"3":{"1":"Pexels","2":"https://www.pexels.com/search/dog/","3":"Dog images · Pexels · Free Stock Photos","4":"Free stock photo of animal, dog, pet, cute","10":"WFheUvWgXjwXtD"},"5":{"1":"prHPnfIfXBtFhXY"}},{"1":{"1":"https://static.boredpanda.com/blog/wp-content/uploads/2016/09/dogs-catching-treats-fotos-frei-schnauze-christian-vieler-66-57e8d9d0ec7ee__880.jpg","3":880,"4":660},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTr_sMZE8eDNndt5ttEAqacKcA-7IgQ0naBGd3A9XVG1GCIWdjj","3":200,"4":149},"3":{"1":"Bored Panda","2":"https://www.boredpanda.com/dogs-catching-treats-fotos-frei-schnauze-christian-vieler/","3":"Hilarious Expressions Of Dogs Trying To Catch Treats In Mid ...","4":"Dog Catching Treat","10":"hCBhQWwnqCrhel"},"5":{"1":"QalunmBgihmCcmj"}},{"1":{"1":"https://i.ytimg.com/vi/GruPNmCb-fQ/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSYVG0JeW7ISz-4OcZ0CiUb0AE3cni6IzuGPYVIbJoAccAM2Umx","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=GruPNmCb-fQ","3":"dogs pictures of dogs","4":"","10":"MJJqMJlsVluLXc"},"5":{"1":"iMAXrPRULaMbSKm"},"7":{"1":{"11":{"1":"dogs pictures of dogs","2":"dogs barking, dogs 101, dogs mating, dogs howling, dogs who fail at being  dogs, dogs and babies, dogs funny, dogs talking, dogs annoying cats with  their frie...","3":"0:55","4":"149947","5":"1439251200000","6":"lifestyle","7":"505","8":"16"}}}},{"1":{"1":"https://i2-prod.mirror.co.uk/incoming/article9769854.ece/ALTERNATES/s615/PROD-Mixed-breed-lab-cross-8-week-old-puppy-in-farm-yard-near-Cochrane-AlbertajpgED.jpg","3":615,"4":409},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqOXnBZYPgzFX8sgcA1iTrixxTbt15sDmyqN1Sy07IXB4acmbM","3":200,"4":133},"3":{"1":"Irish Mirror","2":"https://www.irishmirror.ie/news/world-news/facts-secret-life-of-dogs-9769971","3":"20 amazing dog facts as you watch Secret Life of Dogs series ...","4":"Mixed breed (lab cross) 8-week old puppy in farm","10":"pRFceHyATKdlWr"},"5":{"1":"pNVdrhPrtToqnQq"}},{"1":{"1":"https://images.pexels.com/photos/36477/dogs-batons-play-bite.jpg?auto=compress&cs=tinysrgb&h=350","3":712,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrHgf1GKr5sPjRAytMGs5xrzQ4akViEXH5sPlgs3wGKv4IiFVY9A","3":200,"4":98},"3":{"1":"Pexels","2":"https://www.pexels.com/search/dogs/","3":"1000+ Great Dogs Photos · Pexels · Free Stock Photos","4":"White Short Coat Dog","10":"kVfxtLWgXLSNXO"},"5":{"1":"IArTKYCDEkFNdQJ"}},{"1":{"1":"https://s.abcnews.com/images/US/160825_vod_orig_historyofdogs_16x9_992.jpg","3":992,"4":558},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSiS1BpxgmU8dZtUcZM9ZhCLH0MVGioF9jOuVeSUeKJorZqblc6Zw","3":200,"4":112},"3":{"1":"ABC News - Go.com","2":"https://abcnews.go.com/Lifestyle/history-dogs-pets/story?id=41671149","3":"The History of Dogs as Pets - ABC News","4":"buffering","10":"qPlCWSIdyKBbrM"},"5":{"1":"fXDVNQwDhIpuOwD"}},{"1":{"1":"https://media.mnn.com/assets/images/2013/10/Corgeek.jpg","3":900,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtIZicNvg3fENA9X_vbniL40lcfwe7ioZJ6YulS0GmFe6GfGXI1A","3":200,"4":133},"3":{"1":"Mother Nature Network","2":"https://www.mnn.com/family/pets/stories/31-photos-of-dogs-wearing-glasses","3":"29 photos of dogs wearing glasses | MNN - Mother Nature Network","4":"Corgeek wearing thick-rimmed glasses","10":"lSHpPWQpaPISjU"},"5":{"1":"GYKvLpLqDGPFJXg"}},{"1":{"1":"https://static.scientificamerican.com/sciam/cache/file/B7943D3A-35D3-4D27-906280F095578EC2.jpg","3":320,"4":320},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSNCsn1AuroUrSnWm7f1Wykc9ROorMxkSXPHY-AVOOgV6L-0N0T","3":200,"4":200},"3":{"1":"Scientific American","2":"https://www.scientificamerican.com/article/the-origin-of-dogs/","3":"The Origin of Dogs - Scientific American","4":"","10":"fxsACuFxGdCjOi"},"5":{"1":"hugEXJRCUBEtjsd"}},{"1":{"1":"https://cdn.psychologytoday.com/sites/default/files/styles/image-article_inline_full/public/field_blog_entry_images/2018-03/sandeephanda.jpg?itok=iXHqSFgZ","3":639,"4":430},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFEOQ3smXMSwFXqUvEr1vJ5x21ciMWO0gAiGNpRCvg5rhwxDkD","3":200,"4":134},"3":{"1":"Psychology Today","2":"https://www.psychologytoday.com/us/blog/canine-corner/201803/are-there-some-truths-behind-isle-dogs","3":"Are There Some Truths Behind 'Isle of Dogs'? | Psychology Today","4":"SandeepHanda photo - Creative Commons License CC0","10":"bagMKHtgcbRaDB"},"5":{"1":"modfWdcGLNxQAyJ"}},{"1":{"1":"https://www.healthline.com/hlcmsresource/images/Dog-Breeds-Health-Problems/3180-Pug_green_grass-732x549-thumbnail.jpg","3":732,"4":549},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9fyeRFN6y6AUMwe_0vQvP7mCIf5iurFZrTAcei1CQlN2gfwqrig","3":200,"4":149},"3":{"1":"Healthline","2":"https://www.healthline.com/health/dog-breeds-and-health-issues","3":"12 Common Dog Breeds and Their Health Issues","4":"","10":"JhFfVvGodohGEK"},"5":{"1":"oeXrDfFoklVmGtq"}},{"1":{"1":"https://static.boredpanda.com/blog/wp-content/uploads/2016/09/dogs-catching-treats-fotos-frei-schnauze-christian-vieler-4-57e8d08f5fc8f__880.jpg","3":880,"4":1173},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHMV0D4vwUH9TK5xMCanXYzWgaKAefyVB33Ehg06OK31Nwqm9g","3":149,"4":200},"3":{"1":"Bored Panda","2":"https://www.boredpanda.com/dogs-catching-treats-fotos-frei-schnauze-christian-vieler/","3":"Hilarious Expressions Of Dogs Trying To Catch Treats In Mid ...","4":"Dog Catching Treat","10":"FyEKtGxRPjfnKO"},"5":{"1":"hDUbUkdaJjjbuqP"}},{"1":{"1":"http://www.dogbreedslist.info/uploads/allimg/dog-pictures/Beagle-1.jpg","3":400,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQox7_4om515DH4IbD8Prr6Sbnq30OFIJjaqMeHIjlsLy7nvUfX5w","3":200,"4":149},"3":{"1":"Dog Breeds List","2":"http://www.dogbreedslist.info/all-dog-breeds/","3":"All Dog Breeds, All Dog Types, All Dog List Names & Pictures","4":"Beagle","10":"bfNEoguPVtbtLd"},"5":{"1":"CnXysoILLwWyCtD"}},{"1":{"1":"https://media1.fdncms.com/stranger/imager/u/original/25231124/dog-stock-photos-9.jpg","3":700,"4":508},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQIvUyRcVTeIRW3TJQfwIJAZhoPB4cr_OKWIc0zVIZoEv63MkmHYA","3":200,"4":144},"3":{"1":"The Stranger","2":"https://www.thestranger.com/slog/2017/06/21/25230993/drunk-man-killed-by-a-pack-of-dogs","3":"Drunk Man Eaten Alive By a Pack of Dogs - Slog - The Stranger","4":"This is a free stock photo of a dog. If you want to see the","10":"IgSvbNIltWEEwd"},"5":{"1":"cYgCBcJcaUhVfax"}},{"1":{"1":"https://i.dailymail.co.uk/i/pix/2017/04/24/16/3F907F8A00000578-4440672-image-m-84_1493049047546.jpg","3":470,"4":518},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSncPu-uh8ZvUmH5pHt44DzkScX-iiFVHHSJPZXJpob0NJKtJ9ylg","3":181,"4":200},"3":{"1":"Daily Mail","2":"https://www.dailymail.co.uk/sciencetech/article-4440672/Map-shows-breeds-dogs-evolved-globe.html","3":"Map shows how breeds of dogs evolved around the globe | Daily ...","4":"The researchers have spent year sequencing the genomes of dogs, including  golden retrievers (pictured","10":"IexeHMwHeSSRNj"},"5":{"1":"pAbGXlIdKaoFpeq"}},{"1":{"1":"https://www.telegraph.co.uk/content/dam/Pets/spark/royal-canin/rc-7_dogs.jpg?imwidth=450","3":480,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNFuT_iGr6VUtsCWNJPagVAQbwr38Hf60DH71_60-P6Q43IccrbA","3":200,"4":124},"3":{"1":"The Telegraph","2":"https://www.telegraph.co.uk/pets/essentials/seven-types-of-dog/","3":"The 7 types of dog","4":"7 types of dog","10":"NMEuhtiMRpwOpI"},"5":{"1":"OfowkXWGdhgIatC"}},{"1":{"1":"https://amp.businessinsider.com/images/5ab514477708e97acc0f0cc9-750-562.jpg","3":750,"4":562},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDknn1s15Hxsl9Ia0VWFreeM2JQ3j_1quuxN2gct1k2UNs-mKjDg","3":200,"4":149},"3":{"1":"Business Insider","2":"https://www.businessinsider.com/isle-of-dogs-movie-i-love-dogs-tweets-reactions-2018-3","3":"Isle of Dogs' is pronounced 'I love dogs' and people are ...","4":"Isle of Dogs movie Wes Anderson Fox Searchlight Pictures","10":"iXypfDeEmRoQat"},"5":{"1":"HTpoQgGnRUeWIXc"}},{"1":{"1":"https://images.agoramedia.com/everydayhealth/gcms/Best-and-Worst-Dog-Breeds-for-Allergies-06-1440x810.jpg?width=730","3":730,"4":410},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_xRgFtXHo-nTTWZhLeZWReUdLNv2kLjUdVqneQsYHTG1Ql83_","3":200,"4":112},"3":{"1":"Everyday Health","2":"https://www.everydayhealth.com/allergy-pictures/best-and-worst-dog-breeds-for-people-with-allergies.aspx","3":"Best and Worst Dog Breeds for People With Allergies ...","4":"Best: The Bichon Frise and Labradoodle Are Great Hypoallergenic Dogs","10":"ehAAXIHECfjrGJ"},"5":{"1":"wdVCorFRYSIGGKr"}},{"1":{"1":"http://www.insidedogsworld.com/wp-content/uploads/2016/03/Dog-Pictures.jpg","3":1600,"4":1092},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSwCLO0IhU0gJtCtO7z_oe2TqADEtc_s57hjyxba-omx7Q524EF","3":200,"4":136},"3":{"1":"Inside Dogs World","2":"http://www.insidedogsworld.com/doggy-dna-learn-how-to-determine-your-dogs-breed/","3":"Doggy DNA - Learn How to Determine Your Dog's Breed - Inside ...","4":"Doggy DNA – Learn How to Determine Your Dog's Breed","10":"uuCtKfTFMKWRRC"},"5":{"1":"EQBsTFvYFYLhfah"}},{"1":{"1":"https://www.planwallpaper.com/static/images/3e9c5ad3af07e573b0e74bdb0a1dce3e.jpg","3":1600,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkrUyVlOK9hkIWgIDkh4os23NxTTL925HmkGHa0KhalcOy29at","3":200,"4":149},"3":{"1":"planwallpaper.com","2":"https://www.planwallpaper.com/pictures-dogs","3":"Nice pictures of different types of dogs including, Labrador ...","4":"Pictures of Dogs","10":"mklFCiXFYyFYkP"},"5":{"1":"FlnaWswreHfokNn"}},{"1":{"1":"https://pbs.twimg.com/profile_images/962016398657536000/ygoklDXh_400x400.jpg","3":400,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR45pwTGoDqneOjTgTvSA6rhDEkmhprQi08wkhcR3qIW3vLNSZuaQ","3":200,"4":200},"3":{"1":"Twitter","2":"https://twitter.com/isleofdogsmovie","3":"Isle of Dogs (@isleofdogsmovie) | Twitter","4":"Isle of Dogs","10":"COMSuLFTKJfFRc"},"5":{"1":"NXbmwUJVPlrVJDq"}},{"1":{"1":"https://www.telegraph.co.uk/content/dam/news/2017/10/16/alamy_trans_NvBQzQNjv4Bq_yHCl97T-pmmS890d_-lMLlnpmZnLOvn-dZ00jolDcU.png?imwidth=450","3":480,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSpabtx60ZO8jN9PviVFQHSNuHQE4Hohoo2nEZG0wDm7WRLYtH2cw","3":200,"4":124},"3":{"1":"The Telegraph","2":"https://www.telegraph.co.uk/news/2017/10/16/california-first-us-state-bans-sale-dogs-puppy-mills/","3":"California to be first US state that bans sale of dogs from ...","4":"Follow the author of this article","10":"AbJpjbQJvFhEOp"},"5":{"1":"aLDaXCkraGQRXJj"}},{"1":{"1":"https://images.pexels.com/photos/850602/pexels-photo-850602.jpeg?auto=compress&cs=tinysrgb&h=350","3":525,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR13B6xa4L-1BX-lW6akzUcZGSagbZX-aZpI4ynZ8H8EBufjEgk","3":200,"4":133},"3":{"1":"Pexels","2":"https://www.pexels.com/search/dogs/","3":"1000+ Great Dogs Photos · Pexels · Free Stock Photos","4":"Photography of Three Dogs Looking Up","10":"bCleKSaPgwaqsp"},"5":{"1":"HqvqIYprPdbySFd"}},{"1":{"1":"https://g77v3827gg2notadhhw9pew7-wpengine.netdna-ssl.com/wp-content/uploads/2017/02/side-effects-of-dog-seizures_canna-pet-e1488305138683-1024x675.jpg","3":1024,"4":675},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcROkfK9Akkc6FPWW6QbNvnIZIvYc2jh6J-FiFW6i6cVMFWGs6CS","3":200,"4":131},"3":{"1":"Canna-Pet","2":"https://canna-pet.com/side-effects-dog-seizures/","3":"Side Effects of Dog Seizures | Canna-Pet","4":"When your dog suffers from a seizure, things can get scary. Unless you have  prior experience dealing ...","10":"CuWqYDalAItEAC"},"5":{"1":"ShraFjJEYLkJTuM"}},{"1":{"1":"https://gfnc1kn6pi-flywheel.netdna-ssl.com/wp-content/uploads/2016/12/beagle.jpg","3":2734,"4":1503},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3tZYFHIKJ_a_DdRQ7iwKDgbdovkQxiOGePEGb4LO0jA1ZiFL9Yg","3":200,"4":109},"3":{"1":"The Happy Puppy Site","2":"https://thehappypuppysite.com/dog-breed-groups/","3":"Different Types Of Dogs: The Dog Breed Groups Explained","4":"","10":"PjvrqgbFNJbdVk"},"5":{"1":"yatyBgWoyTxLMtP"}},{"1":{"1":"http://images6.fanpop.com/image/photos/33200000/cute-puppy-dogs-33237869-1024-768.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRo2A34saU-H_gKu_2IRv3s1V9iDvCSj8GCu5UPEglrHBh4Kp8qEw","3":200,"4":149},"3":{"1":"Fanpop","2":"http://www.fanpop.com/clubs/dogs/images/33237869/title/cute-puppy-photo","3":"Dogs images cute puppy HD wallpaper and background photos ...","4":"Dogs images cute puppy HD wallpaper and background photos","10":"egPjrYYHpdvPme"},"5":{"1":"EEICyeYkCvYwXLO"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/dog-how-to-select-your-new-best-friend-thinkstock99062463.jpg","3":2048,"4":1536},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTRIvpifkq9hrRGj8H8kia131DoNNU69BJD13Vbh0RS1Fyc3eir","3":200,"4":149},"3":{"1":"Petfinder","2":"https://www.petfinder.com/pet-adoption/dog-adoption/type-dog-adoption/","3":"What Kind of Dog is Right for You? | Petfinder","4":"How to Select Your New Best Friend","10":"hvnHFcgyhBEWKo"},"5":{"1":"XvtJWtvCTtTUGUE"}},{"1":{"1":"https://phz8.petinsurance.com/-/media/all-phz-images/2016-images-850/painful_condition_dogs850.jpg","3":850,"4":477},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSUaqtvYYYQKvrfvutDGGaiNT8vb-nmbFhs4svZisNCJutwkT7s","3":200,"4":112},"3":{"1":"Pet HealthZone - Nationwide Pet Insurance","2":"https://phz8.petinsurance.com/ownership-adoption/pet-ownership/pet-behavior/secret-language-of-dogs","3":"Secret Language of Dogs","4":"5 of the Most Painful Conditions for Dogs Infographic","10":"WvTABueqaEenmO"},"5":{"1":"RnDslGiNkbYImvT"}},{"1":{"1":"https://boygeniusreport.files.wordpress.com/2016/11/puppy-dog.jpg?quality=98&strip=all&w=782","3":782,"4":529},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtCG9yitxng6vXipfsQ9Ix4kKetdMjZqC6SEsLsaWiUXpvn2DoWw","3":200,"4":135},"3":{"1":"BGR.com","2":"https://bgr.com/2018/04/30/dog-food-recall-illness-2018-australia/","3":"Pet food maker whose food sickened dozens of dogs will now ...","4":"dog food recall","10":"CnJIxRQSgtHwrK"},"5":{"1":"efIduFqGkIJUaKO"}},{"1":{"1":"https://s3.amazonaws.com/cdn-origin-etr.akc.org/wp-content/uploads/2017/11/14144545/Afghan-Hound.981631440-400x267.jpg","3":400,"4":267},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEOtJxduRSati0Da8xMEWEu-XkITbsLG9p7HRWqPdom6wq7ZpSbQ","3":200,"4":133},"3":{"1":"American Kennel Club","2":"https://www.akc.org/dog-breeds/largest-dog-breeds/","3":"Largest Dog Breeds – American Kennel Club","4":"Afghan Hound","10":"fYEbncuQaxwNql"},"5":{"1":"YAgwGCfdvHlIfNe"}},{"1":{"1":"http://www.termcoord.eu/wp-content/uploads/2014/06/Dog1-300x300.jpg","3":300,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyYEIkXsOSEDtelosTsFUwgOvndtVRU05csD-Xls1ih23V6xkIQg","3":200,"4":200},"3":{"1":"TermCoord","2":"http://termcoord.eu/2014/06/language-dogs/","3":"The Language of Dogs - Terminology Coordination Unit [DGTRAD ...","4":"Whether you're a cat or dog person, or even a… turtle person, knowing what  your pet is trying to say ...","10":"tqEScIlTpwyTGg"},"5":{"1":"IltOuDYoEvnfdNp"}},{"1":{"1":"https://2.bp.blogspot.com/-fZNgK0_TgOc/WK82Vp7SKoI/AAAAAAAAClQ/Wp-ptafLniU4Qrq21v9_-GceX1wScZklgCLcB/s1600/dog-puppy-info.jpg","3":736,"4":1128},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTef30plTwjVco7_6sYT-1MGDCo13ArTTkrRDKgdS5RY7nHabQ9ZA","3":130,"4":200},"3":{"1":"Companion Animal Psychology","2":"https://www.companionanimalpsychology.com/p/all-about-dogs.html","3":"Companion Animal Psychology: All About Dogs","4":"Essential info for owners of dogs, like this cute mixed-breed puppy","10":"tCihFexyfCGTyK"},"5":{"1":"DXPnPecpPDdVSyL"}},{"1":{"1":"http://discovermagazine.com/~/media/Images/Issues/2016/December/DSC-A1216_01.jpg","3":1200,"4":1054},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcToOmuh2CoCK5KII7an_lwwd9QvDUXWFv-o5C3ZtTpIMkkxeIFMkg","3":200,"4":175},"3":{"1":"Discover Magazine","2":"http://discovermagazine.com/2016/dec/the-origins-of-dogs","3":"The Origins of Dogs | DiscoverMagazine.com","4":"William Zuback/Discover","10":"SYCeycfBKoolRt"},"5":{"1":"qMPWqKXVSSnvyAS"}},{"1":{"1":"https://www.petmd.com/sites/default/files/excess-protein-urine-dogs.jpg","3":590,"4":428},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXDZ8HeQFcHunFGNZn9x_lNaMnT4RNp6musZ8E9uWkt2E8L97HCA","3":200,"4":144},"3":{"1":"PetMD","2":"https://www.petmd.com/dog/conditions/urinary/c_multi_proteinuria","3":"Excess Protein in the Urine of Dogs | petMD","4":"Excess Protein in the Urine of Dogs","10":"FYHbeBBukLntuP"},"5":{"1":"CyfaFOmUMgNnQab"}},{"1":{"1":"https://timedotcom.files.wordpress.com/2017/04/world-of-dogs-06.jpg","3":2560,"4":1828},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQC_HWVgXvr-oaEoiPhQCqlakG4CjOJhOFpO0iz1offaVxC8saPTA","3":200,"4":142},"3":{"1":"Time","2":"http://time.com/4775436/how-smart-is-a-dog-really/","3":"A Dog's Brain: Inside the Complex Canine Mind | Time","4":"Isabella, a 14 year-old Pomeranian photographed in New York, NY on April","10":"efLLIMPDyVtVHU"},"5":{"1":"muCEStXmFieFAXV"}},{"1":{"1":"https://www.indiewire.com/wp-content/uploads/2018/02/05-isle-of-dogs-1-w710-h473.jpg?w=710","3":710,"4":473},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZ5l8kHahaV_4Y9pHXud4pFwy4dG1DSUy5Pq5L_BBUcKCRyvo6og","3":200,"4":133},"3":{"1":"IndieWire","2":"https://www.indiewire.com/2018/02/wes-anderson-isle-of-dogs-soundtrack-kurosawa-seven-samurai-1201933682/","3":"Wes Anderson's 'Isle of Dogs' Official Soundtrack Revealed ...","4":"\"Isle of Dogs\"","10":"KIxyaUxLUheWqo"},"5":{"1":"cmMlrpWYBWodKUt"}},{"1":{"1":"https://doggonesafe.com/Resources/Pictures/close%20up%20on%20two%20dogs%20mouths.jpg","3":1600,"4":1066},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSvSC5m7zvD0WLFNVWXbdtql8yUsa_QODDOSoLBxzmueG463wVm","3":200,"4":133},"3":{"1":"Doggone Safe","2":"https://doggonesafe.com/event-2017914","3":"Doggone Safe - Learn How To Effectively Manage Groups of Dogs ...","4":"Learn How To Effectively & Safely Manage Groups of Dogs In an Off Leash  Environment","10":"bMtNLBtEdWoimM"},"5":{"1":"kIroRbkLSsunErY"}},{"1":{"1":"https://ksassets.timeincuk.net/wp/uploads/sites/55/2018/03/Isle-Of-Dogs-Wes-Anderson-920x584.jpg","3":920,"4":584},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBtFZgJ_dAq_1mez2TICKHMQF8A5Y_H2TOdjTbhKwI5gJpalpj6Q","3":200,"4":126},"3":{"1":"NME.com","2":"https://www.nme.com/news/film/wes-anderson-isle-of-dogs-accused-of-cultural-appropriation-2270903","3":"Wes Anderson's new film 'Isle Of Dogs' accused of cultural ...","4":"Wes Anderson's 'Isle Of Dogs' Credit: Press/Fox Searchlight","10":"WeFAhcACgFtWre"},"5":{"1":"WSjvUvHYAcYxlOV"}},{"1":{"1":"https://www.southwalesargus.co.uk/resources/images/8069964/?type=responsive-gallery-fullscreen","3":1200,"4":853},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPbAFtbuGs_brIhYaS5WeL1XS3d_-0cobmR3emTzDOfFIAOYcYKA","3":200,"4":142},"3":{"1":"South Wales Argus","2":"https://www.southwalesargus.co.uk/news/16354776.dog-of-the-week-special-urgent-homes-needed-for-influx-of-dogs/","3":"DOG OF THE WEEK SPECIAL: Urgent homes needed for influx of ...","4":"DOG OF THE WEEK SPECIAL: Urgent homes needed for influx of dogs","10":"iPPwrCQrHtUwnj"},"5":{"1":"ThnKbyBJkSonlPR"}},{"1":{"1":"http://images1.fanpop.com/images/photos/1900000/Puppy-3-dogs-1993798-1024-768.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRT4zOhw6SIGsnLaqC8XG3RQTwx1iEJKT98YoiDDYgCKr2dGWhrjw","3":200,"4":149},"3":{"1":"Fanpop","2":"http://www.fanpop.com/clubs/dogs/images/1993798/title/puppy-3-wallpaper","3":"Dogs images Puppy! <3 HD wallpaper and background photos ...","4":"Dogs images Puppy! <3 HD wallpaper and background photos","10":"FIfPysmQXPcEoO"},"5":{"1":"llqdQJtxyVThaQa"}},{"1":{"1":"https://media.newyorker.com/photos/591dccd9394e5718feb60feb/master/w_767,c_limit/NY-Hot-Dogs-23126.jpg","3":767,"4":767},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR0ZnFlsmwesaIXdETZY5aoM2LRKo3hoDcKy2mvnKVFW66j1iIY","3":200,"4":200},"3":{"1":"The New Yorker","2":"https://www.newyorker.com/culture/photo-booth/the-resplendent-humanity-of-dogs-up-close","3":"The Resplendent Humanity of Dogs, Up Close | The New Yorker","4":"18","10":"obsdwjSMvUjVkE"},"5":{"1":"dVCLBRwfFqBXWCd"}},{"1":{"1":"https://www.smartcompany.com.au/content/uploads/2015/02/labrador-600.jpg","3":600,"4":476},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ1oCXNLUiN5QKs8ocIR9-B6Wp8mEu0ZJthZWrIy4_xQ5X2yVyD0A","3":200,"4":158},"3":{"1":"SmartCompany","2":"https://www.smartcompany.com.au/business-advice/legal/dog-food-brand-purina-accused-of-killing-thousands-of-dogs-in-us-lawsuit/","3":"Dog food brand Purina accused of killing thousands of dogs in ...","4":"Dog food brand Purina accused of killing thousands of dogs in US lawsuit","10":"mAroiaYTrBkUhJ"},"5":{"1":"QclmbLEPrprbuAQ"}},{"1":{"1":"https://pmcvariety.files.wordpress.com/2018/03/klaus-dyba_dog1-e1521434052499.jpg?w=1000&h=563&crop=1","3":1000,"4":563},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmpK4KAjLAgKsfHh3h4UgzoEWBZs8dkmcbPUkNwKCR3BQvVL8E","3":200,"4":112},"3":{"1":"Variety","2":"https://variety.com/2018/digital/news/isle-of-dogs-photo-filters-vsco-1202729830/","3":"Isle of Dogs Photo Filters Launched by VSCO App – Variety","4":"VSCO Isle of Dogs","10":"yIIQcRMdUELwFK"},"5":{"1":"DRwSIJbAJufcUvs"}},{"1":{"1":"https://stylesatlife.com/wp-content/uploads/2015/11/Types-of-Dogs-1.jpg","3":500,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtD7XVGiTjOyaMLl6KKi1zgmt4Ksg3FqjyjYxTHpFfBlTf8Cp9gw","3":200,"4":160},"3":{"1":"Styles At Life","2":"https://stylesatlife.com/articles/types-of-dogs/","3":"25 Different Types of Dogs with Origins and Pictures | Styles ...","4":"Types of Dogs 1","10":"tOJvdJJkojReHe"},"5":{"1":"gHncbSaPleDBLkS"}},{"1":{"1":"https://static.independent.co.uk/s3fs-public/thumbnails/image/2018/10/17/11/pitbull-terrier.jpg","3":1885,"4":1414},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTFkzuvCcwzalnLPoz_B_GFuVJbWdy1gU18WCNntvEx6723UA_4","3":200,"4":149},"3":{"1":"The Independent","2":"https://www.independent.co.uk/topic/Dogs","3":"Dogs - latest news, breaking stories and comment - The ...","4":"Hundreds of dogs killed unnecessarily due to misguided laws, say MPs. '","10":"dBrfyemnfqPUHL"},"5":{"1":"bDcFFScCEXkdfSE"}},{"1":{"1":"https://housemydog.com/blog/wp-content/uploads/2017/01/cute-bulldog-smiling-sleeping-dog-narcoleptic-frenchiebutt-millo-2.jpg","3":605,"4":605},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5p9r1S8m6p7LxLVWdn7SIZ7pOxT4LjWxyXmGICcPsSkzdDBC7","3":200,"4":200},"3":{"1":"HouseMyDog","2":"https://housemydog.com/blog/12-photos-of-dogs-and-people-hugging","3":"12 Photos Of Dogs And People Hugging | HouseMyDog Blog","4":"12 Photos of Dogs And People Hugging","10":"BfHFdqIsgdXnvg"},"5":{"1":"hGdfYXJjwBWNhiH"}},{"1":{"1":"http://blog.petmeds.com/wp-content/uploads/2015/12/Dogs-scoot-for-a-variety-of-reasons-720x539.jpg","3":720,"4":539},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJY4S4-LSPElx1yw0jWJlAVtb4nVk_k1iZWjh5nSFLtfqw7eHJ","3":200,"4":149},"3":{"1":"Pet Meds","2":"https://blog.petmeds.com/ask-the-vet/dogs-that-scoot/","3":"The five W's of dogs that scoot","4":"Pug puppy scoots in the grass","10":"QuSVvhWOfrLOve"},"5":{"1":"NSiUBmiSPsgmdbh"}},{"1":{"1":"https://www.petdoors.com/blog/wp-content/uploads/2016/11/20160608_162336.jpg","3":3445,"4":2134},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRxitlvtt6iIOW0ARaZPUAD3TDnUbICzdaNH-MolMhbNFPkcjDLgQ","3":200,"4":124},"3":{"1":"Pet Doors","2":"https://www.petdoors.com/blog/weird-sleeping-positions-of-dogs/","3":"8 Weird Sleeping Positions of Dogs and What They May Mean","4":"tonks sleeping on side","10":"ugFixbcaUjflVW"},"5":{"1":"XjfrAbWCSueIFVj"}},{"1":{"1":"https://www.rover.com/blog/wp-content/uploads/2014/08/puppy-in-popcorn-bucket-960x540.jpg","3":960,"4":540},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRkb9P2Sc2YYiAQL-svc-HhRTTRRaoRXmDmCPAhlZXEnxUnC_S_DQ","3":200,"4":112},"3":{"1":"Rover.com","2":"https://www.rover.com/blog/list-of-dog-movies/","3":"Dog best friends in film: A list of dog movies","4":"Puppy in popcorn - list of dog movies","10":"KAbDbSDgeRWRSh"},"5":{"1":"qHkIgRTfksaBNLN"}},{"1":{"1":"http://www.beliefnet.com/columnists/islaminamerica/files/2015/07/puppy-300x200.jpg","3":300,"4":200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTFpW2rKLGgXz98fq6kA1ZfOpppZFQCS7DiWYZc_E9yw92k8g4W","3":200,"4":133},"3":{"1":"Beliefnet","2":"http://www.beliefnet.com/columnists/islaminamerica/2015/08/01/of-dogs-faith-and-islam/","3":"Of Dogs, Faith and Islam\" - Islam In America","4":"The Qu'ran doesn't label dogs as untouchable (in fact, there's quite a nice  vignette of the Prophet ...","10":"wTWCnjOjpgPeqC"},"5":{"1":"pcaojGbsRwBSnlg"}},{"1":{"1":"https://nationalpostcom.files.wordpress.com/2018/08/pot-dog-1.png","3":1000,"4":750},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSMHAQsQ9v5uiLxRcYzACMQaeYlASsLgRCdf7FQCR7dvd-dq5BpXg","3":200,"4":149},"3":{"1":"National Post","2":"https://nationalpost.com/cannabis/veterinarian-warns-dog-owners-on-cannabis-risks-saying-cases-come-in-weekly","3":"Vet warns of increase in cases of dogs suffering from ...","4":"Aspen, a Husky who was taken to emergency after consuming a presumed  cannabis product at a public ...","10":"ifbKSyggOghgok"},"5":{"1":"QYLiYKmNioYcMKF"}},{"1":{"1":"https://cdn1-www.dogtime.com/assets/uploads/2015/07/file_26979_column_grumpy-dog-earl.jpg","3":399,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSUhbiihu3jBahI_uxXELM5b39I1Jfgys43_yg2wcvB9u16gV1d_w","3":199,"4":200},"3":{"1":"Dogtime","2":"https://dogtime.com/trending/26979-meet-grumpy-dog-the-grumpy-cat-of-dogs","3":"Meet Grumpy Dog: The Grumpy Cat Of Dogs - Dogtime","4":"Meet Grumpy Dog: The Grumpy Cat Of Dogs","10":"tkDKCPGmDEwsLp"},"5":{"1":"pKJSXPQvDqeoJwt"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/147083304-dogs-home-alone-all-day-632x475.jpg","3":632,"4":475},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqYHACs2dhbqxtHrQkONT2kpL_266Yyz1Nr8Qx47NjM54tWY_rvg","3":200,"4":150},"3":{"1":"Petfinder","2":"https://www.petfinder.com/dogs/dog-care/dogs-home-alone-all-day/","3":"Dogs Who Are Home Alone All Day | Petfinder","4":"Dogs Who Are Home Alone All Day","10":"aRApkLsryspgvr"},"5":{"1":"pTnBSeEyxfvAcdB"}},{"1":{"1":"https://www.what-dog.net/Images/faces2/scroll008.jpg","3":600,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQeRO06aRgpx_cMscbjMIB1xhtYZOQ1x2lr4JL1zyw1V9dtVQlfzA","3":200,"4":200},"3":{"2":"https://www.what-dog.net/","3":"What is your dog?","4":"","10":"DVhcDonMkEPCvc"},"5":{"1":"XuuDRWfawIEwkmT"}},{"1":{"1":"https://usercontent1.hubstatic.com/7968066.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSLTxAtZayQYGIp-mX48YfSTdZ1uZBbCG7C13VvSipFeWpT1XLS0g","3":200,"4":149},"3":{"1":"PetHelpful","2":"https://pethelpful.com/dogs/The-Advantages-and-Disadvantages-of-Having-a-Dog","3":"The Advantages and Disadvantages of Having a Dog | PetHelpful","4":"","10":"PHAjVhJQgBreCM"},"5":{"1":"KGclwXLTfhffRbE"}},{"1":{"1":"http://www.picturesofdogs.co.uk/pictures/poodle1%20copy.jpg","3":450,"4":345},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEd2IqP7IPgmOq72NfG6kBOSML6oNcKU1RP7GUVcXFhygTyCFiVw","3":200,"4":153},"3":{"2":"http://www.picturesofdogs.co.uk/","3":"Pictures of Dogs- Pictures Please","4":"Pictures of Dogs","10":"MjeyCYwFOOXIiD"},"5":{"1":"IqdKtHYxoHDvClM"}},{"1":{"1":"https://i.ytimg.com/vi/jJGItJSU1aM/hqdefault.jpg","3":480,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8f2B8tVeG9hrinolfzSFeYqiSgGiK6-HYtLlrUhVDg7YTT-wJgQ","3":200,"4":149},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=jJGItJSU1aM","3":"Different Breeds of Dogs","4":"Different Breeds of Dogs","10":"fJgMXsPToLMMdP"},"5":{"1":"kwiHRNPInpkbNNL"},"7":{"1":{"11":{"1":"Different Breeds of Dogs","2":"A slide show of a different variety of Dogs","3":"4:15","4":"34165","5":"1218844800000","6":"Natasha Eyden","7":"79","8":"20"}}}},{"1":{"1":"https://3c1703fe8d.site.internapcdn.net/newman/gfx/news/hires/2018/2-dogs.jpg","3":1920,"4":1755},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLa94Qb6HvKe7C-Ubn0jxrHHlSj4eemB7DwvDrv6RVjt8Oa7tgSQ","3":200,"4":182},"3":{"1":"Phys.org","2":"https://phys.org/news/2018-10-evidence-dogs-accompanying-humans-europe.html","3":"Evidence of dogs accompanying humans to Europe during Neolithic","4":"Credit: CC0 Public Domain","10":"UlWSqGAKobFJKA"},"5":{"1":"UILGEmQFEFoVAsn"}},{"1":{"1":"https://pixel.nymag.com/imgs/daily/vulture/2018/03/14/14-isle-of-dogs.w1200.h630.jpg","3":1200,"4":630},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTnStaY7_N_-4QdrCvyM4lL2lhbyva5oq2XffsaNXNFpAs9vGM0","3":200,"4":105},"3":{"1":"Vulture","2":"http://www.vulture.com/2018/03/watch-this-video-introducing-the-dogs-of-isle-of-dogs.html","3":"Watch This Short Film Introducing the Dogs of Isle of Dogs","4":"","10":"mypNHTvWswtCOc"},"5":{"1":"lDgHnJMPFmMtKJf"}},{"1":{"1":"https://i.pinimg.com/736x/f5/7e/00/f57e00306f3183cc39fa919fec41418b--teddy-bears-teddy-bear-dogs.jpg","3":736,"4":1169},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJCqloOub7mjnQN642eZl5b6--cZA9bCIbF2djsa8iu49b4ZCGWg","3":125,"4":200},"3":{"1":"Pinterest","2":"https://www.pinterest.com/pin/436075176396371066/","3":"Pin by Debbie Smith on A ! ADORABLE | Pinterest | Dog, Animal ...","4":"Pin by Debbie Smith on A ! ADORABLE | Pinterest | Dog, Animal and Puppys","10":"hKSgDyvRymSNOK"},"5":{"1":"nrkXvuIUqRUTJTg"}},{"1":{"1":"https://s.abcnews.com/images/Video/GTY_dog_day_jef_160826_16x9_992.jpg","3":992,"4":558},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRbFXNRTNnAXdUs_QDs214jo1FjE8COPoo4G-_P9qWw9ARNwuyb","3":200,"4":112},"3":{"1":"ABC News - Go.com","2":"https://abcnews.go.com/Lifestyle/history-dogs-pets/story?id=41671149","3":"The History of Dogs as Pets - ABC News","4":"","10":"dQNaxWEwmsEgUC"},"5":{"1":"bjrXwgWopfKXlyE"}},{"1":{"1":"https://ichef.bbci.co.uk/news/660/cpsprodpb/B45D/production/_100637164_dogs_fox.jpg","3":660,"4":371},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT91tSrZ8U2pYvHbjt0zlEMAUJqWF4MaUv1eQ_LUQljDRpWygA7ag","3":200,"4":112},"3":{"1":"BBC","2":"https://www.bbc.co.uk/news/entertainment-arts-43595611","3":"Why Isle of Dogs is no shaggy dog story - BBC News","4":"Isle of Dogs","10":"adxyWuDDKnakQS"},"5":{"1":"NSqbjoIcrHjXDQU"}},{"1":{"1":"http://bdfjade.com/data/out/65/5719631-picture-of-dogs.jpg","3":600,"4":507},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTghCT-JVAlT-a7YLqHgjsIUDd22U7pV1NlFp2lA9z2XY4PrdZncQ","3":200,"4":168},"3":{"1":"BDFjade","2":"http://bdfjade.com/picture-of-dogs.html","3":"Picture Of Dogs - BDFjade","4":"Dogs Background Galleries » PT-5719631 FHDQ Pictures","10":"TtaqJYSoykOYvn"},"5":{"1":"lHKIsGwxfrMSwTa"}},{"1":{"1":"https://www.stayathomemum.com.au/cache/860x380-0/wp-content/uploads/2017/01/photo-1513549054-cb3611a004fe.jpg","3":574,"4":380},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTlsQHCHS3pVNI4Jm3Z7tcezteSPg9GGv676JZLJBEsNjYvYJHBaQ","3":200,"4":132},"3":{"1":"Stay at Home Mum","2":"https://www.stayathomemum.com.au/houseandhome/pets-and-pet-food/10-breeds-of-dogs-suited-to-family-life-and-children/","3":"10 Breeds Of Dogs Suited To Family Life And Children","4":"","10":"vmDYjbCRtwgNQP"},"5":{"1":"WkdpRVbYsEDmsBq"}},{"1":{"1":"https://stylesatlife.com/wp-content/uploads/2015/11/Types-of-Dogs-22.jpg","3":482,"4":420},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSr-BIza-ID0B_5mHNYZVelACXRObpmJR0A5-vL7LpFQt16XH8t3g","3":200,"4":174},"3":{"1":"Styles At Life","2":"https://stylesatlife.com/articles/types-of-dogs/","3":"25 Different Types of Dogs with Origins and Pictures | Styles ...","4":"Types of Dogs 22","10":"SmymfRmNuLHFEc"},"5":{"1":"DnhvsmvWSkWTSkR"}},{"1":{"1":"https://images.pexels.com/photos/406014/pexels-photo-406014.jpeg?auto=compress&cs=tinysrgb&h=350","3":525,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQMgpV4Dnq4Jd3rBDSJn7AgBp8tMMC9mvRmrd3mCQFe5fs_pW4u","3":200,"4":133},"3":{"1":"Pexels","2":"https://www.pexels.com/search/dog/","3":"Dog images · Pexels · Free Stock Photos","4":"Free stock photo of animal, dog, pet, cute","10":"dxlyAYargfusMe"},"5":{"1":"GwgMRCRrwyIBqXi"}},{"1":{"1":"https://s3.amazonaws.com/cdn-origin-etr.akc.org/wp-content/uploads/2017/11/13001724/American-Eskimo-Dog-On-White-01-400x267.jpg","3":400,"4":267},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTsGNRvlsg6L4sauv_tewVzBQdd7kdb-vT-jKmX6_AB6RWes_V2VA","3":200,"4":133},"3":{"1":"American Kennel Club","2":"https://www.akc.org/dog-breeds/smallest-dog-breeds/","3":"Smallest Dog Breeds – American Kennel Club","4":"American Eskimo Dog","10":"VJLsPEQkfoTgaB"},"5":{"1":"ToAVtwjKBjwaVpB"}},{"1":{"1":"https://www.nc3rs.org.uk/sites/default/files/Images/Animals/Beagles%20in%20safety%20testing%20of%20pharmaceuticals%20-%20RDS.Wellcome.jpg","3":1200,"4":993},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQebnD-bP3tQJxRd0Lw5FaVB6Tmn2b65Or7Snpg04onQpecxfU7ng","3":200,"4":165},"3":{"1":"NC3Rs","2":"https://www.nc3rs.org.uk/3rs-resources/housing-and-husbandry/housing-and-husbandry-dogs","3":"Housing and Husbandry of Dogs | NC3Rs","4":"This page provides advice on the housing of laboratory dogs, tools for  their welfare assessment, ...","10":"pOQBKsUaAExDxp"},"5":{"1":"soKGyPTBNHVPxGm"}},{"1":{"1":"https://cdn.theatlantic.com/assets/media/img/mt/2016/07/max_2/lead_720_405.jpg?mod=1533691832","3":720,"4":405},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRrD_FLFfRw23FSZMRB5oLYOi28vU0rrIsEPf6O_oqlKVtYth2RRA","3":200,"4":112},"3":{"1":"The Atlantic","2":"https://www.theatlantic.com/entertainment/archive/2016/07/the-secret-life-of-pets/490580/","3":"For the Love of Dogs: 'The Secret Life of Pets,' Reviewed ...","4":"Illumination","10":"YYLAymmDrQbMHf"},"5":{"1":"HmwhYiETYOWcYNv"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/d/d9/Collage_of_Nine_Dogs.jpg","3":1665,"4":1463},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRGLQqDCxokM9-_Unrinvx32TEgykSGEiFd8ZN9_ZSsfrEI1ue4iQ","3":200,"4":175},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Dog","3":"Dog - Wikipedia","4":"Collage of Nine Dogs.jpg","10":"uUlLvuUdcuOcIL"},"5":{"1":"uRpIPGNqDVNVpKg"}},{"1":{"1":"http://nldogwhisperer.com/_Media/p4180071_med.jpeg","3":281,"4":281},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDL2Bb5WHO2ylKI0hZM6TqQdBdlk89CR4BMmWlOK02VWBc-dBbNw","3":200,"4":200},"3":{"1":"Newfoundland's Dog Whisperer","2":"http://nldogwhisperer.com/for-the-love-of-dogs/","3":"For the Love of Dogs | Newfoundland's Dog Whisperer","4":"P4180071","10":"DLKanCBMubnDNQ"},"5":{"1":"WBbNVOrlmjMkMgc"}},{"1":{"1":"https://www.wikihow.com/images/1/1d/Take-Care-of-Your-Dog's-Basic-Needs-Step-35.jpg","3":3200,"4":2400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYXiN0MJz5noouc0Rd01auqVsg8HYdxj4XBWBUl9bMMY8lTVG8yA","3":200,"4":149},"3":{"1":"wikiHow","2":"https://www.wikihow.com/Take-Care-of-Your-Dog%27s-Basic-Needs","3":"How to Take Care of Your Dog's Basic Needs (with Pictures)","4":"","10":"bQvvWVUSirmQyO"},"5":{"1":"XuJuXQFfiNvxlyK"}},{"1":{"1":"https://res.cloudinary.com/dk-find-out/image/upload/q_80,w_640,f_auto/12173877_lnvjts.jpg","3":640,"4":459},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSOCIJw6yuhX0fDgoYYzEQXpa7a4ThCE0N_IaetPAZx_Nb0HoTf","3":200,"4":143},"3":{"1":"DK Find Out!","2":"https://www.dkfindout.com/us/animals-and-nature/dogs/domestic-dogs/","3":"Domestic Dogs | Different Types of Dogs | DK Find Out","4":"Dog-main gdcdzd 12173877 lnvjts ...","10":"LpcncxxURIVDEA"},"5":{"1":"RFwLNBmyxgHhnwp"}},{"1":{"1":"https://amp.thisisinsider.com/images/57991d1dd7c3dbae2f8b4657-750-753.png","3":750,"4":753},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTpJq9dJS4dwAjqC6XT35fePL5fVdzpOcgr7djBXCQC45K3OFSCw","3":199,"4":200},"3":{"1":"Insider","2":"https://www.thisisinsider.com/dogs-before-and-after-haircuts-2016-7","3":"Dogs before and after haircuts - INSIDER","4":"Dogs Grace Chon","10":"OBPPjJXnGrWwvC"},"5":{"1":"UfREGxjhQAMqYTc"}},{"1":{"1":"https://timedotcom.files.wordpress.com/2017/04/world-of-dogs-07.jpg","3":2560,"4":1828},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQyXm57CVzJ5EUvu0HvCxqJ7QazwoqMvtL_CH8d-njiLP2lJXlk","3":200,"4":142},"3":{"1":"Time","2":"http://time.com/4775436/how-smart-is-a-dog-really/","3":"A Dog's Brain: Inside the Complex Canine Mind | Time","4":"Nina, an 8-month old Mini Australian Shepherd photographed in New York, NY","10":"SeOxdryAqGCQsI"},"5":{"1":"hPksBoksmOBlNAe"}},{"1":{"1":"https://www.sciencefriday.com/wp-content/uploads/2015/07/12872-1.JPG","3":1000,"4":586},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQuiulGxI6NDSiHAn-tomXc8p0pbyoFyE8F5LGL4Al6ov-QIC0uDQ","3":200,"4":117},"3":{"1":"Science Friday","2":"https://www.sciencefriday.com/segments/dogs-theyre-just-like-us/","3":"Dogs, They're Just Like Us - Science Friday","4":"","10":"hyVtWTqlYpfQXU"},"5":{"1":"goAktcmFFRUUUxT"}},{"1":{"1":"http://images.performgroup.com/di/library/sporting_news/dc/50/dog-3jpg_cp4bgn0c2fk31va2bwpmsci2b.jpg?t=1041338754&w=960&quality=70","3":960,"4":540},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyNLvBbdisDSOVgm54zOFo3euAJl01P_n7MHrsjGwKHnE-Svjr","3":200,"4":112},"3":{"1":"Sporting News","2":"http://www.sportingnews.com/us/other-sports/news/adorable-dogs-2017-westminster-dog-show-photos/q4qu9orrlgq11k3mhptiohrlp","3":"Adorable photos of dogs at the 2017 Westminster Dog Show ...","4":"Dog 3.jpg","10":"rJfjBxOadbyMjm"},"5":{"1":"JSQfIlTHfpFNgrw"}},{"1":{"1":"https://i2-prod.mirror.co.uk/incoming/article6113280.ece/ALTERNATES/s615/PAY--Dog-swallowed-21-inch-riding-crop--whole.jpg","3":615,"4":409},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtkEnSyD6xOwHjh59HAejWd4_9LUq3131QxZkw9JCmB0SJs99Jww","3":200,"4":133},"3":{"1":"Daily Mirror","2":"https://www.mirror.co.uk/news/uk-news/sickening-pictures-poorly-boxer-show-7062981","3":"Sickening pictures of poorly boxer show the danger of dogs ...","4":"Hugo the dog who swallowed a 21 inch riding crop","10":"jKlAiLEGdNSLvC"},"5":{"1":"VrBMenmDSMcGMus"}},{"1":{"1":"http://3.bp.blogspot.com/-F2N-smOO2eI/UfCrLF7syeI/AAAAAAAAAE4/Mp4o0J2vw8s/s1600/Type+of+dog+Patuljasti+SPICE.jpg","3":500,"4":477},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYrAmtPktHqaOxLhSZekIE7JAYa75a9Y2IcCaC1RYJZJbZFUg","3":200,"4":190},"3":{"1":"types of dogs","2":"http://all-typesofdogs.blogspot.com/2013/01/type-of-dog-patuljasti-spice.html","3":"Type of dog Patuljasti SPICE - TYPES OF DOGS","4":"Type of dog Patuljasti SPICE","10":"cSrkLMkXibhHAn"},"5":{"1":"hMYJhfkRorfymFf"}},{"1":{"1":"http://www.qygjxz.com/data/out/183/3980549-pictures-of-dogs.jpg","3":1920,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTbcM2cUV0OTBqLzu9PI67wGMZ1zscxyhetpuCT7iDcMtL4w4Q8","3":200,"4":124},"3":{"1":"QyGjxZ","2":"http://www.qygjxz.com/pictures-of-dogs.html","3":"Pictures Of Dogs - QyGjxZ","4":"Pictures Of Dogs","10":"LOfwRGKPjLYykB"},"5":{"1":"CjNNRjsPTHWFxeo"}},{"1":{"1":"http://www.pawculture.com/uploads/magic-of-dogs-book-destroyer-card.jpg","3":300,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzAFi5bs4u5U0ltE5wgvLY7T-WDzDMctigQm98cc6Yt5eltVwI","3":200,"4":200},"3":{"1":"PawCulture","2":"http://www.pawculture.com/get-inspired/magic-of-dogs","3":"Magic of Dogs | PawCulture","4":"Daisy the puppy in a closet","10":"OSmQrTICUnJcUR"},"5":{"1":"mITEEsGnnMdmedm"}},{"1":{"1":"https://www.soidog.org/sites/default/files/Dogs_for_adoption.jpg","3":1200,"4":662},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7CIoAyUpdA0z_qUGMgonqjeI0B9Vj-Ughlhil-aDrCZ8dVlrlYg","3":200,"4":110},"3":{"1":"Soi Dog Foundation","2":"https://www.soidog.org/adopt-a-dog","3":"Dogs For Adoption | Soi Dog Foundation","4":"At the Soi Dog Foundation shelter, hundreds of dogs wait in anticipation of  loving homes.","10":"LTrFnEFufygVUl"},"5":{"1":"ekyHhXeckvbeULy"}},{"1":{"1":"https://www.abc.net.au/news/image/7089596-3x2-940x627.jpg","3":940,"4":627},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSpb6cNSSuVCnstfWoSuYxVldq9VBTuPeJtu9Nvw3OiMTOVxNeuQg","3":200,"4":133},"3":{"1":"ABC","2":"http://www.abc.net.au/news/2016-01-22/dog-cruelty-stolen-pets-tourists-fuelling-growth-in-meat/7088380","3":"Dog cruelty: Rise in slaughter of stolen pets as Western ...","4":"... Thousands of dogs have been taken by dog meat smugglers but hundreds  have been saved","10":"QKBMOWnXdPgsOs"},"5":{"1":"poXeMAIMtVwnynW"}},{"1":{"1":"https://ybxzcgnc7b-flywheel.netdna-ssl.com/wp-content/uploads/2018/04/male-dog-names-696x435-2.jpg","3":696,"4":435},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSBtHfW9n6ZlEpWaon8kohv1YMJLwXGWfW9U9AB4uztQ2TyLs2ExA","3":200,"4":124},"3":{"1":"The Labrador Site","2":"https://www.thelabradorsite.com/male-dog-names/","3":"Male Dog Names - 150 Brilliant Boy Puppy Name Ideas","4":"Looking for the best male dog ...","10":"yftxFbRJDNJFiA"},"5":{"1":"CwgdpgemBLeBpKD"}},{"1":{"1":"https://www.sciencemag.org/sites/default/files/styles/inline__450w__no_aspect/public/dogs_16x9_0.jpg?itok=6bVMiQge","3":450,"4":253},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSoAY0lBnJg5p3jCKy0bYcuiA-CAS6fwaYe-dwgy0fKfchB82xYow","3":200,"4":112},"3":{"1":"Science","2":"https://www.sciencemag.org/news/2018/08/gene-editing-dogs-offers-hope-treating-human-muscular-dystrophy","3":"Gene editing of dogs offers hope for treating human muscular ...","4":"A colony of dogs at the Royal Veterinary College in London has a mutation  that causes a disease ...","10":"uXDTlpYMRxSysc"},"5":{"1":"hfpslxcHPIhamYL"}},{"1":{"1":"http://www.pbs.org/wgbh/nova/assets/img/posters/meaning-dog-barks-in.jpg","3":322,"4":215},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR83E68kzlY537bxNXFpIzyh4q5OHHa1PZMrJ3n1HOaKfuVDDO7","3":200,"4":133},"3":{"1":"PBS","2":"http://www.pbs.org/wgbh/nova/nature/meaning-dog-barks.html","3":"NOVA - Official Website | The Meaning of Dog Barks","4":"Sources","10":"HeNjnISBGrERNc"},"5":{"1":"yxTUeintWQNxRXd"}},{"1":{"1":"http://cdn.designbeep.com/wp-content/uploads/2011/07/4.dog-love-photos.jpg","3":500,"4":525},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcScX6-QU4RNXhufTydEl5dppkHDnc0XMxOKFScQUw8xjadr6Ljc","3":190,"4":200},"3":{"1":"Designbeep","2":"http://designbeep.com/2011/07/29/heart-touching-photos-of-dogs-with-humans/","3":"Heart Touching Photos of Dogs with Humans | Designbeep","4":"humans and dogs","10":"VBfUhIuRdeHujs"},"5":{"1":"uMfRjnatednVxnF"}},{"1":{"1":"https://gfnc1kn6pi-flywheel.netdna-ssl.com/wp-content/uploads/2015/04/2015-0423-1157-fb.jpg","3":1120,"4":584},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM1fHGWOoPPAiEUl6E9FQOgXzVpYzf9isnt8a78ScgfGWq8oGP","3":200,"4":104},"3":{"1":"The Happy Puppy Site","2":"https://thehappypuppysite.com/dog-breed-groups/","3":"Different Types Of Dogs: The Dog Breed Groups Explained","4":"a group of small dogs puppies beagle","10":"NlbBUKGIwLLigm"},"5":{"1":"vNMpIKLUHNsBVaG"}},{"1":{"1":"https://www.police.gov.hk/info/img/pdu/German_Shepherd.jpg","3":400,"4":322},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFxTlVZoUanSWoUXLNE6pXXWLSzJQu9l1FMxKLCdlSsn7uTzv5","3":200,"4":160},"3":{"2":"https://www.police.gov.hk/ppp_en/11_useful_info/pdu/type.html","3":"Type of Dogs | Hong Kong Police Force","4":"Type of Dogs","10":"HmIFpgTtwytwTY"},"5":{"1":"jNsiYMpoJodyirS"}},{"1":{"1":"https://images.penguinrandomhouse.com/cover/9780451497604","3":292,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvd839rC2S7o1c6nOIZt_sQ1hi0p7zWbI7cR_k6-C098hW9qPv","3":129,"4":200},"3":{"1":"Penguin Random House","2":"https://www.penguinrandomhouse.com/books/546898/the-grace-of-dogs-by-andrew-root/9780451497611/","3":"The Grace of Dogs by Andrew Root | PenguinRandomHouse.com","4":"The Grace of Dogs by Andrew Root","10":"TLRVaBgWkJywvH"},"5":{"1":"wKJVsNHAkjobIKG"},"7":{"1":{"10":{"3":"The Grace of Dogs by Andrew Root | PenguinRandomHouse.com","5":"In the bestselling tradition of Inside of a Dog and Marley & Me, a smart,  illuminating, and entertaining read on why the dog-human relationship is ...","6":true,"7":15.949999809265137,"8":"USD"}}}},{"1":{"1":"http://1.bp.blogspot.com/-D1v9yJRY3Xg/T7ZWzWXAleI/AAAAAAAABuU/4r7Cx4Fra0c/s1600/all+types+of+dogs+1.jpg","3":432,"4":625},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAbyyckK5hIAi5GlQ0t8QhR_EItcdEtUPBhiljyqGLDey1uBta","3":138,"4":200},"3":{"1":"My Top Collection","2":"http://mytopcollection.blogspot.com/2012/05/all-types-of-dogs.html","3":"My Top Collection: All types of dogs","4":"All types of dogs","10":"UilxngmFAWEiiK"},"5":{"1":"gboiCenfWAMpIND"}},{"1":{"1":"https://cdn.theatlantic.com/assets/media/img/mt/2018/03/wes_andersons_isle_of_dogs_is_a_tenderhearted_eccentric_canine_tale_ew_review/lead_720_405.jpg?mod=1533691928","3":720,"4":405},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAhkKwPcbRFSxfvQujIzPRVsP1vF0CURiSHZVSFvhQs31Dtth9","3":200,"4":112},"3":{"1":"The Atlantic","2":"https://www.theatlantic.com/entertainment/archive/2018/03/isle-of-dogs-review/556292/","3":"Wes Anderson's 'Isle of Dogs' Is Beautiful and Sad: Review ...","4":"Fox Searchlight Pictures. “","10":"oSNOuYnslFqJPQ"},"5":{"1":"WDVuvFIUhbsBclN"}},{"1":{"1":"https://cdn.flickeringmyth.com/wp-content/uploads/2018/03/Isle-of-Dogs-character-posters-5-600x851.jpg","3":600,"4":851},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQw50y6LpR2SFWeRSzXZhCEnBGSZ-8kL88QDFSI5CwcDosNKZCzfQ","3":140,"4":200},"3":{"1":"Flickering Myth","2":"https://www.flickeringmyth.com/2018/03/isle-of-dogs-gets-a-series-of-canine-character-posters/","3":"Isle of Dogs gets a series of canine character posters","4":"ISLE OF DOGS tells the story of ATARI KOBAYASHI, 12-year-old ward to  corrupt Mayor Kobayashi.","10":"hlcUpQnykUBRsD"},"5":{"1":"bJuriALucgcSYfp"}},{"1":{"1":"https://i.ytimg.com/vi/QrBvVOoQXCA/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRw6PNel35EaV_kL94y7L3NITd6CI0PQXT5GvgPyzsk23ThnYvl","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=QrBvVOoQXCA","3":"ISLE OF DOGS | Making of: Puppets | FOX Searchlight","4":"ISLE OF DOGS ...","10":"LaWwplLDmbxIGi"},"5":{"1":"YEASMqwXoGYlCoO"},"7":{"1":{"11":{"1":"ISLE OF DOGS | Making of: Puppets | FOX Searchlight","2":"Now on Digital: http://bit.ly/Isle-Of-Dogs Now on Blu-ray and DVD:  http://bit.ly/Isle_Of_Dogs ISLE OF DOGS tells the story of ATARI KOBAYASHI,  12-year-old wa...","3":"4:01","4":"225512","5":"1522627200000","6":"FoxSearchlight","7":"4097","8":"181"}}}},{"1":{"1":"https://static.pjmedia.com/homeland-security/user-content/53/files/2017/03/AP_17071375979364.sized-770x415x0x587x2759x1487.jpg","3":770,"4":415},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQPmnBCkO9u4V6pPdOCN-tdG7t2shwky_RJitakfAZCFZpWQV-y1A","3":200,"4":107},"3":{"1":"PJ Media","2":"https://pjmedia.com/homeland-security/2017/03/14/why-do-so-many-muslims-hate-dogs/","3":"Why Does Islam Teach Hatred of Dogs?","4":"Why Do So Many Muslims Hate Dogs?","10":"knGDhxKVKYAMoa"},"5":{"1":"UXGdXsRnndWjRkG"}},{"1":{"1":"https://ksassets.timeincuk.net/wp/uploads/sites/55/2018/03/M9WC84-copy-920x584.jpg","3":920,"4":584},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT2qLLzgdW9KLjmU1WyjWV8GdiwT2E0ORCDSG05edJ-CMPngeOZ","3":200,"4":126},"3":{"1":"NME.com","2":"https://www.nme.com/reviews/movie/isle-of-dogs-wes-anderson-film-review","3":"Isle Of Dogs review: \"a canine-tastic classic from Wes Anderson\"","4":"Isle of Dogs review","10":"tqSSbIayecUptP"},"5":{"1":"kDVrLYubfwlIEsJ"}},{"1":{"1":"https://cdn.abcotvs.com/dip/images/4233273_091318wtvddogrescuepg1.jpg","3":540,"4":960},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR32rG3iGhRx5mSI8or0zA-9glC4YGt6D4suZuwCcHCQov1P_hM","3":112,"4":200},"3":{"1":"WTVD","2":"https://abc11.com/peak-lab-rescue-saves-dozens-of-dogs-ahead-of-hurricane-florence/4233351/","3":"Peak Lab Rescue saves dozens of dogs ahead of Hurricane ...","4":"Peak Lab Rescue saves dozens of dogs ahead of Hurricane Florence","10":"idpRKpkMwsFNPM"},"5":{"1":"XqVxubpOOppKldH"}},{"1":{"1":"https://media.npr.org/assets/img/2018/03/20/isleofdogs_domestictrailera_txtd_stereo_pr.max-2000x2000_wide-65e44dee126c79b304eadea538e7a6e431a3b8f5-s800-c85.jpg","3":800,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbw9ijmCB3MYzA9W0JI1zLSUByHhz7k8cmM-OX3ZJ8IOAyJqCC","3":200,"4":112},"3":{"1":"NPR","2":"https://www.npr.org/2018/03/22/595194000/the-fast-and-the-furry-us-wes-andersons-masterful-isle-of-dogs","3":"The Fast And The Furry Us: Wes Anderson's Masterful 'Isle Of ...","4":"The Fast And The Furry Us: Wes Anderson's Masterful 'Isle Of Dogs'","10":"TDSoYIgGdaUrsu"},"5":{"1":"fFrdWxxCaWYCrsq"}},{"1":{"1":"https://cdn.kinsights.com/cache/a2/d0/a2d0e228b189836ebc8db503b361d51b.jpg","3":700,"4":305},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKZFyzTBFFkSPnKYJRPYqO__yyePdhoQVpuJ4NMFeNYCeId4gaNg","3":200,"4":87},"3":{"1":"Care.com","2":"https://www.care.com/c/stories/6036/10-fastest-dog-breeds/","3":"10 Fastest Dog Breeds - Care.com","4":"Over the last few centuries, certain types of dogs have been bred for  hunting and racing purposes.","10":"IPkBfAlgpdjjBJ"},"5":{"1":"GdiHoxKRefTnidc"}},{"1":{"1":"https://s.hswstatic.com/gif/frog-1.jpg","3":400,"4":349},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSkD4aIcnoKQk8ptMFEszKlT6UyhIkRee-431_9CtgdDMIvowV4","3":200,"4":175},"3":{"1":"Animals | HowStuffWorks","2":"https://animals.howstuffworks.com/amphibians/frog.htm","3":"How Frogs Work | HowStuffWorks","4":"Green tree frog (Hylidae cinerea). See more amphibian pictures.","10":"oIPgOQIeUteTVv"},"5":{"1":"qGflvvGOFClFscO"}},{"1":{"1":"https://media.wired.com/photos/5abc3122ecb0130b0e72616c/master/pass/frogleaf.jpg","3":2400,"4":1800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS269AZWer7OVu1kw705ldxEHbn2J-pHJ6JSnb0xN5xfG_CvoEl","3":200,"4":149},"3":{"1":"Wired","2":"https://www.wired.com/story/some-frogs-may-be-developing-a-resistance-to-the-disastrous-chytrid-fungus/","3":"Some Frogs May Be Developing a Chytrid Fungus Resistance | WIRED","4":"Some Frogs May Be Developing a Resistance to the Disastrous Chytrid Fungus","10":"WADbSMNiLmVldA"},"5":{"1":"GCKOCqfbKuVTFNd"}},{"1":{"1":"https://cosmos-magazine.imgix.net/file/spina/photo/10994/170407_Frogs_Full.jpg?fit=clip&w=835","3":835,"4":557},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRaVKwWQteHk6Jw5tfXQqYA56T98oG_gFg8K94grY4KlGoUBOAi","3":200,"4":133},"3":{"1":"Cosmos Magazine","2":"https://cosmosmagazine.com/palaeontology/the-death-of-the-dinosaurs-was-good-news-for-frogs","3":"The death of the dinosaurs was good news for frogs | Cosmos","4":"Two Petropedates cameronensis frogs, from Cameroon.","10":"oGVNAKqmOAwwLE"},"5":{"1":"EoJBsLKWhdkSUpN"}},{"1":{"1":"https://images.theconversation.com/files/117973/original/image-20160408-23649-1qxbogn.jpg?ixlib=rb-1.1.0&rect=0%2C516%2C2537%2C1652&q=45&auto=format&w=926&fit=clip","3":926,"4":603},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcROccUf9pp8ecFARqw_6DGs0uNfy88wxZrrmO3OLJmt4HAO-5l-","3":200,"4":130},"3":{"1":"The Conversation","2":"http://theconversation.com/the-future-for-frogs-looks-bleak-unless-humans-change-their-habits-57505","3":"The future for frogs looks bleak, unless humans change their ...","4":"The future for frogs looks bleak, unless humans change their habits","10":"GVxYqfUfpvOaNP"},"5":{"1":"hdrXHFELxglqDQA"}},{"1":{"1":"https://r.hswstatic.com/w_907/gif/frogs-sysk.jpg","3":907,"4":510},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4fKzSHuYmdwaVO9r3iz7z6-YU-RoiWrrU_aekfcxdSMs-_dkD","3":200,"4":112},"3":{"1":"Stuff You Should Know","2":"https://www.stuffyoushouldknow.com/podcasts/frogs.htm","3":"How Frogs Work | Stuff You Should Know","4":"How Frogs Work","10":"KcuycTLNCTKyeK"},"5":{"1":"kDRqcVBphsrCkxY"}},{"1":{"1":"https://le-www-live-s.legocdn.com/sc/media/lessons/wedo-2/wedo-projects/images/frogs-metamorphosis-project-image-feb9db40c70bcda57e12f5671d4bc278.jpg?fit=around|700:700&crop=700:700;*,*","3":700,"4":700},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRNbtN7UdIGFNqIJqRNaWtpxRa-8fONHoROYjex1_qG_s1yn_rlkw","3":200,"4":200},"3":{"1":"LEGO Education","2":"https://education.lego.com/en-us/lessons/wedo-2-science/frogs-metamorphosis","3":"Frog's Metamorphosis - WeDo 2.0 Science - Lesson Plans - LEGO ...","4":"Frog's Metamorphosis - WeDo 2.0 Science - Lesson Plans - LEGO Education","10":"LuCYFWOHovAfWs"},"5":{"1":"QYqyhfrbLHIDSaU"}},{"1":{"1":"https://www.amnh.org/var/ezflow_site/storage/images/media/amnh/images/frog/311113-1-eng-US/frog_dynamic_lead_slide.jpg","3":700,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtD1jRBEihnL1c2uHLMsDTPHLbxaXgm2VniPs7rmxYCGSChO7n","3":200,"4":100},"3":{"1":"American Museum of Natural History","2":"https://www.amnh.org/exhibitions/frogs-a-chorus-of-colors","3":"Frogs: A Chorus of Colors","4":"frog","10":"BHmJIRtnQIHBsx"},"5":{"1":"llGYGsDHxxtOAgh"}},{"1":{"1":"https://cdn.theatlantic.com/assets/media/img/mt/2018/05/ohanlon3HR/lead_720_405.jpg?mod=1533691465","3":720,"4":405},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSocW1F9hcYfvbUB2jHJEzREuIzDsbL6E-_20kEv-YMUbA8_A6l9Q","3":200,"4":112},"3":{"1":"The Atlantic","2":"https://www.theatlantic.com/science/archive/2018/05/frog-fungus-death/560078/","3":"The Origins of the Fungus Killing Frogs - The Atlantic","4":"A green and black frog with a red belly","10":"MEYPTxrgIFQDIY"},"5":{"1":"rlXkQPSDqhqLUYJ"}},{"1":{"1":"https://pmdvod.nationalgeographic.com/NG_Video/952/231/smpost_1507049364751.jpg","3":640,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSNoa4awiR95D5rAClkS7gFSV4JJXD08hAIb8LxjU_1M2i8eqqIcQ","3":200,"4":112},"3":{"1":"National Geographic","2":"https://video.nationalgeographic.com/video/untamed/red-eyed-tree-frogs","3":"Why Does the Red-Eyed Tree Frog Have Three Eyelids?","4":"","10":"EodtsMOmwkmvxy"},"5":{"1":"TRhMSfpPGpbAhfi"}},{"1":{"1":"http://ichef.bbci.co.uk/wwfeatures/wm/live/1280_640/images/live/p0/29/n2/p029n2vj.jpg","3":1280,"4":640},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLGsWeKSeL3n9sUPGD7Mi-WZF50vWpD_UiYo1vxF9P_V3LchLefQ","3":200,"4":100},"3":{"1":"BBC.com","2":"http://www.bbc.com/earth/story/20141029-rare-frog-breeds-inside-bamboo","3":"BBC - Earth - Rare bush frog breeds inside bamboo","4":"","10":"tblmAYrHcdmEcx"},"5":{"1":"qnVLROrMlgjmrAr"}},{"1":{"1":"https://3c1703fe8d.site.internapcdn.net/newman/csz/news/800/2017/whyfrogsneed.jpg","3":700,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAV6FLTscPNap-dxagGyyY5jA47enViUiFeyWiEpb6vS4xvxtl","3":200,"4":128},"3":{"1":"Phys.org","2":"https://phys.org/news/2017-05-frogs.html","3":"Why frogs need saving","4":"","10":"UBtkEBvnckXXVh"},"5":{"1":"wUKJyAlAUsxvETX"}},{"1":{"1":"https://3z2dsg30wpre3s82ui42uwfo-wpengine.netdna-ssl.com/wp-content/uploads/2013/02/dumpy-tree-frog.jpg","3":1000,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTTuPr02JgQNW-5wZUoiCNTBlMkS6hGq_Gk5-uHx2CxvXZ6JdbkBg","3":200,"4":200},"3":{"1":"Underground Reptiles","2":"https://undergroundreptiles.com/product-category/animals/amphibians/tree-frogs/","3":"Tree Frogs Archives - Underground Reptiles","4":"","10":"NFYryMgPrFWjLY"},"5":{"1":"mxKEhURnKTFDgmp"}},{"1":{"1":"https://static.boredpanda.com/blog/wp-content/uploads/2016/11/frog-photography-tantoYensen-2-5836fb5fa3383__880.jpg","3":880,"4":646},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSD54DmGda4ORwNsiNxnRytlkNBFe4POeCfwnGP6A5dsndQ35EN","3":200,"4":146},"3":{"1":"Bored Panda","2":"https://www.boredpanda.com/frog-photography-tantoyensen/","3":"This Photographer Photographs Frogs Like You've Never Seen ...","4":"Cute Frog Photography","10":"GpxCpXhhYRfLQV"},"5":{"1":"kBgYakehSGARbAa"}},{"1":{"1":"https://www.sciencedaily.com/images/2017/09/170913193106_1_540x360.jpg","3":540,"4":359},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYc8jroyQFXBEWjaWBa0XtZCJWB1eh4Q8mphleOwt_rVftk872","3":200,"4":133},"3":{"1":"ScienceDaily","2":"https://www.sciencedaily.com/releases/2017/09/170913193106.htm","3":"Evolution of 'true frogs' defies long-held expectations of ...","4":"Ranidae family are most diverse frog ...","10":"SgOrWSoNkQjkXN"},"5":{"1":"NEnjrAUuUAJVPYY"}},{"1":{"1":"http://ichef.bbci.co.uk/wwfeatures/wm/live/1280_640/images/live/p0/4v/6s/p04v6sqx.jpg","3":1280,"4":640},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRfX2luQyVZ-zbrRFoz93CaY80yyDgBXgWTG6C-Ql7GlQbLg11M","3":200,"4":100},"3":{"1":"BBC.com","2":"http://www.bbc.com/earth/story/20170227-there-are-frogs-that-breed-high-up-in-trees","3":"BBC - Earth - There are frogs that breed high up in trees","4":"There are frogs that breed high up in trees","10":"tnfNeHaMnRjESm"},"5":{"1":"llxhwWaFRlrDOEE"}},{"1":{"1":"https://www.thelocal.fr/userdata/images/article/307e9b4f101734d3f1ed2c7ee4094e692ea7b179dbef0203206ee24ad0d7e233.jpg","3":768,"4":511},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTE8In6K644ktyYDfWI8HJsDnvZw0vFcE5nTcpa9qYL-hqFTCpQ","3":200,"4":133},"3":{"1":"The Local France","2":"https://www.thelocal.fr/20180416/why-are-dordognes-noisy-frogs-at-the-centre-of-a-bizarre-legal-battle","3":"Why are Dordogne's noisy frogs embroiled in a bizarre legal ...","4":"Why are Dordogne's noisy frogs embroiled in a bizarre legal battle?","10":"IpgQyHiQgmancc"},"5":{"1":"kJPYqQFixrMKmJp"}},{"1":{"1":"https://thumbs-prod.si-cdn.com/D8qEZnYE_JIK1U9_V6Q1igPGnhk=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/3b/6c/3b6c8ed1-90ae-4dad-a44d-8250be782a40/rayna_bell_-_litoria_revelata-040.jpg","3":800,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9MkD2sC0lqyeGsSZ_QfsvpkuFlXPF_ld0S1IecqgoECQMajtIcA","3":200,"4":149},"3":{"1":"Smithsonian Magazine","2":"https://www.smithsonianmag.com/smithsonian-institution/color-changing-marvel-tree-frogs-looking-love-180964976/","3":"The Color-Changing Marvel of Tree Frogs Looking for Love | At ...","4":"A new study sheds light on the wild world of “dynamically dichromatic”  amphibians","10":"pEaiVEpDYmLlaL"},"5":{"1":"BDEGPeAgkqWTiSV"}},{"1":{"1":"http://www.savethefrogs.com/d/amphibians/images/ghana/Leptopeles-hyloides-Ankasa-bamboo-cathedral-1-a-328.jpg","3":328,"4":246},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQP4o62qPQpPjo_pwdks06whhF_Uz4pVbxCut95cUpidmvSgxvDDg","3":200,"4":149},"3":{"1":"Save the Frogs","2":"http://www.savethefrogs.com/d/countries/ghana/frogs.html","3":"Frogs & Toads of Ghana","4":"Ghana Frogs","10":"lIquJinHveRXLW"},"5":{"1":"vylFbObXVrHbFhs"}},{"1":{"1":"https://cdn.britannica.com/s:700x450/73/100273-004-341B9A8E.jpg","3":550,"4":372},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9bFMIckxreAHguJKrulYJi39C4ZkLez2JhxY-E7JvGstqHe5uLQ","3":200,"4":135},"3":{"1":"Encyclopedia Britannica","2":"https://www.britannica.com/animal/frog","3":"Frog | amphibian | Britannica.com","4":"Blue arrow-poison frogs (Dendrobates azureus).","10":"PNVCAfaSvvWxRY"},"5":{"1":"aUlpffuPEYYpKFT"}},{"1":{"1":"https://media.wired.com/photos/59273130af95806129f51e1b/master/pass/353A-Ranitomeya-reticulata_Luke-Verburgt.jpg","3":1920,"4":1388},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQPrE-yAWvR2XWEizAmM2pY3K0Av9f17-c5QA-OwgjUSezsmMfGmw","3":200,"4":144},"3":{"1":"Wired","2":"https://www.wired.com/2016/02/frogs-are-really-cool-too-bad-humans-are-killing-them-all/","3":"Frogs Are Really Cool. Too Bad Humans Are Killing Them All ...","4":"Frogs Are Really Cool. Too Bad Humans Are Killing Them All | WIRED","10":"tSjajvqkTHwDPN"},"5":{"1":"NqjLVMLdPkGSOsB"}},{"1":{"1":"https://www.sciencenews.org/sites/default/files/2017/03/main/articles/033017_sm_glass-frog_main_free.jpg","3":860,"4":460},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRQHa3--9uCPkM0iiBenOnNDj2vO_kmQjEa3HbDBy26T7_BEwlG-Q","3":200,"4":106},"3":{"1":"Science News","2":"https://www.sciencenews.org/article/glass-frogs-moms-matter-after-all","3":"For glass frogs, moms matter after all | Science News","4":"Cochranella granulosa glass frog","10":"IcObVOyrqXnwvC"},"5":{"1":"ulDbeqrODGiydVM"}},{"1":{"1":"https://amp.businessinsider.com/images/5980f384b50ab181238b5252-750-563.jpg","3":750,"4":563},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT70yS_9h8ZASXTDmysouJ_pLldMTMXxX3roO92SCgsO0QSnlFg2g","3":200,"4":149},"3":{"1":"Business Insider","2":"https://www.businessinsider.com/xenopus-frogs-pregnancy-test-2017-8","3":"Pregnancy tests used to be African clawed frogs - Business ...","4":"frogs national xenopus laevis resource marine biological laboratory dave  mosher 0","10":"gCpaiJGcuchnym"},"5":{"1":"UTouCGNEmGWJBJi"}},{"1":{"1":"https://media.mnn.com/assets/images/2016/04/frog-head-tilted.jpg.620x0_q80_crop-smart_upscale-true.jpg","3":620,"4":414},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSNpAL5idNr74cEBBf75cRuQi7oFFcVXOAoDUB8jVGmqLdf3BdW","3":200,"4":133},"3":{"1":"Mother Nature Network","2":"https://www.mnn.com/earth-matters/animals/quiz/how-much-do-you-know-about-frogs","3":"How much do you know about frogs? | MNN - Mother Nature Network","4":"frog with head tilted","10":"mjkGEObGkpygTr"},"5":{"1":"WGNgwQbnnUmmsUU"}},{"1":{"1":"https://3c1703fe8d.site.internapcdn.net/newman/gfx/news/hires/2014/157-researchersd.jpg","3":2778,"4":1974},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS383ka-_gDmTcl5dHI4lnxq4HU69cU8zUA-NjtbYN5GUkfB6xuow","3":200,"4":142},"3":{"1":"Phys.org","2":"https://phys.org/news/2014-10-rare-bush-frog-bamboo.html","3":"Researchers discover for the first time that a rare bush frog ...","4":"Researchers discover for the first time that a rare bush frog breeds in  bamboo","10":"wMHSHquWwPWuIG"},"5":{"1":"BqpyHxyDjNlDOSR"}},{"1":{"1":"https://www.floridamuseum.ufl.edu/science/wp-content/uploads/2016/11/gree-treefrog-krysko-1frog.jpg","3":975,"4":649},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRV4hWTYfPeCxXNxv2vP0MLRuOrwGPF1dK-PXiR3GjapGlE_3w","3":200,"4":133},"3":{"1":"Florida Museum of Natural History","2":"https://www.floridamuseum.ufl.edu/science/florida-frog-calls/","3":"Florida Frog Calls – #FloridaMuseumScience","4":"","10":"RgOOcSgRawmGTr"},"5":{"1":"VAoaOdRoPyYymPe"}},{"1":{"1":"https://s.hswstatic.com/gif/hallucinogenic-frog-1.jpg","3":400,"4":267},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT811qRcXqq1PKIwHn9ctU6NOfMcp7OfHJrhniRNyrq9e6Q9LsJsg","3":200,"4":133},"3":{"1":"Animals | HowStuffWorks","2":"https://animals.howstuffworks.com/amphibians/hallucinogenic-frog.htm","3":"Are there really hallucinogenic frogs? | HowStuffWorks","4":"Ribbett. Australia wants to give cane toads the boot. See more amphibian  pictures.","10":"NNRXlXtRjYMXKr"},"5":{"1":"irnuUmaNbBDwXsa"}},{"1":{"1":"http://wildlife.org/wp-content/uploads/2015/08/SM-Salty-frogs-1-Greg-Schechter.jpg","3":3072,"4":1307},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDperTWUFzqrHIxQvZoMnbg-SzfPleA99g2_Gd60dv4YyNkc0L","3":200,"4":84},"3":{"1":"The Wildlife Society","2":"http://wildlife.org/how-frogs-cope-with-road-salt-and-brackish-water/","3":"How Frogs Cope With Road Salt and Brackish Water | THE ...","4":"An ...","10":"RRpuUmLEdTvNps"},"5":{"1":"ErJdfKSPnleMFRc"}},{"1":{"1":"https://cdn.the-scientist.com/assets/articleNo/32185/iImg/5427/1c333be1-1cd8-45a4-8840-aad851ea8123-640treefrog.jpg","3":638,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTuJIm3zsoZMJwIQI-kFWptxRxddJGx5bGJkqs-0S2xYUL0F4DtCg","3":200,"4":113},"3":{"1":"The Scientist Magazine","2":"https://www.the-scientist.com/daily-news/how-traffic-noise-affects-tree-frogs-32185","3":"How Traffic Noise Affects Tree Frogs | The Scientist Magazine®","4":"Hyla arboreaCOURTESY OF THIERRY ...","10":"jaITNMFTLHjCDB"},"5":{"1":"rDVROHvmnyPnAQf"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Anoures.jpg/220px-Anoures.jpg","3":220,"4":319},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSB5OFn6zL-xT4LUPF21-aA9iwNV-a6ZpxbW0DL6Tr5U5pnIfFJ","3":137,"4":200},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Frog","3":"Frog - Wikipedia","4":"Various types of frogs.","10":"TDygJSxFsEHNNb"},"5":{"1":"XeraFUqFJNRCGIG"}},{"1":{"1":"http://www.savethefrogs.com/d/amphibians/images/Litoria-Fallax-Eastern-Sedge-Frog-ds-a.jpg","3":328,"4":254},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQWVy0kfPnm_-zROsm1XFnA7EKepvf0lSJ9iTh1LJyU8P_vkTj6","3":200,"4":154},"3":{"1":"Save the Frogs","2":"http://www.savethefrogs.com/d/threats/index.html","3":"Threats to Frogs","4":"Litoria fallax - Eastern Sedge Frog","10":"vGsIryEramLpBD"},"5":{"1":"odudiYsEAYmertr"}},{"1":{"1":"https://www.pca.state.mn.us/sites/default/files/greenfrog-rclamilg.jpg","3":250,"4":192},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS_jrIVEN0NHjruuGWXQYtwz-mIZryI5Ohu5liTYZeGwick0yoetA","3":200,"4":153},"3":{"1":"Minnesota Pollution Control Agency","2":"https://www.pca.state.mn.us/living-green/frogs-minnesota","3":"Frogs of Minnesota | Minnesota Pollution Control Agency","4":"Green frog (Rana clamitans) Listen to the call","10":"DtexviIWEYAioL"},"5":{"1":"iymrjxsAarRNyqK"}},{"1":{"1":"https://static01.nyt.com/images/2018/04/03/science/30Zimmer-1/30Zimmer-1-articleLarge.jpg?quality=75&auto=webp&disable=upscale","3":600,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRg48ytBu6zAYEm6Vak59KHCkczIts4UjZpDIXON8Xz04WiIy8P","3":200,"4":149},"3":{"1":"The New York Times","2":"https://www.nytimes.com/2018/03/29/science/frog-species-panama-fungus-rebound.html","3":"A Few Species of Frogs That Vanished May Be on the Rebound ...","4":"Image","10":"WFnybfuMiBvtbq"},"5":{"1":"iVFcPipApAbDUnM"}},{"1":{"1":"https://www.sciencedaily.com/images/2015/01/150120084545_1_540x360.jpg","3":359,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS1u35g96pNmfdVInRYeSr1hxsC0JW_xWRn8nL1BFP69W_nA8fP4Q","3":199,"4":200},"3":{"1":"ScienceDaily","2":"https://www.sciencedaily.com/releases/2015/01/150120084545.htm","3":"The seeing power of frogs: Frogs can detect single photons of ...","4":"Red-eye frog ...","10":"DwLdSrCqGJPnQn"},"5":{"1":"avpQCfRTQPjQuRb"}},{"1":{"1":"https://www.popsci.com/sites/popsci.com/files/styles/1000_1x_/public/images/2017/09/rayna_bell_-_dscn3184_0.jpg?itok=uD3aH5n_&fc=50,50","3":1000,"4":750},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSg8gtykqCthu94tEl1-S2BXWKLDVVCEHHQ879Ct2iEOYFpIG0","3":200,"4":149},"3":{"1":"Popular Science","2":"https://www.popsci.com/frogs-change-color-orgies","3":"These frogs might change color to avoid confusion during ...","4":"A frog couple has sex. The male is yellow.","10":"bclaQHSsaIoFaW"},"5":{"1":"fkWsCbMSUeGMUvu"}},{"1":{"1":"https://wonderopolis.org/wp-content/uploads/2017/10/Frogs_and_Toadsdreamstime_xl_30843151.jpg","3":900,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTbNlkw_129iVOBFK3N8-duInY1cCBeLYxvsmIn4usa1b99FGo","3":200,"4":133},"3":{"1":"Wonderopolis","2":"https://wonderopolis.org/wonder/are-frogs-and-toads-the-same","3":"Are Frogs and Toads the Same? | Wonderopolis","4":"Wonder Contributors","10":"eySSflmKbfKRMG"},"5":{"1":"uBpfcLuQxLKgIYx"}},{"1":{"1":"https://www.sciencenewsforstudents.org/sites/default/files/2016/06/main/articles/060116_leopardfrog_main_SNS.jpg","3":860,"4":460},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSxVLjF4xOVgAdqZcHIVYLF_0sPJaVH5N0AhcHI7or9jdNTDVYA","3":200,"4":106},"3":{"1":"Science News for Students","2":"https://www.sciencenewsforstudents.org/article/why-some-frogs-can-survive-killer-fungal-disease","3":"Why some frogs can survive killer fungal disease | Science ...","4":"Leopard frog","10":"tAPGLJWjpeNNgF"},"5":{"1":"gjqakrYgfmpSEWa"}},{"1":{"1":"http://www.torontozoo.com/adoptapond/guide_images/Green%20Frog.jpg","3":720,"4":480},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSeqz9-u1RXG1QaZUZiCafyguHmln-WNtZhUu4kIx1ub3wlU-3uCg","3":200,"4":133},"3":{"1":"Toronto Zoo | Adopt A Pond | SGuides","2":"http://www.torontozoo.com/adoptapond/frogs.asp?fr=11","3":"Toronto Zoo | Adopt A Pond | SGuides","4":"Green Frog","10":"wgFqDwNcxpBuhX"},"5":{"1":"AvVIBNnUgajVBsE"}},{"1":{"1":"https://defenders.org/sites/default/files/styles/homepage-feature-2015/public/frogs_visser-ruurd.png?itok=gAa6MAqt","3":960,"4":480},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgMktAwGtDGr628lxn6umXvObH5FhK9gr74bSbP9WvTt7-_5ka","3":200,"4":100},"3":{"1":"Defenders of Wildlife","2":"https://defenders.org/frogs/basic-facts","3":"Frogs | Basic Facts About Frogs | Defenders of Wildlife","4":"Frogs","10":"lyJyYSIWtJWjMf"},"5":{"1":"wFayTaBYdFYafFh"}},{"1":{"1":"https://news.nationalgeographic.com/content/dam/news/2017/04/27/frog-gallery/01-frog-day-gallery.ngsversion.1493410969588.adapt.1900.1.jpg","3":1900,"4":1261},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTDEHb9huCNeicJ_22gT2yp5zapE5T0VTrh2N-Cvf1kRRpEzHyFfg","3":200,"4":132},"3":{"1":"Latest Stories - National Geographic","2":"https://news.nationalgeographic.com/2017/04/frog-photos-save-frog-day/","3":"13 Gorgeous Pictures Remind Us Why Frogs Need Our Help","4":"","10":"IjNOCPUPHhlhve"},"5":{"1":"bRNCLBJoeoEkhIm"}},{"1":{"1":"https://i.ytimg.com/vi/Fa_I68L_APY/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvaHJGb7GygNJu7t6mgtQ-IKRVRvpfHsGsObxrS2Cb_5YsBLzM","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=Fa_I68L_APY","3":"World's Most Famous Frog!","4":"","10":"bbcjDPvxYExfaL"},"5":{"1":"eTlMaEBGhKXNQsB"},"7":{"1":{"11":{"1":"World's Most Famous Frog!","2":"Please SUBSCRIBE - http://bit.ly/BWchannel Watch More -  http://bit.ly/BTpoisonfrog On this episode of Breaking Trail, Coyote tracks  down Costa Rica’s most ic...","3":"7:58","4":"2622194","5":"1484006400000","6":"Brave Wilderness","7":"56906","8":"5741"}}}},{"1":{"1":"https://www.rbg.ca/image/events/frogs/frogslide-mexicanleaf.jpg","3":980,"4":480},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTi4ERHFfdC_UtsiGGg5on4mesPQfYLrVgvuSi5LjGGXvfWVcWR","3":200,"4":97},"3":{"1":"Royal Botanical Gardens","2":"https://www.rbg.ca/frogs","3":"Frogs - Royal Botanical Gardens","4":"Mexican Leaf Frog","10":"ePEhpmgjFyRaVL"},"5":{"1":"EQwwCqjQQqUeyUu"}},{"1":{"1":"https://cosmos-images2.imgix.net/file/spina/photo/11978/170925-Frog-Full.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835","3":835,"4":555},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSk7YieHJL3q75pri3jgdNO0li65jlUTlHLBqeo_OnMd8CWkdYxJg","3":200,"4":133},"3":{"1":"Cosmos Magazine","2":"https://cosmosmagazine.com/biology/why-poisonous-frogs-don-t-croak","3":"Why poisonous frogs don't croak | Cosmos","4":"The little devil poison frog is immune to its own toxins.","10":"UeiEkghhVkMXKs"},"5":{"1":"WUoHoDDlhgfBtrO"}},{"1":{"1":"http://www.frogsofborneo.org/images/Header%20Frontpage.jpg","3":2000,"4":1145},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSiMg-d9JBxdtDIF6MccrQmpv2DVFycXK7-vjF0S9Jcvqi_KTom","3":200,"4":114},"3":{"2":"http://www.frogsofborneo.org/","3":"Frogs of Borneo","4":"Bornean Families","10":"CRMKIDvekmMVLT"},"5":{"1":"rlfRjDeDKVSjJIx"}},{"1":{"1":"https://kids.nationalgeographic.com/content/dam/kids/photos/articles/Other%20Explore%20Photos/R-Z/Wacky%20Weekend/Frogs/ww-frogs-budgetts-tile.ngsversion.1461604295186.adapt.1900.1.jpg","3":1900,"4":1068},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhVTWE1uxmNxemqwwuhCBflDlg12w5EV8tcdnWZdU3ml1lLe2ixw","3":200,"4":112},"3":{"1":"National Geographic Kids","2":"https://kids.nationalgeographic.com/explore/wacky-weekend/frogs/","3":"Wacky Weekend: Frogs","4":"","10":"PpMNVnlqTuNRvy"},"5":{"1":"ygHfQinPsVhlRDU"}},{"1":{"1":"https://www.swarovski.com/medias/?context=bWFzdGVyfHJvb3R8NDkzMzh8aW1hZ2UvanBlZ3xoZTIvaDllLzg4NDg0NzA4MDI0NjIuanBnfGYzMGE4MTI1NjkxZTYzYjc2OTEyZmFiMjIzODM5OWU5NjhlZWI5ZTA3ZWViOTI2MzBkNWMwZWU3OGRjMWQyNmU","3":607,"4":607},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBrs02ONOspqXB32cicZkYZB3Yp4IrYQxI3K_U8le5cuHrZYV","3":200,"4":200},"3":{"1":"Swarovski","2":"https://www.swarovski.com/en-AR/p-5136807/Frogs/","3":"Frogs by SWAROVSKI","4":"Frogs - Swarovski, 5136807","10":"PsQJRbaRKxpryy"},"5":{"1":"PAPVKUeteEYVjso"},"7":{"1":{"10":{"3":"Frogs by SWAROVSKI","4":"Swarovski","5":"Honoring the unique flora and fauna of the rainforest, this pair of  Swarovski frogs sparkles in a combination of vibrant crystal colors. The  frogs can ...","7":19900.0,"8":"ARS"}}}},{"1":{"1":"https://jr.brainpop.com/science/animals/frogs/screenshot_1.png","3":600,"4":460},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS0XWJGUpxOeC3j6b7az5dv7y0bWOgXV-29SwL2Hw-LIudZX5F0bA","3":200,"4":153},"3":{"1":"BrainPOP","2":"https://jr.brainpop.com/science/animals/frogs/","3":"Frogs - BrainPOP Jr.","4":"Whoops! Looks like we had a problem playing your video. Refresh the page to  try again.","10":"IFDBtpyVQMwWrO"},"5":{"1":"biORwvUFemtsbpV"}},{"1":{"1":"https://static01.nyt.com/images/2017/02/02/science/sciencetake-frogs-video/sciencetake-frogs-video-superJumbo.jpg","3":2048,"4":1365},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRpdhQxRxS3laHzJhYtcNQxezg_oIYGxbjPLI5SwmI5k5oWiJdUNQ","3":200,"4":133},"3":{"1":"The New York Times","2":"http://www.nytimes.com/topic/subject/frogs","3":"Frogs - The New York Times","4":"The Power of Frog Spit","10":"nFlfdHamKlFCET"},"5":{"1":"IgOMSaMcvdDJvfD"}},{"1":{"1":"https://www.rspb.org.uk/globalassets/images/birds-and-wildlife/non-bird-species-illustrations/common-frog_1200x675.jpg?preset=landscape_mobile","3":768,"4":432},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQneCrWRM20xTxTsyRjgncmLD4_d5dRnsVDFUzF7C5cE8Ul2_Uu","3":200,"4":112},"3":{"1":"RSPB","2":"https://www.rspb.org.uk/birds-and-wildlife/wildlife-guides/other-garden-wildlife/amphibians-and-reptiles/common-frog/","3":"Common Frog | What Do Frogs Eat & other Frog Facts - The RSPB","4":"Common frog","10":"hWliTCrvAjyrCm"},"5":{"1":"pfaqPXfSPlHMJWY"}},{"1":{"1":"https://i.kinja-img.com/gawker-media/image/upload/tgfdtzodvqb4egv9au6w","3":1152,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTv97ml3Gr9qxutD333q_xu2TyeqQHbRs07ex_A6ypKtsTvEefD","3":200,"4":124},"3":{"1":"ClickVentures - ClickHole","2":"https://clickventures.clickhole.com/acquire-frogs-1825124396","3":"Acquire Frogs","4":"","10":"MFsYykfcUNjRcn"},"5":{"1":"sRHvGnXMaNcuJNS"}},{"1":{"1":"https://news.utexas.edu/sites/default/files/styles/news_article_main_image/public/photos/epipedobates-anthonyi_872_830.jpg?itok=oW0C6k-o","3":1660,"4":996},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStpr6bG1jDp0RgcXcV4_ysG8p8S64TGZ5-2XDk9wz-Vlwzo0s0kg","3":200,"4":120},"3":{"1":"UT News - The University of Texas at Austin","2":"https://news.utexas.edu/2017/09/21/why-poison-frogs-don-t-poison-themselves","3":"Why Poison Frogs Don't Poison Themselves | UT News | The ...","4":"Phantasmal Poison Frog (Epipedobates anthonyi)","10":"xSqSEpkCdmrHPP"},"5":{"1":"ieaUIKHjtRyVtQS"}},{"1":{"1":"https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ftimedotcom.files.wordpress.com%2F2017%2F05%2Ffrog2.jpg&w=1600&q=70","3":1512,"4":1265},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRkJWTXmEQHgBuRrjqaVc6B3ylbTfQY1Pt6XV0OI-f4TOfeb-FE","3":200,"4":167},"3":{"1":"Time","2":"http://time.com/4798314/transparent-frog-new-species-amazon/","3":"Transparent Frog: Scientists Discover New Species in Amazon ...","4":"Have a look: The transparent Hyalinobatrachium yaku frog","10":"dgiUNFlNKNOccA"},"5":{"1":"XXwbLBnCIlGQyvr"}},{"1":{"1":"https://cdn.the-scientist.com/assets/articleNo/30156/iImg/1051/frogs.jpg","3":640,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_hM5VsgXC_2i3qjylFXbM7To9vXuHsrIdrF8ToPAVfj1ddXD4AQ","3":200,"4":112},"3":{"1":"The Scientist Magazine","2":"https://www.the-scientist.com/features/frog-skin-yields-potent-painkillers-but-none-clinic-ready-30156","3":"Frog Skin Yields Potent Painkillers, but None Clinic Ready ...","4":"Frog Skin Yields Potent Painkillers, but None Clinic Ready | The Scientist  Magazine®","10":"ynCfIlcKdHkixo"},"5":{"1":"bhsADIhKmrvyuci"}},{"1":{"1":"https://www.sciencemag.org/sites/default/files/styles/inline__450w__no_aspect/public/frog_16x9.jpg?itok=KqXPFU6-","3":450,"4":253},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRaSIlATqbnPq12oVBUV-FewL_jEHPUauSUvsYvya4JuM1LPxyjFg","3":200,"4":112},"3":{"1":"Science","2":"http://www.sciencemag.org/news/2017/07/can-you-tell-whether-frog-excited-just-listening-its-voice","3":"Can you tell whether this frog is excited just by listening ...","4":"Can you tell whether this frog is excited just by listening to its voice?","10":"RoUBvJcSfsQsEp"},"5":{"1":"wCdnAIPTKcdsehy"}},{"1":{"1":"http://www.backyardbuddies.org.au/_assets/images/buddy-hero-images/Green-Tree-Frog-Emily-Sephton.jpg","3":1600,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBpqkRi_p8cw0r1zriKqubKg7I4407IYbBPCRcNAyLCzqCDiVo","3":200,"4":74},"3":{"1":"Backyard Buddies","2":"http://www.backyardbuddies.org.au/fact-sheets/frogs-1","3":"Frogs","4":"","10":"tCDKWOcIIqIleH"},"5":{"1":"kDcRCsbVfhmkpTF"}},{"1":{"1":"https://assets.bwbx.io/images/users/iqjWHBFdfxIU/imbdOzKpGFA8/v0/800x-1.jpg","3":800,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSkuYRypL8YpOM3Vafl6mD1qeYIlPtdEuClardhV-0iqZR4_O3F","3":200,"4":112},"3":{"1":"Bloomberg","2":"https://www.bloomberg.com/news/articles/2018-09-12/biohacker-makes-diy-mutant-frogs-and-hopes-they-don-t-croak","3":"The Biohacker Who Experimented on Himself Is Making DIY ...","4":"Illustration: Alvin Fai","10":"RXSyqHDTadRjtW"},"5":{"1":"vkPBNnHYwsnVFvv"}},{"1":{"1":"http://www.pbs.org/wnet/nature/files/2014/05/08_46MB-1000x469.jpg","3":1000,"4":469},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTmCB9eU3X3ExdbLwzLwhHxKgbu1nng-4QoHh-JT-CzBKJggJTm","3":200,"4":93},"3":{"1":"PBS","2":"http://www.pbs.org/wnet/nature/group/amphibians-reptiles/frog/","3":"Frogs | Nature | PBS","4":"Frogs are a diverse and largely carnivorous group of short-bodied, tailless  amphibians composing the ...","10":"vuYFGyiAAfkGBk"},"5":{"1":"FrKpgBDXBgIYHNt"}},{"1":{"1":"https://kids.sandiegozoo.org/sites/default/files/2017-07/animal-hero-fantasticfrogs_0.jpg","3":1020,"4":580},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBi_RE4pZgVrzGi0oOsFQ1upFnjroThpWTvvYtbIOg4WcsI1aY","3":200,"4":113},"3":{"1":"San Diego Zoo Kids","2":"https://kids.sandiegozoo.org/stories/fantastic-frogs","3":"Fantastic frogs | San Diego Zoo Kids","4":"Mossy frog","10":"WwCjiVEiYOYMUy"},"5":{"1":"CuWfmiUxmLvOvYN"}},{"1":{"1":"https://image.pennlive.com/home/penn-media/width620/img/wildaboutpa/photo/bullfrogjpg-e6472ceba9e0d463.jpg","3":504,"4":339},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRb48Qyf5Pyu7vj-WvC1637fW4gfxTu9Mj2MR-nWvHjxHHu-ZO3","3":200,"4":134},"3":{"1":"PennLive.com","2":"https://www.pennlive.com/wildaboutpa/2017/07/frogs_and_toads_of_pennsylvani.html","3":"Frogs and toads of Pennsylvania: Are there really 17 species ...","4":"bullfrog.jpg","10":"MsAdcYkHVqdUns"},"5":{"1":"avrqpgGUaxwIuwK"}},{"1":{"1":"https://www.enasco.com/medias/xenopus-frogs-categoryvideo-4.jpg?context=bWFzdGVyfGltYWdlc3w0MzgxMHxpbWFnZS9qcGVnfGltYWdlcy9oMDUvaGJkLzg3OTYyNDM0MjczNTguanBnfGUxZDEwODZhM2Y3MmE2NmU2YjQwM2FjOGE0OTMyNjEzMTZjNGZkZGYzYzI4NDI4NzQ0MDIxM2MzNzJkNWE1NjA","3":795,"4":384},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT5zCC-PVFgf7Qv21BIeSlYBvRJqkCg8ZTg9AwbDz7b4rmEClZk","3":200,"4":96},"3":{"1":"Nasco","2":"https://www.enasco.com/c/Education-Supplies/Xenopus-Frogs","3":"Xenopus Frogs | Education Supplies | Nasco","4":"Xenopus Tropicalis","10":"IaQBBwidFDPrCW"},"5":{"1":"wLjTrSuCIAbSvok"}},{"1":{"1":"https://cdn.britannica.com/s:700x450/57/22457-049-8F80A555.jpg","3":320,"4":240},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRC2g7gY5I0hlcR6Z4QhvO3In2kVjfG7bRe9zPNTsgEpAHjHMv","3":200,"4":149},"3":{"1":"Encyclopedia Britannica","2":"https://www.britannica.com/animal/frog","3":"Frog | amphibian | Britannica.com","4":"tree frog","10":"NMHkeHYhlmacxd"},"5":{"1":"yrkGEFyXWiJttwW"}},{"1":{"1":"https://cdn-images-1.medium.com/max/595/0*F57sByVPzim7oA4w.jpg","3":595,"4":335},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvKl7iN6SsOCeJ8Fll0Z02OxnR_x035trZiPcOOx5wZ-i_dhPofg","3":200,"4":112},"3":{"1":"The Economist - Medium","2":"https://medium.economist.com/hunting-for-frogs-in-the-western-ghats-270768e5bc7d","3":"Hunting for frogs in the Western Ghats – The Economist","4":"","10":"EVTOruFlqfrwql"},"5":{"1":"dCTcNXqnebIqpOA"}},{"1":{"1":"https://media.mnn.com/assets/images/2016/12/jaymi-heimbuch-_JH_1705-01.jpg","3":1500,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqEEUZzO9SD97G3OK33jGBdkLiCVlRV8EhUH8uJ3SXncnQF0v0Jw","3":200,"4":133},"3":{"1":"Mother Nature Network","2":"https://www.mnn.com/earth-matters/animals/blogs/This-why-red-eyed-tree-frogs-have-red-eyes","3":"This is why red-eyed tree frogs have red eyes | MNN - Mother ...","4":"red-eyed tree frog","10":"tXEDrMjTLTVffk"},"5":{"1":"WHNDEeEFejqccyh"}},{"1":{"1":"https://www.wettropics.gov.au/site/user-assets/mcms_cb_resized/miketrenerryyellowgianttreefroglitoriainfrafrenata-1.jpg","3":428,"4":281},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJ79-75lr0_bJHHMIlrua9-5VXZf65pz8z9hZcHW0QNDTHbN1c","3":200,"4":131},"3":{"1":"Wet Tropics Management Authority","2":"http://www.wettropics.gov.au/frogs","3":"Frogs | Wet Tropics Management Authority","4":"Frogs","10":"uRyKVOHxdXSsmk"},"5":{"1":"QbFEoXpYyrEGjJM"}},{"1":{"1":"https://www.davincisciencecenter.org/wp-content/uploads/2018/05/leaf-frogs-900x600.jpg","3":900,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRraAutITBAvNnDVw-ZMxGOdt13vfXj1aWWTi_dElmIkO0Vv4oUjg","3":200,"4":133},"3":{"1":"Da Vinci Science Center","2":"https://www.davincisciencecenter.org/frogs-and-friends/","3":"Frogs and Friends - Da Vinci Science Center - Da Vinci ...","4":"The Solomon Island leaf frog has a loud call and eats crickets. Its body  shape","10":"poKVJCxYdnKqqv"},"5":{"1":"ihBTVRWKYwlwLQD"}},{"1":{"1":"https://blog.nationalgeographic.org/wp-content/uploads/2013/11/poison-dart-frog-pumilio-defenses-s2048x1372-p.jpg","3":2048,"4":1372},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRHohSag9Y5M5cLULNwpN9CIuK3v1cXX63_cVi1lMUvMM4G8wMv","3":200,"4":134},"3":{"1":"National Geographic Blog - National Geographic Society","2":"https://blog.nationalgeographic.org/2013/11/21/poison-frogs-make-their-babies-toxic-too/","3":"Poison Frogs Make Their Babies Toxic, Too – National ...","4":"Photo of a strawberry poison dart frog in Costa Rica.","10":"JbVtKgCKdSCDpF"},"5":{"1":"HVtlNFOTShVHwPH"}},{"1":{"1":"https://australianmuseum.net.au/Uploads/Images/35550/P2060249_smll_big.jpg","3":526,"4":396},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqu0UClFqLeww4-3Kl3DtKP4QOb0I93zzpekB4vzd9VJXvAt3j","3":200,"4":150},"3":{"1":"Australian Museum","2":"https://australianmuseum.net.au/blogpost/why-do-frogs-call","3":"Why do frogs call? - Australian Museum","4":"Graceful Tree Frog","10":"SKbgJUFUnTXUSG"},"5":{"1":"UgSWbgQLclfCCww"}},{"1":{"1":"https://static.independent.co.uk/s3fs-public/thumbnails/image/2018/06/14/12/frog-pond.jpg?w968h681","3":968,"4":681},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcsVTOChE6B-9A6nmhsXu9rSwvz4PEy8nkrcC_8qfIHZWCypwJgw","3":200,"4":140},"3":{"1":"The Independent","2":"https://www.independent.co.uk/environment/frog-pesticides-female-fertility-chemicals-linuron-endangered-species-extinction-a8399401.html","3":"Pesticides could wipe out frogs by turning them female, study ...","4":"Amphibians such as this common frog could have their fertility impacted by  the widespread use of","10":"iyIAOSSBEjwOOh"},"5":{"1":"rxmnwHOufvxpBRu"}},{"1":{"1":"https://www.mashpilodge.com/wp-content/uploads/mashpi-frogs-hyloscirtus-mashpi.jpg","3":1600,"4":1067},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQQfZJvwaZ3EojQn1-eO7Mj-fLyaLONuP3lBJC3gJ_ale1CY09m3Q","3":200,"4":133},"3":{"1":"Mashpi Lodge","2":"https://www.mashpilodge.com/the-amphibians-of-mashpi-type-of-toads-and-frogs/","3":"The amphibians of Mashpi – types of toads and frogs - Mashpi ...","4":"This frog is associated with rivers and bodies water, where it can be  observed during night walks.","10":"yBLkOyCxDEKoae"},"5":{"1":"VLxvFyvAyDyKxBh"}},{"1":{"1":"http://cdn.sci-news.com/images/enlarge3/image_4673e-Red-Eyed-Tree-Frog.jpg","3":1920,"4":1407},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRV45DKX-3v_5slq83_DhC8HnJezhTby-xu984ywDIMeriPI2wj","3":200,"4":146},"3":{"1":"Sci-News.com","2":"http://www.sci-news.com/biology/frogs-see-color-extreme-darkness-04673.html","3":"Frogs Have Unique Ability to See Color in Extreme Darkness ...","4":"According to Yovanovich et al, frogs can see color in extreme darkness,  down to","10":"DGLLcwTUHTSEBJ"},"5":{"1":"YPDAQqibncYwdyG"}},{"1":{"1":"https://asset-manager.bbcchannels.com/i/2fdrc1c20e61000","3":1730,"4":510},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRcnwCzJIetuwttMZoCBzhPYpWA3Y5U8LUiYfZbdBBZBPgPK_t8Q","3":200,"4":58},"3":{"1":"BBC Earth","2":"https://www.bbcearth.com/blog/?article=how-a-pregnancy-test-caused-a-catastrophe-for-frogs","3":"How a pregnancy test caused a catastrophe for frogs | BBC Earth","4":"","10":"qdgocElyxSTqkY"},"5":{"1":"yNbKaltLjiGApAU"}},{"1":{"1":"https://i.ytimg.com/vi/nyBZqRgbds4/maxresdefault.jpg","3":1688,"4":950},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvgZ_rnKmy-LUO_bgqV09Xo7VtxrFklvrk_FR7zBsh2UaBdDX3","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=nyBZqRgbds4","3":"Deadly Poison Dart Frog?","4":"","10":"ywtsACBNNDlKbh"},"5":{"1":"hWLcNTvNTqEOHBg"},"7":{"1":{"11":{"1":"Deadly Poison Dart Frog?","2":"Please SUBSCRIBE NOW! http://bit.ly/BWchannel Watch More -  http://bit.ly/BTvinegaroon On this episode of Breaking Trail, Coyote  ventures deep into the rainfo...","3":"7:19","4":"5023010","5":"1465257600000","6":"Brave Wilderness","7":"53218","8":"6142"}}}},{"1":{"1":"https://www.popsci.com/sites/popsci.com/files/styles/1000_1x_/public/images/2017/09/beelzebufo_bw.jpg?itok=Bsceo4Tm&fc=50,50","3":1000,"4":749},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ53aSAARzQhZhCs3dXMzRax6IrlFQDBVtcUKkiwiOZGw2HwKj3PQ","3":200,"4":149},"3":{"1":"Popular Science","2":"https://www.popsci.com/beelzebufo-devil-frog-bite-force-dinosaur","3":"Giant ancient frogs might have snacked on baby dinosaurs ...","4":"beelzebufo illustration","10":"bAsGfhyeefhjIT"},"5":{"1":"hJEuyvjjMTpcYyh"}},{"1":{"1":"https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzA5NS81MjEvb3JpZ2luYWwvZnJvZy13aXRoLWJpdGUtMDEuanBn","3":660,"4":412},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqapZ9iWr9W9Oe_YbibjwU6erpILlkUc6WnnRWMMKLCA0fYUH66A","3":200,"4":124},"3":{"1":"Live Science","2":"https://www.livescience.com/60474-frog-with-powerful-bite.html","3":"Extinct Big-Mouthed Frogs May Have Dined on Dinos","4":"","10":"XaVkXuxBOQtOYM"},"5":{"1":"tGrvIFxeXtnParj"}},{"1":{"1":"http://www.cellphonetaskforce.org/wp-content/uploads/2012/01/frog-left.jpg","3":400,"4":349},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2wSIPot_nLb4yZwcoRXUiaxf0IZIiUnyQL_w21k0GOS7FvX4h6A","3":200,"4":175},"3":{"1":"Cellular Phone Task Force","2":"https://www.cellphonetaskforce.org/frogs/","3":"FROGS • Cellular Phone Task Force","4":"ALL ARTICLES BY ALFONSO BALMORI · Frog","10":"LBmFoLPUBwrHWV"},"5":{"1":"UTIlnIJacMSxMmw"}},{"1":{"1":"https://www.irishtimes.com/polopoly_fs/1.2197035.1430491144!/image/image.jpg_gen/derivatives/box_620_330/image.jpg","3":620,"4":330},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSlpk8viG1gD-hI0-Ibjct-tGd0wZwqyl_AHnL8kLDa0O1gFh0F","3":200,"4":106},"3":{"1":"The Irish Times","2":"https://www.irishtimes.com/news/science/toxic-frogs-how-do-they-make-their-poison-1.2197039","3":"Toxic frogs: how do they make their poison?","4":"A Sira poison frog (Ranitomeya sirensis)","10":"uuLugouUGykRXY"},"5":{"1":"enbGNsfFaLrpfDV"}},{"1":{"1":"https://www.environment.nsw.gov.au/-/media/OEH/Corporate-Site/Topics/Animals-and-plants/Native-animals/eastern-dwarf-tree-frog-litoria-fallax-109029.jpg","3":690,"4":580},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8eSPAd8tNxrrC1QIH_M16-iew--LDC-62tRpFqYwRCM1gFFpdoA","3":200,"4":168},"3":{"1":"Office of Environment and Heritage - NSW Government","2":"https://www.environment.nsw.gov.au/topics/water/wetlands/plants-and-animals-in-wetlands/frogs","3":"Frogs in wetlands | NSW Environment & Heritage","4":"","10":"xgkwsnPjHadhee"},"5":{"1":"YloQyjvnXVxIxkp"}},{"1":{"1":"https://media.treehugger.com/assets/images/2018/05/golden_poison_dart_frog_photo.jpg.1200x0_q70_crop-smart.jpg","3":1200,"4":805},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSVzxce_y_9aBwPULkVsS581ldwa8toZ9uCPttXL-0Jhma2NKRm","3":200,"4":134},"3":{"1":"TreeHugger","2":"https://www.treehugger.com/slideshows/natural-sciences/16-beautiful-deadly-frogs/","3":"16 beautiful but deadly frogs | TreeHugger","4":"golden poison dart frog photo","10":"uwGepFKTYKyqLa"},"5":{"1":"SbDWopSVpGkxKFO"}},{"1":{"1":"https://www.mashpilodge.com/wp-content/uploads/mashpi-frogs-hyalinobatrachium-aureoguttatum.jpg","3":1600,"4":1273},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTfXZMfK9HGzYMUdGrrqmycQmI19-C_Dfsf_oYEkLSqx60K3UAG","3":200,"4":158},"3":{"1":"Mashpi Lodge","2":"https://www.mashpilodge.com/the-amphibians-of-mashpi-type-of-toads-and-frogs/","3":"The amphibians of Mashpi – types of toads and frogs - Mashpi ...","4":"Tree frogs (Hylidae)","10":"RmpLINVYskvAOi"},"5":{"1":"cUedHTGKOviDEvO"}},{"1":{"1":"https://www.crees-manu.org/wp-content/uploads/2017/05/cochranella-nola-glass-frog-eilidh-munro-peruvian-amazon-crees-foundation-research-sustainability5.jpg","3":1200,"4":800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2Ox9uBF6dmqIdJl96WhYixhJ4euA2Kdm15kqKSyDMQ1QU1BhG2A","3":200,"4":133},"3":{"1":"Crees Manu","2":"https://www.crees-manu.org/why-are-glass-frogs-transparent-cochranella-nola/","3":"Glass frogs: their weapon and weakness","4":"A glass frog with round, sticky toe pads blends into a leaf | Image ©  Eilidh Munro","10":"DnmtNUAAWptehN"},"5":{"1":"vwoBwiimxGbHhQq"}},{"1":{"1":"http://www.savethefrogs.com/d/day/images/icon-STF-Day-Last-Saturday-328.jpg","3":328,"4":246},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRoZ47SU0mt_tmoty9q6RwrdNkUHet4AofB4IM97KD1p1ORBuNC","3":200,"4":149},"3":{"1":"Save the Frogs","2":"http://www.savethefrogs.com/d/day/index.html","3":"Save The Frogs Day - April 29, 2017","4":"","10":"VQgobmBEaiwSSY"},"5":{"1":"sCWgepsdcGGKheQ"}},{"1":{"1":"https://smhttp-ssl-52271.nexcesscdn.net/media/catalog/product/w/h/white_s_tree_frogs_7.jpg","3":1797,"4":1789},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3eXxwGn2yYty-WrFBnJF6Dfd4PBj9ykuWY5SgTthzATQ6PFZKgg","3":200,"4":199},"3":{"1":"Josh's Frogs","2":"http://www.joshsfrogs.com/white-s-tree-frog-captive-bred.html","3":"Blue Phase White's Tree Frog - Litoria caerulea (CBP)- $34.99 Only 5 left  Quantity Available: 5","4":"Blue Phase White's Tree Frog - Litoria caerulea (CBP) | Josh's Frogs","10":"rtPYdQKSKLIcIU"},"5":{"1":"AQxFvMDWWwwKMPL"},"7":{"1":{"10":{"3":"Blue Phase White's Tree Frog - Litoria caerulea (CBP)- $34.99 Only 5 left  Quantity Available: 5","5":"White's Tree Frog (Captive Bred) - Litoria caerulea","6":true,"7":34.9900016784668,"8":"USD"}}}},{"1":{"1":"https://www.futurity.org/wp/wp-content/uploads/2016/07/mating_frogs2_1600-770x440.jpg","3":770,"4":440},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBtcy-7M_1t5dx5nDND5tHuc2f1Bzv7Xxx020ax10cOtifp1hK","3":200,"4":114},"3":{"1":"Futurity.org","2":"https://www.futurity.org/frogs-mating-land-1212492-2/","3":"Some frogs mate on land to avoid a 'breeding frenzy' - Futurity","4":"","10":"FsAorQNLSeMLwS"},"5":{"1":"YbmpWttSsocNiVp"}},{"1":{"1":"https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/froghed.png?itok=Bi4CHog0&resize=1100x1100","3":1100,"4":739},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmY0H3CbzQT8mOLU0YUllEo-UFmUxxcAFPYm6vjsT_4dQOyymJ","3":200,"4":134},"3":{"1":"Mental Floss","2":"http://mentalfloss.com/article/71568/hawaiis-big-island-overrun-loud-frogs-puerto-rico","3":"Hawaii's Big Island Is Overrun With Loud Frogs From Puerto ...","4":"Hawaii's Big Island Is Overrun With Loud Frogs From Puerto Rico","10":"xseKINCUlyrvvk"},"5":{"1":"EETLpMYcyuUJiNf"}},{"1":{"1":"https://defenders.org/sites/default/files/frog-kevin-clark-dpc.jpg","3":498,"4":272},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSdlp5WACg_U6DCIeigBfLXDLqop9Q9zgib8dM8phjv7P9jc4xywA","3":200,"4":109},"3":{"1":"Defenders of Wildlife","2":"https://defenders.org/frogs/basic-facts","3":"Frogs | Basic Facts About Frogs | Defenders of Wildlife","4":"","10":"sbpFxFBQDgGtnc"},"5":{"1":"skuSpTbIYMWIUMF"}},{"1":{"1":"https://pmdvod.nationalgeographic.com/NG_Video/66/327/170127-news-finding-frogs-original-edit-vin_640x360_866906691953.jpg","3":640,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS5q2Gz_zZ4yGCE03P3_UwddQwRNY49y2CuKKlDvMG4j08DQvAqQw","3":200,"4":112},"3":{"1":"National Geographic","2":"https://video.nationalgeographic.com/video/news/170127-news-finding-frogs-original-edit-vin","3":"Tracking Frogs In the Amazon Rain Forest","4":"","10":"FuwxHswpnLfGeI"},"5":{"1":"uKfhwUXcIhoogNT"}},{"1":{"1":"http://www.aquariumofpacific.org/images/made/images/slideshow/frogs_slideshow_banner_940x260_940_260_85shar-70-.5-5.jpg","3":940,"4":260},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTvWwjH2RxiLhhzaYnK9ou-2d84Hx90uK4SvYfOQ5eMCF8cCcEK8g","3":200,"4":55},"3":{"1":"Aquarium of the Pacific","2":"http://www.aquariumofpacific.org/exhibits/frogs","3":"Aquarium of the Pacific | Frogs: Dazzling & Disappearing ...","4":"FROGS: Dazzling and Disappearing","10":"pkqLeJeLmKVNPF"},"5":{"1":"HTqRRDiwKRWWKBN"}},{"1":{"1":"https://media.npr.org/assets/img/2017/01/31/frog-promo-1d3cdbeae91022c34fc659ad35ec677db5fb477f-s800-c85.jpg","3":800,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRrh_0JT1Hmrrmk3TG2UQOs4tvHlayNaoSV_F6kCzWorG_Az374","3":200,"4":149},"3":{"1":"NPR","2":"https://www.npr.org/sections/thetwo-way/2017/01/31/512622260/to-catch-prey-frogs-turn-to-sticky-spit","3":"To Catch Prey, Frogs Turn To Sticky Spit : The Two-Way : NPR","4":"Enlarge this image","10":"pdqSoGRTEjggYa"},"5":{"1":"VsMstoapUTjNyhP"}},{"1":{"1":"https://www.thesprucepets.com/thmb/mBbnO3P3iy42LYw40qiqHrw7y6M=/450x0/filters:no_upscale():max_bytes(150000):strip_icc()/GettyImages-175174320-581251b65f9b58564ccaffe2.jpg","3":450,"4":338},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgO-9VaUig5kL576jezP40Xe6p85j65n3RCkuY6y3Wzu7P7pBw","3":200,"4":149},"3":{"1":"The Spruce Pets","2":"https://www.thesprucepets.com/whites-tree-frog-1236816","3":"A Guide to Caring for Pet White's Tree Frogs","4":"White's Tree Frogs' Behavior and Temperament","10":"JMVRbqkbIIvjsk"},"5":{"1":"CouNEYfSeOArmVa"}},{"1":{"1":"http://ichef.bbci.co.uk/wwfeatures/wm/live/1280_640/images/live/p0/2d/z3/p02dz3cy.jpg","3":1280,"4":640},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR0-DmARCSCVbR2JmafaUUp2xKyuJbYqxkvUi5BYaCiCQ6Y3gBa","3":200,"4":100},"3":{"1":"BBC.com","2":"http://www.bbc.com/earth/story/20141210-gorgeous-new-frogs-found-in-india","3":"BBC - Earth - Nine beautiful new frogs found in India's ...","4":"Nine beautiful new frogs found in India's Western Ghats","10":"olXkoxuJEnONJo"},"5":{"1":"XwtKwbtqWryTOGk"}},{"1":{"1":"https://3c1703fe8d.site.internapcdn.net/newman/gfx/news/2018/woodfrogsno1.jpg","3":800,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaXimX_N6UETTMd8m_L0fNt23keTeateEaRjOtZ5Jf4UyOTKxS","3":200,"4":149},"3":{"1":"Phys.org","2":"https://phys.org/news/2018-05-wood-frogs-option-pee-winter.html","3":"Wood frogs' No. 1 option: Hold in pee all winter to survive","4":"","10":"CEqxlvQHXVHXVa"},"5":{"1":"bVFQHcQuFFJXjXe"}},{"1":{"1":"https://www.radionz.co.nz/assets/news_crops/51939/eight_col_Green_and_golden_bell_frog_-_Paul_Schilov__DOC.jpg?1518755893","3":720,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRArRLV-ZPjCLU1LlLyxwL2Qg_gq32A_qk1H6q2qZfHwyFFkCVoBw","3":200,"4":124},"3":{"1":"Radio NZ","2":"https://www.radionz.co.nz/news/national/350590/screeching-frogs-no-music-to-papamoa-s-ears","3":"Screeching frogs no music to Papamoa's ears | RNZ News","4":"Green and gold bell frogs: delightful to some; less so to others","10":"lmMkugWXrTFWkI"},"5":{"1":"vCKvENJeDtssMYw"}},{"1":{"1":"https://static1.squarespace.com/static/56648ab9e4b08333d1fdda0d/t/59d2de38a803bbf1d1a6c600/1506992166743/green_and_mink_CES.jpg?format=750w","3":750,"4":322},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTDg-7IY9-O3b-eFzg5_UFgYlhu9ZZVGJk09Hbyjv9B2y3TffT","3":200,"4":85},"3":{"1":"Field Ecology","2":"https://www.fieldecology.com/blog/a-case-of-two-confusing-frogs","3":"Head to Head: A Case of Two Confusing Frogs — Field Ecology","4":"Left: Green frog ( Lithobates clamitans ). Right: Mink Frog ( Lithobates  septentrionalis","10":"pUVUOdaTRwOyjh"},"5":{"1":"yHjTdyQroDgCWdN"}},{"1":{"1":"http://www.ipcc.ie/wp/wp-content/uploads/2012/11/bogfrog1.jpg","3":432,"4":324},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdh7xGlfYKIZZoIX39opV4q6g3zMhcrxSKXDxXKhJM8mdHukTvYw","3":200,"4":149},"3":{"1":"Irish Peatland Conservation Council","2":"http://www.ipcc.ie/a-to-z-peatlands/frogs/","3":"Frog Factsheet - Irish Peatland Conservation Council ...","4":"Common Frog (Rana temporaria) in Lodge Bog, Co. Kildare","10":"raWUPnKvHoPLse"},"5":{"1":"wcXpPtnYsGdoKJF"}},{"1":{"1":"https://www.sciencedaily.com/images/2017/11/171129090421_1_540x360.jpg","3":536,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvlee0GkpwWYEUJKQoGPFpk2EG5FhGdkJFgd2H-zeYSNERweOS9A","3":200,"4":134},"3":{"1":"ScienceDaily","2":"https://www.sciencedaily.com/releases/2017/11/171129090421.htm","3":"Invasive frogs give invasive birds a boost in Hawaii ...","4":"Coquis ...","10":"KqBADfyUpcYQqH"},"5":{"1":"rBVhEPdGgtpfabn"}},{"1":{"1":"https://thumbs-prod.si-cdn.com/_zguUogCQ0DkXMlu0ktSFESkTJI=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/66/45/6645520f-0f24-4eb7-a788-4ca9ec2f61ed/14-fun-facts-about-frogs-550-419.jpg","3":550,"4":419},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQX1FgR9O8odOodFbUAzW-aIA9CrePB8C3WUy472Xlyta32Z5VN","3":200,"4":152},"3":{"1":"Smithsonian Magazine","2":"https://www.smithsonianmag.com/science-nature/14-fun-facts-about-frogs-180947089/","3":"14 Fun Facts About Frogs | Science | Smithsonian","4":"#4: When Darwin's frog tadpoles hatch, a male frog swallows the tadpoles","10":"RjFrolyMuvCBYP"},"5":{"1":"wEciuiYICEKAObu"}},{"1":{"1":"https://www.savethefrogs.com/images/events/day/2018/icon-save-the-frogs-day-2018-official-550.jpg","3":550,"4":413},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRibUOmBWEy-Cr0uMqu0tZT6s9ORQC2xzbGIgMASssmk7I_5QfV","3":200,"4":149},"3":{"2":"https://www.savethefrogs.com/","3":"SAVE THE FROGS! - Home","4":"icon save the frogs day 2018 official 550","10":"tYUCavGVyiNQiH"},"5":{"1":"UpPaLeYDytuQxjc"}},{"1":{"1":"https://www.environment.nsw.gov.au/-/media/OEH/Corporate-Site/Topics/Water/Wetlands/alpine-tree-frog-litoria-verreauxii-alpina-109924.jpg?h=585&w=810&hash=89D07E2F6959476D1F9FA0F15848FBC38932D6B4","3":810,"4":585},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRl84qjRzDxuAWE5CW28jJmJHKst8vnd-WBF8jZhP-xrNLaj3FV","3":200,"4":144},"3":{"1":"Office of Environment and Heritage - NSW Government","2":"https://www.environment.nsw.gov.au/topics/water/wetlands/plants-and-animals-in-wetlands/frogs","3":"Frogs in wetlands | NSW Environment & Heritage","4":"Alpine tree frog (Litoria verreauxii alpina) Photo: / Dr Dave Hunter","10":"NjrkvJayacyTXP"},"5":{"1":"BQliixBjqTljksX"}},{"1":{"1":"https://advancedtissue.com/wp-content/uploads/wound-healing-with-frog-skin.jpg","3":357,"4":242},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLyhCAwXxFitHayeYypMi2h03p7e0uAyUt7qVkb7HFXnjrVHnm","3":200,"4":135},"3":{"1":"Advanced Tissue","2":"https://advancedtissue.com/2015/07/frogs-and-wound-healing-whats-the-connection/","3":"Frogs and Wound Healing: What's the Connection?","4":"","10":"eQwjeANbJEgnpN"},"5":{"1":"JRXTEKjTTNmhMWe"}},{"1":{"1":"https://www.earthrangers.com/content/wildwire/green_frog_in_lake.jpg","3":640,"4":427},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJKWWjU37-8POn1JDoz-F-YfCeTdS1K6CPB9XEzia2N3a9zt3O","3":200,"4":133},"3":{"1":"Earth Rangers","2":"https://www.earthrangers.com/wildwire/omg_animals/whats-so-great-about-frogs/","3":"What's So Great About Frogs? | Earth Rangers Wild Wire Blog","4":"What's So Great About Frogs?","10":"wLPhaSrclSwRIR"},"5":{"1":"fmuLWTTSNMbcpig"}},{"1":{"1":"http://www.pbs.org/wnet/nature/files/2014/06/frog-interactive.jpg","3":935,"4":526},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcA8Iblt3ZgEQXiWQnGBqtiKMf8hZFf9CBYZQZSlztYk9-76bscA","3":200,"4":112},"3":{"1":"PBS","2":"http://www.pbs.org/wnet/nature/fabulous-frogs/8904/","3":"Fabulous Frogs | About | Nature | PBS","4":"Attenborough's Family of Fabulous Frogs","10":"BeRwlXHEGexsjP"},"5":{"1":"rIBinmesmIPwajF"}},{"1":{"1":"https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&h=350","3":527,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTw8Du8Ux7DmwbCFXbOkl-jyZ31neHXZPFLFNmLwThLTfd52sRK7g","3":200,"4":132},"3":{"1":"Pexels","2":"https://www.pexels.com/search/cat/","3":"446 Adorable Cat Pictures · Pexels · Free Stock Photos","4":"Grey and White Short Fur Cat","10":"TREAroYWuwFPbe"},"5":{"1":"kUtiOrdImbWFUov"}},{"1":{"1":"https://images.pexels.com/photos/617278/pexels-photo-617278.jpeg?auto=compress&cs=tinysrgb&h=350","3":528,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyvCOVHlpY5k9zMZYVgTZ3UrMBZcwRgkOFnmUuo80Ik7epQb7OgQ","3":200,"4":132},"3":{"1":"Pexels","2":"https://www.pexels.com/search/cat/","3":"446 Adorable Cat Pictures · Pexels · Free Stock Photos","4":"","10":"TsqdXdqOmrGDFt"},"5":{"1":"xStLTJfYSAJEtuf"}},{"1":{"1":"http://www.catster.com/wp-content/uploads/2017/08/A-fluffy-cat-looking-funny-surprised-or-concerned.jpg","3":600,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYQo_3zC1FpgMmtbD0IDEVKiCMZ8H3SfbtBTOn42O8_fIj4fe8xQ","3":200,"4":133},"3":{"1":"Catster","2":"https://www.catster.com/cat-behavior/what-is-cat-flehmen-response","3":"What is a Cat Flehmen Response? - Catster","4":"","10":"PqnOEAEekXfkks"},"5":{"1":"KHGxdUcqYOSnNFb"}},{"1":{"1":"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&h=350","3":525,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTvSeOYRVExl062WjSramBG1P_LA-KUmQNFBD7s-Kqagn1XvJZn","3":200,"4":133},"3":{"1":"Pexels","2":"https://www.pexels.com/search/cat/","3":"446 Adorable Cat Pictures · Pexels · Free Stock Photos","4":"Free stock photo of animal, pet, cat, adorable","10":"NNeOBwdWCVthYB"},"5":{"1":"kigYrKahGHXFYqm"}},{"1":{"1":"https://www.cats.org.uk/uploads/images/featurebox_sidebar_kids/grief-and-loss.jpg","3":582,"4":328},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRkadsYJoVDlWZ6IbaBDHQBCr8xqf9tghiiGd1kUosjQfa87EwDxA","3":200,"4":112},"3":{"2":"https://www.cats.org.uk/","3":"Cats Protection - UK's Largest Feline Welfare Charity","4":"Ginger cat","10":"JTPLwlndmEDniN"},"5":{"1":"FNDtweTpuRKfAaw"}},{"1":{"1":"https://www.readersdigest.ca/wp-content/uploads/sites/14/2011/01/4-ways-cheer-up-depressed-cat.jpg","3":1000,"4":700},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzydEUK5PkeCEMWd5_FBN6rPwGUZE5NpniXIJvFolxCxP0k_Ya","3":200,"4":140},"3":{"1":"Reader's Digest Canada","2":"https://www.readersdigest.ca/home-garden/pets/4-ways-cheer-depressed-cat/","3":"How to Cheer Up a Depressed Cat","4":"4 Ways to Cheer Up a Depressed Cat","10":"ANUMBTkkqibRAD"},"5":{"1":"dOqNJVdHiXMiRAx"}},{"1":{"1":"https://s.hswstatic.com/gif/whiskers-sam.jpg","3":400,"4":272},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQkLe7r0U3Tw6QYb4r4nDvtysFrTFA6kfkByQ-NMk64VqgPqrE","3":200,"4":136},"3":{"1":"Animals | HowStuffWorks","2":"https://animals.howstuffworks.com/pets/question592.htm","3":"Why do cats have whiskers? | HowStuffWorks","4":"A cat's whiskers are so sensitive that they can detect the slightest  directional change in a","10":"lsrjwuKAaujOte"},"5":{"1":"HhtIvaifBWqrnAo"}},{"1":{"1":"https://i.ytimg.com/vi/I7jgu-8scIA/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQEq5El8D9lupke-0HjTPkPdfpS-KP8r4ic4Hutkz0lU-9VyX1Dcw","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=I7jgu-8scIA","3":"Animal Funny Cat Images, Pics, Videos","4":"Animal Funny Cat Images, Pics, Videos","10":"GFeWDFVjovWHnS"},"5":{"1":"RnAdHAIxVJeRIkj"},"7":{"1":{"11":{"1":"Animal Funny Cat Images, Pics, Videos","2":"A Funny Cat Videos Compilation, Cats Pictures, Images & Photos, cat photos  free download, cat photos wallpaper, cat photos free, Cat Photos hd  wallpapers fre...","3":"1:31","4":"102595","5":"1468454400000","6":"Real Video","7":"195","8":"1"}}}},{"1":{"1":"https://pbs.twimg.com/profile_images/378800000532546226/dbe5f0727b69487016ffd67a6689e75a_400x400.jpeg","3":400,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTbviSJcx2a4U01BRinV9aTIrdxUBzy9ZCHs2WdNG49aanJilZG","3":200,"4":200},"3":{"1":"Twitter","2":"https://twitter.com/cats","3":"Cats (@Cats) | Twitter","4":"Cats","10":"NdifjEknWFWSjU"},"5":{"1":"aTqngNpkitmabKn"}},{"1":{"1":"http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg","3":720,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS1O0mrtqT01GaiopVuQ6xn9yxiBGX8Vq4GZgq1bTcAbddeDAP","3":200,"4":200},"3":{"1":"Animal Planet","2":"http://www.animalplanet.com/pets/cats/","3":"Cats | Animal Planet","4":"Enter Your Cat In the #SaturdayCaturday Photo Contest","10":"emYEBtlYQpiAbm"},"5":{"1":"ivgquuqMrsiRMqY"}},{"1":{"1":"http://catsatthestudios.com/wp-content/uploads/2017/12/12920541_1345368955489850_5587934409579916708_n-2-960x410.jpg","3":960,"4":410},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2CCdsr45LaljC1fM0vx0IwzNWhFO4t6AlEmZlhsjrhmjbknh-","3":200,"4":85},"3":{"2":"http://catsatthestudios.com/","3":"Cats At The Studios","4":"","10":"CfMfbnycBdJMNW"},"5":{"1":"XxgiTeyyBktDYgI"}},{"1":{"1":"https://images.pexels.com/photos/326875/pexels-photo-326875.jpeg?auto=compress&cs=tinysrgb&h=350","3":525,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAeaY5lovSy3u9wAf2A-evp1YJow4XxrBY2N49sitZikCt3odshg","3":200,"4":133},"3":{"1":"Pexels","2":"https://www.pexels.com/search/cat/","3":"446 Adorable Cat Pictures · Pexels · Free Stock Photos","4":"Cat Outdoors","10":"gDtGgtJFNRBnKs"},"5":{"1":"fqQxxvMBbmHnoGf"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/101438745-cat-conjunctivitis-causes.jpg","3":2673,"4":1797},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-RyKa-DFc31yM6YnVxmbpH-Wh-TGhvGs-EbC9mIBiOSk2i3fIyw","3":200,"4":134},"3":{"1":"Petfinder","2":"https://www.petfinder.com/animal-shelters-and-rescues/fostering-cats/eight-reasons-you-can-foster-a-pet/","3":"Eight Reasons You Can Foster a Pet -- Even If You Think You ...","4":"Photo Credit: Thinkstock","10":"oVsrTAfMjhstNX"},"5":{"1":"RjxVkBxrJfxAkFb"}},{"1":{"1":"https://ichef.bbci.co.uk/images/ic/720x405/p0517py6.jpg","3":720,"4":405},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpvUB49_6VsNZeqiVuryzEbAgFrEFF-rz3xLc7KOtIA3rdtWmDzw","3":200,"4":112},"3":{"1":"BBC.com","2":"https://www.bbc.com/news/uk-scotland-39717634","3":"Should designer cats be banned?","4":"","10":"EVfyYqRfoeydmH"},"5":{"1":"tAjxscAqhLXqVDW"},"7":{"1":{"11":{"1":"Should designer cats be banned?","2":"The British Veterinary Association says irresponsible breeding of Scottish  Fold cats should be banned.","3":"0:51","5":"1493251200000"}}}},{"1":{"1":"https://www.rd.com/wp-content/uploads/2016/04/01-cat-wants-to-tell-you-laptop.jpg","3":2400,"4":1600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTg6mKUF2r_U-_Nz10Wnk4TB5NLniqvO3oUHJW3at3cJp5UzffsMg","3":200,"4":133},"3":{"1":"Reader's Digest","2":"https://www.rd.com/advice/pets/how-to-decode-your-cats-behavior/","3":"Cat Behavior: Things Your Cat Wants to Tell You | Reader's Digest","4":"Please do not disturb my nap on your laptop or keyboard","10":"hPwqXxbtgVUEng"},"5":{"1":"ogVpkBcTvnUHKQg"}},{"1":{"1":"http://www.petsworld.in/blog/wp-content/uploads/2014/09/adorable-cat.jpg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKr6YlGNsqgJzvgBBkq1648_HsuDizVn_ZXC6iQp9kjXFzLvs1BA","3":200,"4":112},"3":{"1":"Petsworld","2":"https://www.petsworld.in/blog/cat-pictures-funny-cute-adorable-and-all-time-favorite-cat-images.html","3":"Cat Pictures - All Time Favorite Images of Cats | Pets World","4":"Lovely ...","10":"VWyqcdIifiPAsd"},"5":{"1":"yEBvoqdpBJAADwy"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg","3":1200,"4":1199},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZCGyzQCpBWIboSErgUWkpGjp6NnHDRHNukRLST7JZ484gOrrN","3":200,"4":199},"3":{"1":"Wiktionary","2":"https://en.wiktionary.org/wiki/cat","3":"cat - Wiktionary","4":"","10":"qesKDTYqjNDBQr"},"5":{"1":"nFrmKJJBTxIDCyJ"}},{"1":{"1":"http://www.catster.com/wp-content/uploads/2017/10/A-kitten-meowing-with-his-mouth-open.jpg","3":600,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSe8Jz9HWznGSe5UmiA7aTpyr4h0ZbU6kMaNVtLoe1bzXJePHXG","3":200,"4":133},"3":{"1":"Catster","2":"https://www.catster.com/lifestyle/cat-wont-stop-meowing-reasons-for-cat-meowing","3":"Cat Won't Stop Meowing? 7 Reasons For All That Cat Meowing ...","4":"Cat Won't Stop Meowing? 7 Reasons For All That Cat Meowing - Catster","10":"rOLKXbEemWMNIf"},"5":{"1":"HwATpmJvGCtpMFg"}},{"1":{"1":"https://cdn-images-1.medium.com/max/1600/1*mONNI1lG9VuiqovpnYqicA.jpeg","3":1600,"4":911},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBSLktez1akzZE9ow_QqBWlJ0tKmIEwPdNcsa6b-e3smz0Y5z9","3":200,"4":113},"3":{"1":"Hacker Noon","2":"https://hackernoon.com/a-guide-to-giving-your-cats-their-annual-performance-review-fbf14610305","3":"A guide to giving your cats their annual performance review","4":"","10":"awJBeEDkWAhkkj"},"5":{"1":"kTEHqrRYxvSjFcs"}},{"1":{"1":"https://www.aspca.org/sites/default/files/cat-care_urine-marking_main-image.jpg","3":1040,"4":500},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjlvHgqz9zSaliBXKKJRhynljd48S70CA-gQoVifLjXfFzXTex","3":200,"4":96},"3":{"1":"aspca","2":"https://www.aspca.org/pet-care/cat-care/common-cat-behavior-issues/urine-marking-cats","3":"Urine Marking in Cats | ASPCA","4":"Urine Marking in Cats","10":"BlkviGkEnuVojJ"},"5":{"1":"ecTTqLuGxKVUcJP"}},{"1":{"1":"https://media.istockphoto.com/photos/feline-picture-id512202044?k=6&m=512202044&s=612x612&w=0&h=VhTTUGX--kLckiNLgoEELarEJUgemigqLHkjo9-VVYE=","3":612,"4":408},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRZemwo9_Ur3LX9ZP9rk-ZskbIHKDD4nniZAymFOC1F6ot0HYQnA","3":200,"4":133},"3":{"1":"iStock","2":"https://www.istockphoto.com/sg/photos/cats","3":"Royalty Free Cats Pictures, Images and Stock Photos - iStock","4":"Feline stock photo","10":"iMthlYTpJYgtdI"},"5":{"1":"vuXdIGjRcfjLJAO"}},{"1":{"1":"https://www.bluecross.org.uk/sites/default/files/assets/images/cat%20tick.jpg","3":3200,"4":2595},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlq8UxNpI3sv4Ld-h2o83xxncY9URNPXVbWTL4ECfxmuG0th4Rag","3":200,"4":162},"3":{"1":"Blue Cross","2":"https://www.bluecross.org.uk/pet-advice/cats-and-ticks","3":"Cats and ticks | How to spot and remove ticks from cats ...","4":"Cats and ticks | How to spot and remove ticks from cats | Blue Cross","10":"ghAtIlveaDuvKG"},"5":{"1":"PWaSYHMWopSrgKf"}},{"1":{"1":"https://www.shelterluv.com/sites/default/files/animal_pics/464/2016/11/25/22/20161125220040.png","3":1024,"4":1024},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlaceNooMylVTLcMPyXpgPqt033qbXFseV3BQnOdwoOF4yWL02","3":200,"4":200},"3":{"1":"Austin Pets Alive!","2":"https://www.austinpetsalive.org/adopt/cats/","3":"Austin Pets Alive! Available Cats - Austin Pets Alive!","4":"Winnie","10":"mbCVTqDjXUGOqI"},"5":{"1":"RPbuTitwcJrARju"}},{"1":{"1":"http://www.petsworld.in/blog/wp-content/uploads/2014/09/cute-kittens.jpg","3":460,"4":276},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR7gRqfGF8AOysFCbPj7FQEkvPD7EJxficJ3hG3jAnKHqk7OSnDww","3":200,"4":120},"3":{"1":"Petsworld","2":"https://www.petsworld.in/blog/cat-pictures-funny-cute-adorable-and-all-time-favorite-cat-images.html","3":"Cat Pictures - All Time Favorite Images of Cats | Pets World","4":"A healthy young cat sitting","10":"DJCvRXDEMFHWFC"},"5":{"1":"JSCCVENnJxkeJkS"}},{"1":{"1":"https://news.nationalgeographic.com/content/dam/news/2018/05/17/you-can-train-your-cat/02-cat-training-NationalGeographic_1484324.ngsversion.1526587209178.adapt.1900.1.jpg","3":1900,"4":1266},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSiuxf2WZEzJwoVCSC87LI4g-KBxBnmld-Y9t7YuRLo9-H8ifC-Vw","3":200,"4":133},"3":{"1":"Latest Stories - National Geographic","2":"https://news.nationalgeographic.com/2018/05/animals-cats-training-pets/","3":"Why You're Probably Training Your Cat All Wrong","4":"","10":"VigYrdlMvakobR"},"5":{"1":"eiQWTqEIvjVgrgE"}},{"1":{"1":"https://www.argospetinsurance.co.uk/assets/uploads/2017/10/pexels-photo-416160.jpeg","3":3888,"4":2592},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRPCS-aaaF7r3ypNGiFTi29miHqRFGgC7bnqTs7pw-71L0a-Mwnzw","3":200,"4":133},"3":{"1":"Argos® Pet Insurance","2":"https://www.argospetinsurance.co.uk/we-talk-pet/10-things-cats-do-to-show-they-love-you/","3":"10 Things Cats Do To Show They Love You | Argos Pet Insurance","4":"10 Things Cats Do To Show They Love You","10":"rYgIMLoQkrocaW"},"5":{"1":"kodUSpMtIyjumXF"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/112809642-fostering-cats-kittens-632x475.jpg","3":632,"4":475},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFJ4TjzMvQCcqtVW8DjfRlgZRNhW0icO1WhlVJfaqr2jwjybd8","3":200,"4":150},"3":{"1":"Petfinder","2":"https://www.petfinder.com/animal-shelters-and-rescues/fostering-cats/fostering-cats-kittens/","3":"How to Be the Best Cat Foster Parent | Petfinder","4":"How to be the Best Cat Foster Parent","10":"RpYktfNNgFFUdM"},"5":{"1":"hVlXPYvfICAxvrP"}},{"1":{"1":"https://www.msah.com/sites/default/files/play-cats.jpg","3":632,"4":353},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtcDTBvP4A08AMSJl0Tk0_gLs_BjEnJ5-b1_2lvE3fSl_b0Yau","3":200,"4":111},"3":{"1":"Metairie Small Animal Hospital","2":"https://www.msah.com/services/cats/blog/playing-your-cats-%E2%80%93-every-day","3":"Playing with Your Cats – Every Day | MSAH - Metairie Small ...","4":"Playing with Your Cats – Every Day","10":"tsqryOecsuMihO"},"5":{"1":"BgVXTRcSCvUAcCp"}},{"1":{"1":"https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/munchkinhed.png?itok=oeH4evcQ&resize=1100x1100","3":1100,"4":739},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbjgFUFnqKqflsXhxpCLxR3RP5jl8OT0OVTCmr4zXIMpJEJ64","3":200,"4":134},"3":{"1":"Mental Floss","2":"http://mentalfloss.com/article/80011/7-short-facts-about-munchkin-cats","3":"7 Short Facts About Munchkin Cats | Mental Floss","4":"iStock","10":"oYOoVrtVhpULsR"},"5":{"1":"BwXdgvLEqHVuGgC"}},{"1":{"1":"https://cdn.pixabay.com/photo/2014/03/29/09/17/cat-300572_960_720.jpg","3":858,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiXhgkC523CD5DIdvfwFl3G_S1Hc3oHzh8NUTXPeRSfYv1i8rA","3":200,"4":168},"3":{"1":"Pixabay","2":"https://pixabay.com/en/cat-animal-pet-cats-close-up-300572/","3":"Cat Animal Pet · Free photo on Pixabay","4":"cat animal pet cats close up","10":"OHrigtPprUbqIt"},"5":{"1":"UVwBxWqQQJpELdq"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/152964589-welcome-home-new-cat-632x475.jpg","3":632,"4":475},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ1Ryrw8RcKm866nT-TcscKEKQUMvsrnhdNLT3y06nvxb-FhfDt","3":200,"4":150},"3":{"1":"Petfinder","2":"https://www.petfinder.com/cats/bringing-a-cat-home/welcome-home-new-cat/","3":"9 Ways to Welcome Home your New Cat | Petfinder","4":"9 Ways to Welcome Home your New Cat","10":"RbACJocuSEhqRa"},"5":{"1":"nJnuySiDYQJflde"}},{"1":{"1":"https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/istock_000072600763_small.jpg?itok=LGQn4NSZ&resize=1100x1100","3":1100,"4":732},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR58HJCXknbahGz6Dc710zOivlLK6YAeGPkOsNWDo_k4RibzPJo","3":200,"4":133},"3":{"1":"Mental Floss","2":"http://mentalfloss.com/article/75833/celebrate-japans-cat-day-these-7-japanese-instagram-cats","3":"Celebrate Japan's Cat Day with These 7 Japanese Instagram ...","4":"iStock","10":"YUCVnPpvTavfJV"},"5":{"1":"qqAjxskMBsjupEQ"}},{"1":{"1":"https://thumbs-prod.si-cdn.com/3asSf7LmvyrY5m0-ggxJjrnd_DI=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/58/04/5804c840-3073-4ecf-a1d2-37808419fe93/gdahh5-wr.jpg","3":800,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQgwhDHRTam8t_vntCH3lU3vZ3A697TxZwdbMZwvMNuLSQ3TakM","3":200,"4":149},"3":{"1":"Smithsonian Magazine","2":"https://www.smithsonianmag.com/science-nature/theres-no-such-thing-hypoallergenic-cat-180968819/","3":"There's No Such Thing as a Hypoallergenic Cat | Science ...","4":"These unusual cats may have some advantages for allergic owners, but to  call them hypoallergenic ...","10":"dmLuuTyYAvgAOD"},"5":{"1":"UwxXbIqINHIIvuh"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2012/11/91615172-find-a-lump-on-cats-skin-632x475.jpg","3":632,"4":475},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTuxqqFdfLl9xgGpx0T4ErYHW7JQjhh2U5JDnTIm6lQQKuWlchb","3":200,"4":150},"3":{"1":"Petfinder","2":"https://www.petfinder.com/cats/","3":"Cats: Adoption, Bringing A Cat Home and Care","4":"","10":"uJOSoggYshTaUI"},"5":{"1":"waQpBnMWGyMBaQg"}},{"1":{"1":"https://ravishly-9ac9.kxcdn.com/cdn/farfuture/edYzCuowlJVcDos1RjXSa8_1o5tGDQBE4ebEFE6R1OE/mtime:1479930604/sites/default/files/maxresdefault_2.jpg","3":1600,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTOD7uc1bCe8jGOehxNSdsB3RewoVlWU-4EON8EXBLTIupS4YQS","3":200,"4":149},"3":{"1":"Ravishly","2":"https://ravishly.com/ravs-radar/your-cat-making-you-horny-what","3":"Is Your Cat Making You Horny? (What?) | Ravishly | Media Company","4":"Is Your Cat Making You Horny? (What?)","10":"rbYhAXkbgtNkAY"},"5":{"1":"SLwJxCswOkjIuxT"}},{"1":{"1":"http://www.animaltransportationassociation.org/Resources/Pictures/cat2.jpg","3":2560,"4":1600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRawXsBlHjuyVHNLuP5KWss9CfyB_LyXdOhy0lD1_aFl7w9fRO8","3":200,"4":124},"3":{"1":"Animal Transportation Association","2":"http://www.animaltransportationassociation.org/19Mar15_atawebcast","3":"Animal Transportation Association - Carrying Cats ...","4":"Carrying Cats: Considerations for Felines During Transit","10":"XhJwPxfLULYfXJ"},"5":{"1":"TbdLHqgvygvuRPl"}},{"1":{"1":"https://r.hswstatic.com/w_907/gif/tesla-cat.jpg","3":907,"4":510},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXjhYG2c5myi8y_vziQOoCg_4WvcIHkAFKr9PpsJCUZSTKZtDD","3":200,"4":112},"3":{"1":"Animals | HowStuffWorks","2":"https://animals.howstuffworks.com/pets/teslas-cat-and-other-feline-fascinations.htm","3":"Nikola Tesla's Cat and Other Feline Fascinations | HowStuffWorks","4":"","10":"YPnSORjUREfjUP"},"5":{"1":"oUMXyuhFJqlfjTK"}},{"1":{"1":"https://i.ytimg.com/vi/zGcYabz3hYg/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTn95ROGrOOGyx5B8KPjaooWMaGSzy0o-UGgPWSMhbyj438qZcRYA","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=zGcYabz3hYg","3":"Sushi for Cats","4":"Sushi for Cats","10":"YDCvnorpNepngG"},"5":{"1":"bdssmGwdEiDSYRu"},"7":{"1":{"11":{"1":"Sushi for Cats","2":"â–ºPatreon: https://www.patreon.com/JunsKitchen â–ºEQUIPMENT I use on my  channel that you can buy online (Amazon affiliates links) ―Knife― Chef  Knife: Sekimagoro...","3":"4:04","4":"10220867","5":"1500854400000","6":"JunsKitchen","7":"246890","8":"17056"}}}},{"1":{"1":"https://imgix.bustle.com/rehost/2017/5/30/f9fc3698-7ca6-40e5-975b-a63878357657.jpg","3":4288,"4":3216},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQs07PEKjsUcCKXIEeLpIYG_um9W8Z_tAUym4laTeMEQqxrnu2e_g","3":200,"4":149},"3":{"1":"Bustle","2":"https://www.bustle.com/articles/144945-6-reasons-cats-are-not-just-like-women-because-the-stereotypes-have-got-to-go","3":"6 Reasons Cats Are Not \"Just Like\" Women, Because The ...","4":"6 Reasons Cats Are Not \"Just Like\" Women, Because The Stereotypes Have Got  To Go","10":"wUAIaceDiYwbQS"},"5":{"1":"bmGlSRwqgVAblRg"}},{"1":{"1":"https://www.shelterluv.com/sites/default/files/animal_pics/464/2016/11/25/21/20161125215406.png","3":1024,"4":1024},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSdoH6fd7-mpAM9EcN7wj2dmhgKcUBNrjPdLqruK--36bvJ6qr1xA","3":200,"4":200},"3":{"1":"Austin Pets Alive!","2":"https://www.austinpetsalive.org/adopt/cats/","3":"Austin Pets Alive! Available Cats - Austin Pets Alive!","4":"Ellsworth 5","10":"cjoDglsXHWwNUE"},"5":{"1":"yQFhabreXuYuacm"}},{"1":{"1":"http://r.ddmcdn.com/w_830/s_f/o_1/cx_0/cy_66/cw_288/ch_162/APL/uploads/2014/10/cat_5-1.jpg","3":830,"4":466},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZr_w2kP8Wg9ESCJmgUCcsHj8zDgLM2cvpQbUTZt9LIdfHr0jF","3":200,"4":112},"3":{"1":"Animal Planet","2":"http://www.animalplanet.com/pets/cats/","3":"Cats | Animal Planet","4":"General Cat Care Tips","10":"DiVYMoamtOsUgN"},"5":{"1":"enxIppusXeDqqOC"}},{"1":{"1":"https://thumbs-prod.si-cdn.com/arpyrvhwaJWduhI6QhMe9Fo3858=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/20110913074012glowing_cat_web.jpg","3":470,"4":251},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbVN3ZxmtUTLNkABAQstR_IcVm3nGK9FBZxwfhOWU5mjGjn0DN","3":200,"4":106},"3":{"1":"Smithsonian Magazine","2":"https://www.smithsonianmag.com/science-nature/the-glow-in-the-dark-kitty-77372763/","3":"The Glow-In-The-Dark Kitty | Science | Smithsonian","4":"A fluorescent green cat could help in the fight against AIDS","10":"uIAMvvVbSXvIUH"},"5":{"1":"yBiLdBepktKCObP"}},{"1":{"1":"https://icatcare.org/sites/default/files/kcfinder/images/images/aggressive-red-cat.jpg","3":490,"4":326},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRH8x6rsyQTeKuDhI4Y3q_xjU5PYPQljhfvxy_1BjkvQKGBp4PT","3":200,"4":133},"3":{"1":"International Cat Care","2":"https://icatcare.org/advice/problem-behaviour/aggression-between-cats","3":"Aggression between cats | International Cat Care","4":"Aggression between cats","10":"usEbeWdynUvWJO"},"5":{"1":"lGvbsGkSBdmGRuJ"}},{"1":{"1":"http://cdn0.wideopenpets.com/wp-content/uploads/2018/02/AdobeStock_181671521.jpeg","3":4272,"4":2848},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT2c7pm89h2GgdUOys6nBz1omEtspO1aguhl7DPUj5gR_aImYFm","3":200,"4":133},"3":{"1":"Wide Open Pets","2":"https://www.wideopenpets.com/8-affectionate-cat-breeds-that-actually-love-to-cuddle/","3":"9 Affectionate Cat Breeds That Actually Love to Cuddle","4":"Girl holds in his hands a beautiful Siamese cat","10":"MhRqTMHQiSQTSq"},"5":{"1":"oxLmbcibtEAPGRO"}},{"1":{"1":"https://www.thesprucepets.com/thmb/7kVrWdBf13osb9nYJ-4D2yPAwfQ=/425x326/filters:no_upscale():max_bytes(150000):strip_icc()/GettyImages-466792657-59cef0d6c412440010be728c.jpg","3":425,"4":326},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9-jeA_VEFnUUwJzRS9dTC2FRcAiNZboqIhgAGCPI_Gd_G6b8e","3":200,"4":153},"3":{"1":"The Spruce Pets","2":"https://www.thesprucepets.com/cats-4162124","3":"How to Be a Responsible Cat Owner","4":"Cats","10":"rTaXFKEVvQoCxn"},"5":{"1":"UjCFlVxhlVPNwjF"}},{"1":{"1":"https://ichef.bbci.co.uk/news/624/cpsprodpb/305D/production/_103218321_gettyimages-134815902.jpg","3":624,"4":351},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSOL8rHQ04-vwxJqVlRqN-H0hK4kUwnmckDMP0zTvKXJy1iG3Nc","3":200,"4":112},"3":{"1":"BBC","2":"https://www.bbc.co.uk/news/world-asia-45347136","3":"Why a village in New Zealand is trying to ban all cats - BBC News","4":"Stock image of a cat outside in flower bed","10":"NrUvUBQTcTCSiL"},"5":{"1":"YHAqNrBWfXaEMVb"}},{"1":{"1":"https://atlantahumane.org/wp-content/uploads/2012/08/adopt-a-cat-1200x630.png","3":1200,"4":630},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5TH43KjTPkOGsCqmw8hjBcrHO-erQelSZ0FWlA29r0zOoJW92hg","3":200,"4":105},"3":{"1":"Atlanta Humane Society","2":"https://atlantahumane.org/adopt/cats/","3":"Adopt a Cat or Kitten","4":"Adopt a Cat","10":"knAaYJckcivLmR"},"5":{"1":"TsjhVmbdmbVoHoD"}},{"1":{"1":"http://www.dreams.metroeve.com/wp-content/uploads/2017/04/dreams.metroeve_cats-dreams-meaning.jpg","3":592,"4":304},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTNet_foDzEqA51kZf7y8R5kOWFEUKK9F9ICsbZYr4bOTLhMeZ5","3":200,"4":102},"3":{"1":"Dream Dictionary","2":"http://www.dreams.metroeve.com/cats/","3":"Cats dreams meaning - Interpretation and Meaning","4":"Cats dreams meaning","10":"pYiiOfEsHvASoL"},"5":{"1":"yitDHIAaQOOdaRT"}},{"1":{"1":"https://www.petful.com/wp-content/uploads/2011/10/cats-cuddling-funny-850x539.jpg","3":850,"4":539},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQOMIoyg_pWYw3k1LS2ryBqbL8tjvfoqv9-OTFEXTplBM5yJx7l","3":200,"4":126},"3":{"1":"Petful","2":"https://www.petful.com/behaviors/how-do-cats-communicate-with-each-other/","3":"How Do Cats Communicate With Each Other? - Petful","4":"3 Ways of Communication Between Cats","10":"LQaqSqLhLnBUfW"},"5":{"1":"bUTftQCTbDFlsdb"}},{"1":{"1":"http://www.petsworld.in/blog/wp-content/uploads/2014/09/cat.jpg","3":400,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2WhOti17crdhQ5YaH0tWnaPwy-EL7rVEWpyH_VABFAmjfA8mZKA","3":133,"4":200},"3":{"1":"Petsworld","2":"https://www.petsworld.in/blog/cat-pictures-funny-cute-adorable-and-all-time-favorite-cat-images.html","3":"Cat Pictures - All Time Favorite Images of Cats | Pets World","4":"A Cat lover's delight","10":"MIeOauNTFxruUL"},"5":{"1":"ynywhMRTGlWxicb"}},{"1":{"1":"http://sciencenordic.com/sites/default/files/imagecache/620x/kat_astma_videnskab.jpg","3":620,"4":412},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKXdoXAT7VqIMXRBmjSFJDcgeP1cDrLo3O_bGAGSgSJ79PcRRo","3":200,"4":132},"3":{"1":"ScienceNordic","2":"http://sciencenordic.com/cats-protect-newborns-against-asthma","3":"Cats protect newborns against asthma | ScienceNordic","4":"","10":"ebtAfFAJkMedhO"},"5":{"1":"TbgPbTfAlYCrRsQ"}},{"1":{"1":"http://www.catcareofvinings.com/blog/wp-content/uploads/2017/05/CCV_iStock-619079366-2000x1331.jpg","3":2000,"4":1331},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9KUm5nLqQKG0OAzhoQxzDccFO7C0MmTanEFr-DHp3mHqaQQpmow","3":200,"4":133},"3":{"1":"Cat Care of Vinings","2":"http://www.catcareofvinings.com/blog/cat-thinking/","3":"Deep Thoughts: What is Your Cat Thinking Throughout the Day ...","4":"cat care","10":"qQBClwCNpdCxEj"},"5":{"1":"lQNOMbAUqgcyqYD"}},{"1":{"1":"https://images.immediate.co.uk/volatile/sites/4/2018/08/iStock_000044061370_Medium-fa5f8aa.jpg?quality=45&crop=5px,17px,929px,400px&resize=960,413","3":960,"4":413},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgIMohz552yuAneZIasvHIn5KJKN4L5IK7jc6rSluz48MIov2BvQ","3":200,"4":85},"3":{"1":"BBC Focus Magazine","2":"https://www.sciencefocus.com/nature/is-it-true-that-most-ginger-cats-are-male/","3":"Is it true that most ginger cats are male? - Science Focus ...","4":"Is it true that most ginger cats are male? © iStock","10":"IsSWOkewoBVoyN"},"5":{"1":"rvWVNrAfIXvtwcE"}},{"1":{"1":"https://cdn.theatlantic.com/assets/media/img/mt/2017/06/shutterstock_319985324/lead_720_405.jpg?mod=1533691890","3":720,"4":405},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYRaFuQDancwY5rr0g1FR48S7rbXhI1cPh0UHMtjTNKpGRoH7WSw","3":200,"4":112},"3":{"1":"The Atlantic","2":"https://www.theatlantic.com/science/archive/2017/06/cat-domination/530685/","3":"How Cats Used Humans to Conquer the World - The Atlantic","4":"Cat jumps in air","10":"vUEGUDKayXFWYs"},"5":{"1":"ROWDGLyjMsbVgwt"}},{"1":{"1":"https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Fpeopledotcom.files.wordpress.com%2F2018%2F08%2F34982856_913748398827212_5249963337373974528_n.jpg%3Fw%3D1800&w=700&c=sc&poi=face&q=85","3":700,"4":700},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTsKnyOc-9bYJXBDCVmG6xK9sBNmbi2myY2zFL8u8FaDkmajd8BAQ","3":200,"4":200},"3":{"1":"People Magazine","2":"https://people.com/pets/iambronsoncat-33-pound-cat-weight-loss-journey/","3":"iambronsoncat: Fat Cat on Instagram Losing Weight | PEOPLE.com","4":"Bronson the cat/Instagram","10":"uYuIUYkriwkfEs"},"5":{"1":"bcluKuWcQjWgSGD"}},{"1":{"1":"https://static.boredpanda.com/blog/wp-content/uploads/2017/07/funny-tiny-face-cats-photoshop-battle-11-596db6bf66c5b__605.jpg","3":605,"4":409},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5eo0CbpzMdi0QofgC2v0k6G089ljeSEqjlTBdjVQ8AXas3dANIQ","3":200,"4":134},"3":{"1":"Bored Panda","2":"https://www.boredpanda.com/funny-tiny-face-cats-photoshop-battle/","3":"People Are 'Breeding' Cats With Tiny Faces, And We Can't ...","4":"Cats With Tiny Faces","10":"KhasNKHCjkpiOK"},"5":{"1":"BRXGRcorLPkYToy"}},{"1":{"1":"https://d17fnq9dkz9hgj.cloudfront.net/uploads/2013/09/cat-black-superstitious-fcs-cat-myths-162286659.jpg","3":632,"4":353},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRoAclhVC7gbhlRQOYDDcxQpjCH0_0aI0BIftb1X0JixabN0-KuSg","3":200,"4":111},"3":{"1":"Petfinder","2":"https://www.petfinder.com/cats/","3":"Cats: Adoption, Bringing A Cat Home and Care","4":"black cat","10":"jgvbapwuhVjMDF"},"5":{"1":"LIPTYfsRLcsdxef"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Cat_eating_a_rabbit.jpeg/220px-Cat_eating_a_rabbit.jpeg","3":220,"4":187},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTM2lD05jXtOZSV7AuO3hvNvDWkObMlWiC97BQtxlT0RGL_LH4zjQ","3":200,"4":170},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Cat","3":"Cat - Wikipedia","4":"Impact on prey species","10":"MvcDWiVddakwSO"},"5":{"1":"DdiScMFQsSrAqKm"}},{"1":{"1":"https://assets3.thrillist.com/v1/image/2696152/size/tmg-article_tall;jpeg_quality=20.jpg","3":640,"4":853},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuPeTpZbE5BZKB-5-exd6Ecv4fY1BlGVHZ1leqZN2Zu0vHdPhigw","3":149,"4":200},"3":{"1":"The Dodo","2":"https://www.thedodo.com/close-to-home/what-to-do-stray-cat","3":"What To Do If You Find A Stray Cat - The Dodo","4":"Share on Facebook ...","10":"gQcCvghMoTEaHn"},"5":{"1":"xHsHCsPpDjcLGUm"}},{"1":{"1":"https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/video/wibbitz/wbz-when-cats-sneeze.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSoBO_x3BJPFuVLwm8fyi2dbu0KIAmw32oWZn8hyckaIzj4Ain9","3":200,"4":112},"3":{"1":"Pet WebMD","2":"https://pets.webmd.com/cats/why-cats-sneeze","3":"Why Cats Sneeze","4":"","10":"lIiLWrpodGqLbE"},"5":{"1":"tcsvWDVrmXKLuXN"},"7":{"1":{"11":{"1":"Why Cats Sneeze","2":"WebMD explains why cats sneeze.","3":"0:49"}}}},{"1":{"1":"https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Fimages.hellogiggles.com%2Fuploads%2F2015%2F12%2F11083247%2Fcat.jpg&w=700&c=sc&poi=face&q=85","3":700,"4":467},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTyqlbEiXO_ve-xH0IupMWF_e06JxgJ1zW99lvaKeClbZopfbLt","3":200,"4":133},"3":{"1":"HelloGiggles","2":"https://hellogiggles.com/news/10-cat-puns-will-ever-need/","3":"The only 10 cat puns you will ever need - HelloGiggles","4":"","10":"FKYqmXrURSmLOp"},"5":{"1":"octogHMDQOutVmB"}},{"1":{"1":"https://lh3.googleusercontent.com/aR34MxRBretppyADbJcfqIZp-LraO1ELhk00lTZw0Q7MF1ebUKZeggeQkjBuZCCmYRSYNzr8=w640-h400-e365","3":640,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ6uXSCu96cLwMFotwgSKSr5TWi3PGa-RoBaNJLp6CXb4UzJw-f","3":200,"4":124},"3":{"1":"Chrome - Google","2":"https://chrome.google.com/webstore/detail/tabby-cat/mefhakmgclhhfbdadeojlkbllmecialg","3":"Tabby Cat - Chrome Web Store","4":"","10":"oMpQUFDpPDlshm"},"5":{"1":"otuueNvgwlPdxEJ"}},{"1":{"1":"https://cdn.cnn.com/cnnnext/dam/assets/150324154028-16-internet-cats-restricted-super-169.jpg","3":1100,"4":619},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqyAVnpTM5-KWPFFMnxMBPcmj-D8uuBwiY8TXf2odz72qQPGpx","3":200,"4":112},"3":{"1":"CNN.com","2":"https://www.cnn.com/2015/09/08/health/what-your-cat-is-trying-to-say/index.html","3":"This is what your cat is really trying to say - CNN","4":"<a href=\"https://www.facebook.com","10":"dLjonTcctpsPqG"},"5":{"1":"NsRfhrFRIgtGQCA"}},{"1":{"1":"http://media1.santabanta.com/full1/Animals/Cats/cats-149a.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS6Br_9c6YcOob_VRgBd0e3pRU4TIenPqGfy3_Mthi3Hrk2s0cO","3":200,"4":149},"3":{"1":"SantaBanta","2":"http://www.santabanta.com/photos/cats/2121149.htm","3":"Cats Wallpaper #150","4":"Cats","10":"ekdheuirMEGftK"},"5":{"1":"VRnuCjBVsnlKWgP"}},{"1":{"1":"https://ichef.bbci.co.uk/news/624/cpsprodpb/CC9D/production/_103218325_gettyimages-469927070.jpg","3":624,"4":351},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTRRLfK-jVNOChSkHJdIkdsHaO8dXY03z2yxcvMKhmG7a1OQ35x","3":200,"4":112},"3":{"1":"BBC","2":"https://www.bbc.co.uk/news/world-asia-45347136","3":"Why a village in New Zealand is trying to ban all cats - BBC News","4":"Stock image of a brown cat outfoors","10":"eRGrhfWPhjjycQ"},"5":{"1":"oWRQBUPOabUscQd"}},{"1":{"1":"https://i.ytimg.com/vi/bcENL_Vdoqw/maxresdefault.jpg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcROK723ru1FrNl8bV6pZuVJq4V5evxglOVkxHVyYFTElbSgm9Pw","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=bcENL_Vdoqw","3":"Cats vs Zombies","4":"","10":"VAdjUbmUiCJCFM"},"5":{"1":"VxjIxHRkQbIyfrJ"},"7":{"1":{"11":{"1":"Cats vs Zombies","2":"Cats declare war on Zombies to save the survivor kitten! SUBSCRIBE for more  videos â–º http://bit.ly/IWantMORE In Syfy’s Z Nation, a group of survivors  must cr...","3":"2:19","4":"59834392","5":"1441843200000","6":"Mr.TVCow","7":"312398","8":"14803"}}}},{"1":{"1":"https://lookaside.fbsbx.com/lookaside/crawler/media/?media_id=1496110487353938","3":548,"4":548},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzNjlUiXWA4sUaNvaTQ6HGkbJ4NpvPE5V8oSqxD_8fusAlmHRk","3":200,"4":200},"3":{"1":"Facebook","2":"https://www.facebook.com/CatsLoveCatnip/","3":"Cats on Catnip - Home | Facebook","4":"Post Your Cats","10":"hLuQEqDsfjIgrX"},"5":{"1":"jEkQhJpAOoRmYHg"}},{"1":{"1":"https://purrfectlove.net/wp-content/uploads/2015/06/catfamily.jpg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRA4hP9AZHDtW5ZnT3H21a7ma7gBf47CweoEjKthR4HQyvfRIG7","3":200,"4":112},"3":{"1":"Purrfect Love","2":"https://purrfectlove.net/cat-law-how-many-cats-is-too-many/","3":"How Many Cats Is Too Many? - Purrfect Love","4":"How Many Cats Is Too Many?","10":"ivxnqDKXbuUwSG"},"5":{"1":"OCYtoUuNlwggjDy"}},{"1":{"1":"https://www.popsci.com/sites/popsci.com/files/styles/1000_1x_/public/import/2014/5827857531_8962f29333_o.jpg?itok=b0be33M8","3":1000,"4":932},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyoHtobTnEVMoaBL6pEjD3ZI8JBi0TUYaWWxJwiuzg3tVHMFap","3":200,"4":186},"3":{"1":"Popular Science","2":"https://www.popsci.com/article/science/sorry-cat-haters-science-isnt-your-side","3":"Sorry, Cat Haters, Science Isn't On Your Side | Popular Science","4":"\"Unfeeling\" Cats. \"","10":"GohBftUAojRsam"},"5":{"1":"QiShqprShJXePFT"}},{"1":{"1":"https://cdn.cliqueinc.com/cache/posts/256509/cutest-cat-breeds-256509-1525454554042-main.700x0c.jpg","3":700,"4":467},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoweT_7x_-6xw2jD1svn8S5JIP7xaWzmQDp2x7d21Wo7CHlXv5","3":200,"4":133},"3":{"1":"MyDomaine","2":"https://www.mydomaine.com/cutest-cat-breeds","3":"Time to Procrastinate—Here Are the 9 Cutest Cat Breeds ...","4":"Norwegian Forest Cat","10":"DxlXHrbvPbRhRM"},"5":{"1":"WTgXnhEmHrmntVB"}},{"1":{"1":"https://www.factslides.com/imgs/black-cat.jpg","3":500,"4":644},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTY5ABlFn6BCa3HbeR35lZob_mc_PNIcqInrkKLsOQMCI68mH8qqA","3":155,"4":200},"3":{"1":"Factslides","2":"https://www.factslides.com/s-Cats","3":"Cat Facts: 67 Facts about Cats ←FACTSlides→","4":"Black cats are considered to bring good luck in Japan.","10":"yQaaLWLeScxINi"},"5":{"1":"alLwPdgtUAOpfaT"}},{"1":{"1":"https://steemitimages.com/DQmZ9QBgKETeQpVdvYF5jjG7YpNMvjTN9pSNTvZK3JfgjAx/This%20picture%20of%20a%20chubby%20ginger%20cat%20sat%20on%20his%20bum%20is%20one%20of%20the%20hilarious.jpg","3":660,"4":880},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTuAgPVocqHRVosZVfOxm_KWOrHcHGaRbU03lWxQnShpG1f9UDj","3":149,"4":200},"3":{"1":"Steemit","2":"https://steemit.com/photography/@kamrankami/how-was-it-cat-you-good-is-not-what-you-also-cats-to-hobby-is-this-cat","3":"How was it cat you good is not what you also cats to hobby is ...","4":"... This picture of a chubby ginger cat sat on his bum is one of the  hilarious","10":"bViAqgFCwwrfcj"},"5":{"1":"hXylHubafKgcrrO"}},{"1":{"1":"https://static.boredpanda.com/blog/wp-content/uploads/2016/10/worlds-most-beautiful-cats-44-57fc8f4e023ca__700.jpg","3":700,"4":700},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZCF3NPqMlA7u4mEVY3v8hpfMGvL5p0PaOZO9o0aUUhe7ZxMSI","3":200,"4":200},"3":{"1":"Bored Panda","2":"https://www.boredpanda.com/worlds-most-beautiful-cats/","3":"10+ Of The Most Beautiful Cats In The World | Bored Panda","4":"#7 Venus The Chimera Cat","10":"aSdHCwrUghWycR"},"5":{"1":"vjPxBDUANFhClKA"}},{"1":{"1":"https://www.pspca.org/sites/default/files/styles/pspca_banner/public/2018-01/38795646774_9d83bbaaab_o_0.jpg?h=2cfee321&itok=_Llsh3dA","3":1400,"4":580},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBGw3oS82bfnV5sV7-Uku1Ypnab84IKm1kcKmY6wzdtVMleayZqw","3":200,"4":82},"3":{"1":"pspca","2":"https://www.pspca.org/adoptcats","3":"Find Adoptable Cats | Pennsylvania Society for the Prevention ...","4":"Tabby cat","10":"JrmThTANNxNJUo"},"5":{"1":"SPSOOiyAYWREAol"}},{"1":{"1":"https://static01.nyt.com/images/2018/08/31/world/31nz-cats-print/31nz-cats-1-facebookJumbo.jpg","3":1050,"4":550},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVkepqVFEZUGC6MZsm3oP6jZ9QTqoHm1veIfbXVOOy-G4-bYJU5w","3":200,"4":104},"3":{"1":"The New York Times","2":"https://www.nytimes.com/2018/08/30/world/australia/new-zealand-cat-ban-birds.html","3":"New Zealand Town May Ban Cats to Protect Other Species - The ...","4":"New Zealand Town May Ban Cats to Protect Other Species - The New York Times","10":"uAXMylHRqniqpp"},"5":{"1":"qRjVlYTlLnuMaJn"}},{"1":{"1":"https://images.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg?auto=compress&cs=tinysrgb&h=350","3":335,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ8E2tu2o8JBkbyQfvl6nQ7NifLnv_QyRCXJCw9t5GjUl99ODUF","3":192,"4":200},"3":{"1":"Pexels","2":"https://www.pexels.com/search/cat/","3":"446 Adorable Cat Pictures · Pexels · Free Stock Photos","4":"Free stock photo of animal, pet, cute, kitten","10":"ndmNLdYnvbrOas"},"5":{"1":"HgrJlEORaXxLNIF"}},{"1":{"1":"https://ichef.bbci.co.uk/news/660/cpsprodpb/AECE/production/_99805744_gettyimages-625757214.jpg","3":660,"4":371},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT5HpqXD4cwzpfY_ncvOjnVTUuOKgEP1KhtZek2UBmt-r3mn87L","3":200,"4":112},"3":{"1":"BBC","2":"https://www.bbc.co.uk/news/uk-42871851","3":"Black cats shunned for purr-fect selfies - BBC News","4":"black cat looking at phone camera","10":"DSUwnvAAdiVpUf"},"5":{"1":"urBDFTTGLWcefFD"}},{"1":{"1":"https://cf.ltkcdn.net/cats/images/std/219726-675x450-kittehshnuggles.jpg","3":675,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrFGgZpa-BeJ65O8X70lA6zVn1vFMWMvNBzy8NhYH7hJzCbG3v","3":200,"4":133},"3":{"1":"Cats - LoveToKnow","2":"https://cats.lovetoknow.com/Cats_Mating","3":"Stop Cats Mating","4":"According to the Cats ...","10":"sUCTegpsVdFOop"},"5":{"1":"xjnhKdXhpwlUgYM"}},{"1":{"1":"http://www.orphankittenrescue.com/~ASSETS/img/upload/Cauliflower.JPG","3":1280,"4":1278},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa6M7jf9-TJ43GpiBfJZ1peF_8uGDJNyxg-OGpdyo4DE8eqPWEKw","3":200,"4":199},"3":{"2":"http://www.orphankittenrescue.com/","3":"Home - Vancouver Orphan Kitten Rescue Association (VOKRA)","4":"For ...","10":"uYtTmBTjjvMpvq"},"5":{"1":"iXDxdNRxEAIoOFn"}},{"1":{"1":"http://www.petmd.com/sites/default/files/multiple-cats-need-multiple-litter-boxes.jpg","3":590,"4":428},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbJpN8IE4jcuTJqFlRmaodVEW2_Yw8GEEUdJoPwskX6kGI-tri","3":200,"4":144},"3":{"1":"PetMD","2":"https://www.petmd.com/cat/centers/litter/evr_why_multi_cat_households_need_multiple_litter_boxes","3":"Why Multiple Cats Need Multiple Litter Boxes | petMD","4":"Purrfect and Tigress have adapted to sharing things and people in their  multi-cat household.","10":"xsIhunJNqlbxyW"},"5":{"1":"NoDkCFOkmfIlErY"}},{"1":{"1":"https://res.cloudinary.com/jpress/image/fetch/w_700,f_auto,ar_3:2,q_auto:low,c_fill/if_h_lte_200,c_mfit,h_201/https://www.lep.co.uk/webimage/1.9366362.1537968620!/image/image.jpg","3":700,"4":467},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQI8VbyK01jJozDTLPjCxKv7J4uqHCJzU_E1IlEQrD7CSFoH3t1ng","3":200,"4":133},"3":{"1":"Lancashire Evening Post","2":"https://www.lep.co.uk/news/watch-woman-with-terminal-cancer-s-urgent-plea-to-rehome-40-cats-1-9366366","3":"WATCH: Woman with terminal cancer's urgent plea to rehome 40 ...","4":"One of Marlene's cats to rehome","10":"HgVYXYnQeEWNFQ"},"5":{"1":"OECaxpuUVkUSGKa"}},{"1":{"1":"https://s3.amazonaws.com/geniusvets/gv-cta/sidebar/cta-cat-lab-tests-sidebar.png","3":320,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS3qZL1yS7DkEibVCeAFpS3IeTkWn5nUeZjF6jRclHe9DQItJYf","3":200,"4":187},"3":{"1":"Bakerstown Animal Hospital","2":"http://www.bakerstownah.com/services/cats/blood-tests-for-cats","3":"What Blood Tests Can Tell You About Your Cat's Health","4":"CTA - Cat Laboratory","10":"WYGLoSFkQkkOlU"},"5":{"1":"QIpENFLTqwFExTI"}},{"1":{"1":"https://imgix.bustle.com/uploads/image/2018/2/12/8a1cc530-2b29-436f-b780-70c5c7e8322e-fotolia_157293628_subscription_monthly_m.jpg?w=970&h=582&fit=crop&crop=faces&auto=format&q=70","3":970,"4":582},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHQzWOL9X_qCnsDHYja_J1EJSQQI5awRS9GEIlqi4sOtozcXyrLw","3":200,"4":120},"3":{"1":"Bustle","2":"https://www.bustle.com/articles/124691-why-are-cats-afraid-of-cucumbers-it-may-seem-funny-but-heres-why-you-shouldnt-pull","3":"Why Are Cats Afraid Of Cucumbers? It May Seem Funny, But ...","4":"Why Are Cats Afraid Of Cucumbers? It May Seem Funny, But Here's Why You  Shouldn't Pull This Viral ...","10":"vXmiRmjooFgCsj"},"5":{"1":"KJdGBlHcfKCtPiq"}},{"1":{"1":"https://www.nationalgeographic.com/content/dam/animals/thumbs/rights-exempt/mammals/d/domestic-cat_thumb.ngsversion.1472140774957.adapt.1900.1.jpg","3":1900,"4":1900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS4UX9nw98T3rBMvfzkMFJE9h2S6lpppox9iqvgHiM9t3jrEX5u","3":200,"4":200},"3":{"1":"National Geographic","2":"https://www.nationalgeographic.com/animals/mammals/d/domestic-cat/","3":"Cat | National Geographic","4":"","10":"FHvtOxoVXKKBNG"},"5":{"1":"IwmWDqshKHyErfm"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/A_completely_deaf%2C_pure_white_blue-eyed_cat.jpg/220px-A_completely_deaf%2C_pure_white_blue-eyed_cat.jpg","3":220,"4":330},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfePLQh_QXB06o8zZm2w6RlMOK0_4z-Q9LqU3OWziuf7IlJ9Op","3":133,"4":200},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Congenital_sensorineural_deafness_in_cats","3":"Congenital sensorineural deafness in cats - Wikipedia","4":"Congenital sensorineural deafness in cats","10":"kmgduSfYJOmlpK"},"5":{"1":"CVrmsAPQhtudphd"}},{"1":{"1":"https://d32xvgr96w2oxp.cloudfront.net/2013/07/cats-16140154-1920-1080.jpg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSelnL0s3W9PXwG0lPGhgM1xmvwhVHpX_m2eEM3jmYF0YpgVOiY","3":200,"4":112},"3":{"1":"Yummypets","2":"https://www.yummypets.com/mag/2013/08/02/11279/a-few-fun-facts-about-cats","3":"A few fun facts about cats! - Yummypets","4":"A few fun facts about cats!","10":"abfnJMfahgkwRm"},"5":{"1":"LgiWDdvJnjKfhEb"}},{"1":{"1":"https://static.independent.co.uk/s3fs-public/thumbnails/image/2016/02/25/13/cat-getty_0.jpg?w968h681","3":968,"4":681},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsey-RjxxJtFRzTkCUUQp4em18r93OWP0tvIGf-W9jkq1R9-zd","3":200,"4":140},"3":{"1":"The Independent","2":"https://www.independent.co.uk/news/science/cat-experts-reveal-the-meaning-behind-different-meows-a6895251.html","3":"Cat experts reveal the meaning behind different meows | The ...","4":"Cat's typical meow sounds can be friend or – shocker – demanding","10":"jgcQCeHiOQIDbM"},"5":{"1":"MjXqsEobUlMmfLt"}},{"1":{"1":"https://66.media.tumblr.com/53f218922ce36eb3957c8b959056f1a9/tumblr_n93t8amQUU1s8za4to1_1280.jpg","3":1067,"4":1600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQDmhgMW6xaIDtGTqv6VCQgdKIs04I70koEXRO-C2V-PkUU2I2y","3":133,"4":200},"3":{"1":"Tumblr","2":"http://dailycatistanbul.tumblr.com/","3":"Daily Cat Istanbul","4":"Dear followers, we got some great news. We decided to start a new cat","10":"IvDLbjNNOryhbS"},"5":{"1":"rYckeHyARYEbbeR"}},{"1":{"1":"https://www.abc.net.au/news/image/8633778-3x2-700x467.jpg","3":700,"4":467},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKTb2ah9He3-Xo9Hme0yacwxLRQaF2NEypbBITEWVqLWjBCjxO","3":200,"4":133},"3":{"1":"ABC","2":"https://www.abc.net.au/news/2018-08-09/toxoplasmosis-killing-tasmanian-wildlife/10093038","3":"Cats blamed for spread of native wildlife-killing ...","4":"A close up of a feral cat snarling at the camera.","10":"KXxoHJqlfICMDU"},"5":{"1":"gUDcoTovICjNepP"}},{"1":{"1":"https://www.bluecross.org.uk/sites/default/files/assets/images/112970lpr.jpg","3":2000,"4":1331},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSdk_hAs_ErbyX2hIej7d8tFygdcqiFk-dhSqzDHLhs4dxCfQ3q8w","3":200,"4":133},"3":{"1":"Blue Cross","2":"https://www.bluecross.org.uk/pet-advice/cat-flu","3":"Cat Flu | Symptoms, Causes, and Treatment | Blue Cross","4":"","10":"tvreuIdeESOHnF"},"5":{"1":"RnLSXADdWcyXYpP"}},{"1":{"1":"https://i.guim.co.uk/img/media/0b974a22ecd3807e87b92a90f9f0aa43d61bb6a2/0_223_3425_2056/master/3425.jpg?width=300&quality=85&auto=format&fit=max&s=d198019642f0a69970aeabd0f3f1cca9","3":300,"4":180},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVXkjXSAyfe6sOqBzO3Hs89SRE_HPo7Kzkz4OBrDyJm53_9u9B","3":200,"4":120},"3":{"1":"The Guardian","2":"https://www.theguardian.com/science/2018/jul/24/pets-at-home-do-cats-and-dogs-really-fight-like-cats-and-dogs","3":"Pets at home: do cats and dogs really fight like cats and ...","4":"Cat and dog sleeping together.","10":"esrjymQlNJECVQ"},"5":{"1":"rvPqIPGkumxGfAy"}},{"1":{"1":"http://bdfjade.com/data/out/81/5865451-images-of-cats.jpg","3":960,"4":640},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ6WnsQqx0e_YvExPhGnIJ7jDYjfHYPczkXfq7EVBnGFGDy1aRG0g","3":200,"4":133},"3":{"1":"BDFjade","2":"http://bdfjade.com/images-of-cats.html","3":"Images Of Cats - BDFjade","4":"Great HD Backgrounds Collection of Cats : 960x640 px, 31 March 2018","10":"sJVYDputioFjCH"},"5":{"1":"ALTNohaJtwEMeMU"}},{"1":{"1":"https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/549585-istock-909106260.jpg?itok=ds7LqH1N&resize=1100x1100","3":1100,"4":619},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRNivVznOF2iMAOTxkbkGFlENUk0T3PupKcmuqnMHvr6ASROiXF3w","3":200,"4":112},"3":{"1":"Mental Floss","2":"http://mentalfloss.com/article/549585/science-backed-tips-for-getting-a-cat-to-like-you","3":"10 Science-Backed Tips for Getting a Cat to Like You | Mental ...","4":"iStock","10":"yMAcOJDdqOGiPX"},"5":{"1":"RgbiAhAWIGlcxot"}},{"1":{"1":"https://cf.ltkcdn.net/cats/images/std/214162-672x450-sickcat2.jpg","3":672,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQArG5eajQAFbAnEW89M-JKMxvnWKGwvfkk3C6G7s_aEr4lSd_z0g","3":200,"4":134},"3":{"1":"Cats - LoveToKnow","2":"https://cats.lovetoknow.com/Symptoms_of_a_Dying_Cat","3":"6 Symptoms of a Dying Cat","4":"sick cat","10":"xhCRTUnAklObRo"},"5":{"1":"PaPmYFaioiXrPId"}},{"1":{"1":"https://www.telegraph.co.uk/content/dam/women/2018/01/30/TELEMMGLPICT000152840203_trans_NvBQzQNjv4BqqVzuuqpFlyLIwiB6NTmJwViJj1eTvcjzL4JkNP_PJEs.jpeg?imwidth=450","3":480,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTIDDev27kU_mpiZieiFS2GLloZrjUJ9u4UIwN1VT-kgYng1rmi","3":200,"4":124},"3":{"1":"The Telegraph","2":"https://www.telegraph.co.uk/women/life/black-cats-life-not-just-selfies/","3":"Black cats are for life - not just for selfies","4":"Black cat","10":"gkOewILuUIvjXT"},"5":{"1":"lJurAURRDqWVCbg"}},{"1":{"1":"https://d3i6fh83elv35t.cloudfront.net/static/2018/04/cats-and-dogs_AdobeStock_84016419-1200x798.jpeg","3":1200,"4":798},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTifShE2NmndOYRU4Rx1EqTaW6s6Wil1HDjAD6zGxYB0Rw0MW3X","3":200,"4":133},"3":{"1":"PBS","2":"https://www.pbs.org/newshour/science/which-are-smarter-cats-or-dogs-we-asked-a-scientist","3":"Which are smarter, cats or dogs? We asked a scientist | PBS ...","4":"Which are smarter, cats or dogs? We asked a scientist | PBS NewsHour","10":"qegkjvsTYSvuHn"},"5":{"1":"rmSDrQGBgNmRutj"}},{"1":{"1":"https://cnet4.cbsistatic.com/img/Qqn2oPvTkSKUkTWImHSLYglPYSw=/970x0/2014/01/12/b3815b11-8533-11e3-bc97-14feb5ca9861/cats9.png","3":970,"4":495},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQOrnbAPdbxfR92s6_fhv2L7-iPdF1fp-hGDJ3EVAE0WiURylwYiQ","3":200,"4":101},"3":{"1":"CNet","2":"https://www.cnet.com/news/scientist-cats-think-you-are-just-a-big-stupid-cat/","3":"Scientist: Cats think you are just a big, stupid cat - CNET","4":"He thinks we're stupid. compilarizTVi/YouTube Screenshot by Chris  Matyszczyk/CNET","10":"AqoknMTexdNcKA"},"5":{"1":"BqwNiVVuhSkDFNc"}},{"1":{"1":"https://petplaceimages-embracepetinsura1.netdna-ssl.com/wp-content/uploads/2017/10/nano_nastasia-324812-1024x678.jpg?x35507","3":1024,"4":678},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQnjNGXLc5f9Gxz-kOa1rfnfThxvD24WE2IG3SN3ZeTTHnzjE9q","3":200,"4":132},"3":{"1":"PetPlace","2":"https://www.petplace.com/article/cats/pet-behavior-training/how-mother-cats-take-care-of-kittens/","3":"How Mother Cats Take Care of Kittens - PetPlace","4":"how mother cats take care of kittens","10":"fstbGCbnKklCWs"},"5":{"1":"YGRvshjgiPcnHfD"}},{"1":{"1":"https://news.nationalgeographic.com/content/dam/news/photos/000/755/75552.ngsversion.1422285553360.adapt.1900.1.jpg","3":1900,"4":1266},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTz_Sh7LYVHgP9ET4wwXoFSjYv-5A4P80-8ffTTluC4c3FnOVmj","3":200,"4":133},"3":{"1":"Latest Stories - National Geographic","2":"https://news.nationalgeographic.com/news/2014/01/140127-cats-pets-animals-nation-dogs-people-science/","3":"What Do Cats Think About Us? You May Be Surprised","4":"","10":"VphispWPumbBiE"},"5":{"1":"TVkNslFGDNKKIRM"}},{"1":{"1":"https://s.abcnews.com/images/Lifestyle/AL_scared_cat_jt_151225_16x9_1600.jpg","3":1600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSdu_tIfOlHoq3_A60curgxLzwIkcOWyK8uLa4R0rBwbDNfvkyFzQ","3":200,"4":112},"3":{"1":"ABC News - Go.com","2":"https://abcnews.go.com/Lifestyle/scaredy-cats-absolutely-terrified-cucumbers/story?id=35953032","3":"Why These Scaredy Cats Are Absolutely Terrified of Cucumbers ...","4":"Why These Scaredy Cats Are Absolutely Terrified of Cucumbers - ABC News","10":"cBroNeBtkONFKK"},"5":{"1":"qSJAkXaVsSBWYpO"}},{"1":{"1":"https://images-gmi-pmc.edge-generalmills.com/fe558022-4544-458f-aaa0-eda0de1bcf99.jpg","3":800,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQHlociyYPIGxVhWpLE6zq1Bpec1Db96iFfIx69a_3gR4NA43D","3":200,"4":112},"3":{"1":"Betty Crocker","2":"https://www.bettycrocker.com/recipes/chocolate-mousse/25446b27-770f-4d48-babd-5315521b0e7b","3":"Chocolate Mousse","4":"Chocolate Mousse","10":"ybuCFRCjuKtQQs"},"5":{"1":"xLDKoBGBGbKjeYL"},"7":{"1":{"9":{"1":4.5,"2":70,"3":"Chocolate Mousse","4":["4 large egg yolks Save $","1/4 cup sugar Save $","2 1/2 cups whipping (heavy) cream Save $","8 oz semisweet baking chocolate, chopped Save $"],"5":"Don’t be intimidated by the fancy French name. If you’ve ever heated milk  on the stove for hot ...","6":"2 hr 20 min","7":"8"}}}},{"1":{"1":"https://img.taste.com.au/I3x-cteh/taste/2010/01/chocolate_mousse_in_minutes_1980x1320-117905-1.jpg","3":1980,"4":1320},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSjxU2jUDK8GVZgZM5rAnnMvSYf_sYBLqtPMq5vjF9-euHoSC6qhA","3":200,"4":133},"3":{"1":"Taste","2":"https://www.taste.com.au/recipes/chocolate-mousse-minutes/e5b571f4-3a16-4f5d-ad95-89479e3763c1","3":"Chocolate mousse in minutes","4":"","10":"pbcxpwBJAJMHYv"},"5":{"1":"NNkYCBkxSTXdNnP"},"7":{"1":{"9":{"1":4.699999809265137,"2":190,"3":"Chocolate mousse in minutes","4":["300g good-quality dark chocolate, roughly chopped","3 eggs, at room temperature","1/4 cup (55g) CSR Caster Sugar","1 tablespoon good-quality cocoa powder, sifted","300ml thickened cream, plus extra whipped cream to serve"],"5":"The middle of the week is a very good time to try out this tasty treat.  It's the perfect pick-me-up, ...","6":"1 hr 35 min","7":"6"}}}},{"1":{"1":"https://bellyfull.net/wp-content/uploads/2018/02/Chocolate-blog-2.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJ7XuEBk6X58uxaghaiTqKBZgX7mE7ZfIeF5lKk-4KOICx7wZJNw","3":133,"4":200},"3":{"1":"Belly Full","2":"https://bellyfull.net/2018/02/03/simple-chocolate-mousse/","3":"Simple Chocolate Mousse","4":"","10":"LfmiAQAfQXpXHC"},"5":{"1":"QFxRiEmhawOSIxG"},"7":{"1":{"9":{"3":"Simple Chocolate Mousse","4":["1/2 cup ((4 ounces) Signature Kitchens semi-sweet chocolate chips)","1/8 teaspoon salt","1/4 teaspoon espresso powder ((optional))","1/2 cup Lucerne© whole milk","1 cup chilled Lucerne© heavy whipping cream"],"5":"This Simple Chocolate Mousse only requires 6 ingredients and 10 minutes of  prep. It’s so easy and ...","6":"3 hr 10 min","7":"4"}}}},{"1":{"1":"https://www.abeautifulplate.com/wp-content/uploads/2018/02/easy-chocolate-mousse-5-600x900.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ2dAsuDHYcQac9pwFNVAwn-_f1s2mqBWR5t4Yw-H4eeG_9Rj0V2Q","3":133,"4":200},"3":{"1":"A Beautiful Plate","2":"https://www.abeautifulplate.com/easy-chocolate-mousse/","3":"Easy Chocolate Mousse","4":"Easy Chocolate Mousse","10":"BiTHkoAwtsNrVr"},"5":{"1":"cKgNDtTbgMtFbJt"},"7":{"1":{"9":{"3":"Easy Chocolate Mousse","4":["1 cup (125 grams) semisweet chocolate chips, divided*","1 cup (240 mL) heavy whipping cream","1/2 cup (70 grams) roasted salted almonds","1/2 teaspoon ground cinnamon","2 large egg whites"],"5":"This EASY Chocolate Mousse recipe is made with two ingredients (heavy cream  and chocolate chips) and ...","6":"1 hr 30 min","7":"4-6 Servings"}}}},{"1":{"1":"https://bromabakery.com/wp-content/uploads/2017/04/Secretly-Healthier-Chocolate-Mousse-2.jpg","3":1143,"4":1600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStM5KBU-JE3CFkjJ3v5pIdc1M-AxyOphnMK-5JGmBrPG27g-f-Iw","3":142,"4":200},"3":{"1":"Broma Bakery","2":"https://bromabakery.com/2017/04/secretly-healthier-chocolate-mousse.html","3":"Secretly Healthier Chocolate Mousse - Broma Bakery","4":"A rich chocolate mousse made healthier with a secret ingredient! Best part?  You can","10":"BHymqaDWivlkyx"},"5":{"1":"fLxHmOAaRyapPXw"}},{"1":{"1":"https://assets.marthastewart.com/styles/video-preview-1280x720-highdpi/d32/ST0022%20-%20Chocolate%20Mousse%20vTHUMB/ST0022%20-%20Chocolate%20Mousse%20vTHUMB.jpg?itok=cbp5Ehuk","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvtgWrMXfj6BxSzuFQ93R7-1uytxwtVzRHPzSlH4KhVMcnWAtC","3":200,"4":112},"3":{"1":"Martha Stewart","2":"https://www.marthastewart.com/336783/chocolate-mousse","3":"Chocolate Mousse","4":"ST0022 - Chocolate Mousse vTHUMB.jpg?itok=cbp5Ehuk","10":"NutFHbrFCImUim"},"5":{"1":"bycFEyvjoTPumhG"},"7":{"1":{"9":{"1":3.6500000953674316,"2":397,"3":"Chocolate Mousse","4":["4 large egg yolks","4 tablespoons sugar","2 cups heavy cream","8 ounces bittersweet chocolate, melted","1 teaspoon vanilla extract"],"5":"Because bittersweet chocolate is high in pure chocolate (at least 35  percent cocoa solids), it's ...","6":"1 hr","7":"6 servings"}}}},{"1":{"1":"https://s3.amazonaws.com/finecooking.s3.tauntonclud.com/app/uploads/2017/04/18133529/051097025-01-chocolate-mousse-main.jpg","3":600,"4":500},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZDxQWfTZxel5L8IGA5kmuEhUf0at1gSY3mYa95nfuZsPu1GzpQA","3":200,"4":166},"3":{"1":"Fine Cooking","2":"https://www.finecooking.com/recipe/real-chocolate-mousse","3":"Real Chocolate Mousse","4":"Scott Phillips","10":"SuOsgrwyRsQCsU"},"5":{"1":"SGIexlfsTALIWVA"},"7":{"1":{"9":{"1":4.199999809265137,"2":17,"3":"Real Chocolate Mousse","4":["6 oz. semisweet or bittersweet chocolate, preferably 60% to 62% cacao,  chopped","2 Tbs. unsalted butter, cut into 8 pieces","3 large egg whites","Pinch of table salt","3 Tbs. granulated sugar"],"7":"four. servings"}}}},{"1":{"1":"https://www.tasteaholics.com/wp-content/uploads/2017/09/double-chocolate-mousse-cover-1.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh1ImOygeqktM6K35eQYxWZbRg6_uaLc_VriqCi1hgS5BLEdq6","3":133,"4":200},"3":{"1":"Tasteaholics","2":"https://www.tasteaholics.com/recipes/desserts/5-ingredient-double-chocolate-mousse/","3":"5 Ingredient Double Chocolate Mousse","4":"","10":"EPEhuvnfjwVDhN"},"5":{"1":"UXrmrAwWqlkymUy"},"7":{"1":{"9":{"1":5.0,"2":62,"3":"5 Ingredient Double Chocolate Mousse","4":["1 oz. Lily's Chocolate Chips","1 cup heavy cream","4 oz. cream cheese","1/4 cup powdered erythritol","2 tbsp cocoa powder"],"5":"Macros per serving:, • 469 Calories, • 45g of Fat, • 7g of Protein, • 5g of  Net Carbs","6":"25 min","7":"2"}}}},{"1":{"1":"https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/basicchocolatemousse_93648_16x9.jpg","3":832,"4":468},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRKrk3KulomPwWQnKu6t9MnylAF_DLFHmVrrBJf0IBsrW629-GLA","3":200,"4":112},"3":{"1":"BBC.com","2":"https://www.bbc.com/food/recipes/basicchocolatemousse_93648","3":"Raymond Blanc's chocolate mousse","4":"Raymond Blanc's chocolate mousse","10":"yxUNLYxInwbjDF"},"5":{"1":"OLQFjjusGwNwcOL"},"7":{"1":{"9":{"3":"Raymond Blanc's chocolate mousse","4":["170g/6oz good-quality dark chocolate, minimum 60 per cent cocoa solids,  roughly chopped (dairy free, if necessary)","7 free-range egg whites (use pasteurised egg white in a carton if you have  any concerns about raw egg)","¼ tsp lemon juice","40g/1½oz caster sugar"],"5":"Raymond Blanc shows you how to make an easy, 4-ingredient chocolate mousse  with his classic recipe.","6":"2 hr 10 min","7":"Serves 4"}}}},{"1":{"1":"https://hungryhappenings.com/wp-content/uploads/2018/02/best-chocolate-mousse-recipe-2.jpg","3":680,"4":680},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtvhxHmITq5xO-0RTBo7hG4x-F_EomgloDEDqJBFN9IiliLhTj","3":200,"4":200},"3":{"1":"Hungry Happenings","2":"https://hungryhappenings.com/best-chocolate-mousse-recipe/","3":"The BEST Chocolate Mousse Recipe","4":"Best Chocolate Mousse Recipe","10":"LIjeWQhQdqrgNx"},"5":{"1":"cbkeWAaBITGNFCV"},"7":{"1":{"9":{"1":5.0,"2":3,"3":"The BEST Chocolate Mousse Recipe","4":["3 tablespoons water","3 tablespoons sugar","3 large egg yolks","1/2 cup heavy whipping cream","12 ounces melted semi-sweet chocolate"],"5":"The most luxuriously creamy and smooth chocolate mousse recipe you'll ever  try.","6":"25 min","7":"8"}}}},{"1":{"1":"https://d39ziaow49lrgk.cloudfront.net/wp-content/uploads/2016/10/Chocolate-Mousse-final-1.jpg","3":744,"4":631},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgRx52xBN3wpTcEVufSuHKp3Hb8LGrbLBYIl6eXUJKYVhxQha4_g","3":200,"4":169},"3":{"1":"PaleoHacks","2":"https://blog.paleohacks.com/chocolate-mousse-recipe/","3":"Healthy Dark Chocolate Mousse Recipe","4":"Chocolate-Mousse-final-1.jpg","10":"bVpNOeqinghWQH"},"5":{"1":"DKAQSLoCFRxkRcR"},"7":{"1":{"9":{"3":"Healthy Dark Chocolate Mousse Recipe","4":["7 oz dark chocolate, roughly chopped","1 1/2 cans coconut milk, refrigerated overnight","1/4 cup raw honey","1/4 cup cocoa powder","Seeds from one fresh vanilla pod"],"5":"Meet the creamiest, richest mousse you’ve ever tasted. Dairy-free and  packed with antioxidant dark ...","6":"8 min"}}}},{"1":{"1":"https://www.seriouseats.com/recipes/images/2017/11/20171023-chocolate-mousse-vicky-wasik-20-1500x1125.jpg","3":1500,"4":1125},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTC5kDBJ5vNlrzibyZARnUvcjTkadfd3-LpLwnccHpgZv_kc3L7","3":200,"4":149},"3":{"1":"Serious Eats","2":"https://www.seriouseats.com/recipes/2017/12/eggless-chocolate-mousse.html","3":"Eggless Chocolate Mousse Recipe","4":"","10":"dmuXXylWkryNKF"},"5":{"1":"AugXlPfvEvKuJqI"},"7":{"1":{"9":{"3":"Eggless Chocolate Mousse Recipe","4":["For the Base:","7 ounces plain or toasted sugar (1 cup; 195g)","2 ounces Dutch cocoa powder, such as Cacao Barry Extra Brute (about 2/3  cup, spooned; 55g)","1/4 teaspoon (1g) Diamond Crystal kosher salt; for table salt, use about  half as much by volume or the same weight","32 ounces milk, any percentage will do (4 cups; 910g)"],"5":"The creamy toffee notes of homemade condensed milk set this recipe apart  from the custardy, ...","6":"2 hr 30 min","7":"Six 5 1/2 ounce portions"}}}},{"1":{"1":"https://www.wellplated.com/wp-content/uploads/2016/02/Avocado-Chocolate-Mousse-Vegan-and-Low-Carb.jpg","3":1200,"4":1461},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT93V5GbHolHUlNX-AGoHrgjlvdmij2uRImMX4kCAVZowUoJaFVqw","3":163,"4":200},"3":{"1":"Well Plated","2":"https://www.wellplated.com/avocado-chocolate-mousse/","3":"Avocado Chocolate Mousse","4":"2 Weck jars of Avocado Chocolate Mousse topped with whipped coconut cream  and a fresh raspberry","10":"RcTUITfLyekOnS"},"5":{"1":"QQNfVEMRTtCOPAN"},"7":{"1":{"9":{"1":4.5,"2":17,"3":"Avocado Chocolate Mousse","4":["4 ounces chopped semisweet chocolate or chocolate chips (at least 60%  dark), about 1/2 cup plus 2 tablespoons","2 large, ripe avocados (about 8 ounces each)","3 tablespoons unsweetened cocoa powder","1/4 cup Almond Breeze Unsweetened Almondmilk Cashewmilk Blend","1 teaspoon pure vanilla extract"],"5":"Creamy, rich healthy Avocado Chocolate Mousse made with avocado, dark  chocolate, and maple syrup. ...","6":"10 min","7":"4 generous servings"}}}},{"1":{"1":"https://lovingitvegan.com/wp-content/uploads/2015/09/Peppermint-Chocolate-Mousse-6.jpg","3":1500,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIpRns-4PxKMwUy38BgcoFYma84kl5pV6EFgZGjHNdVhc1MmZrYA","3":200,"4":133},"3":{"1":"Loving It Vegan","2":"https://lovingitvegan.com/vegan-peppermint-chocolate-mousse/","3":"Vegan Peppermint Chocolate Mousse","4":"Vegan Peppermint Chocolate Mousse","10":"jGDHgBoyseXFeG"},"5":{"1":"jlPfQqTOlSGGXmw"},"7":{"1":{"9":{"1":5.0,"2":2,"3":"Vegan Peppermint Chocolate Mousse","4":["Liquid from 1 15oz (425g) can of Chickpeas","1/4 tsp Cream of Tartar","2 Tbsp Powdered Sugar","1/4 tsp Peppermint Extract","7 oz (200g) Vegan Dark Chocolate"],"5":"Amazing vegan peppermint chocolate mousse, the best texture vegan mousse  you've ever had! In just 5 ...","6":"20 min","7":"4"}}}},{"1":{"1":"http://media.foodnetwork.ca/recipetracker/dmm/C/L/Classic_Dark_Chocolate_Mousse_001.jpg","3":460,"4":230},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTn1P0lnbsEmbX1A87YDXQEf10PRs26K_llOYmlnhRvQcpKxHT0","3":200,"4":100},"3":{"1":"Food Network Canada","2":"http://www.foodnetwork.ca/recipe/classic-dark-chocolate-mousse/12736/","3":"Classic Dark Chocolate Mousse","4":"Classic Dark Chocolate Mousse","10":"SWSaYBdApXLyHI"},"5":{"1":"HIVxACCKxQLVDyJ"},"7":{"1":{"9":{"1":2.882352828979492,"2":357,"3":"Classic Dark Chocolate Mousse","4":["7 oz bittersweet chocolate, chopped","2 Tbsp unsalted butter","1 cup whipping cream","¼ cup brewed espresso, cooled","3 Tbsp brandy"],"5":"One taste and you won't be able to stop! Smooth, creamy chocolate mousse  topped with a garnish of ...","6":"1 min","7":"serves 6-8"}}}},{"1":{"1":"https://img.buzzfeed.com/thumbnailer-prod-us-east-1/f36600ff3f7b4c97aaf6760902758ca1/BFV16661_ShrimpAlfredoDinnerForTwoFINAL.jpg?output-quality=60&resize=1000:*","3":1000,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRc8Zp_qw2_0V3Tmlle37pBzezvwfl2f6IQdSkOldl9CUZs_sKNMg","3":200,"4":200},"3":{"1":"Tasty","2":"https://tasty.co/recipe/chocolate-mousse","3":"Chocolate Mousse Recipe by Tasty","4":"Chocolate Mousse","10":"BQWyXvChckhxEJ"},"5":{"1":"eLWfCmNpDypSbiE"},"7":{"1":{"9":{"1":92.0,"2":70,"3":"Chocolate Mousse Recipe by Tasty","4":["1 cup heavy cream","3 tablespoons sugar","2 ounces chocolate, broken into small pieces","¼ cup heavy cream, hot","6 raspberries, to garnish"],"5":"Here's what you need: heavy cream, sugar, chocolate, heavy cream,  raspberry, mint, tube cookie","7":"2 servings"}}}},{"1":{"1":"https://www.saveur.com/sites/saveur.com/files/styles/1000_1x_/public/import/2014/images/2012-09/7-SAV150-78.ChocolateMousse-750x750.jpg?itok=sdcDoBXA","3":1000,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_WevA8nG-msc6riM-VMa_DFWbV0xcW7YIlAnNygK0ARRDLTke","3":200,"4":200},"3":{"1":"Saveur","2":"https://www.saveur.com/article/Recipes/Classic-Chocolate-Mousse","3":"Chocolate Mousse","4":"Chocolate Mousse","10":"kocxNNJLHKeOuC"},"5":{"1":"RvhyvBBheYBakAO"},"7":{"1":{"9":{"3":"Chocolate Mousse","4":["1 2⁄3 cups heavy cream","2 tsp. vanilla extract","1⁄2 tsp. kosher salt","4 egg whites","1⁄2 cup sugar"],"5":"Chocolate mousse, with its light texture and intense chocolate flavor, is a  totally crave-worthy ...","7":"serves 4"}}}},{"1":{"1":"https://food.fnr.sndimg.com/content/dam/images/food/fullset/2006/8/4/0/gl0605_mousse1.jpg.rend.hgtvcom.616.462.suffix/1382538446454.jpeg","3":616,"4":462},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTfsroJofYyl5Y5GlP4M2ODenY8wugz2hFK9RQtgPE1yTG9u3ny","3":200,"4":149},"3":{"1":"Food Network","2":"https://www.foodnetwork.com/recipes/bobby-flay/dark-chocolate-mousse-recipe-1917102","3":"Dark Chocolate Mousse","4":"Dark Chocolate Mousse","10":"ymDXqtyDHGnKex"},"5":{"1":"pPtCrYdSleBYsWu"},"7":{"1":{"9":{"1":4.5,"2":108,"3":"Dark Chocolate Mousse","4":["5 1/4 ounces bittersweet chocolate, coarsely chopped","14 ounces cold heavy cream","3 large egg whites","1-ounce sugar","Sweetened whipped cream, for garnish, optional"],"5":"Get Dark Chocolate Mousse Recipe from Food Network","6":"1 hr 20 min","7":"4 to 6 servings"}}}},{"1":{"1":"https://img.taste.com.au/3WAjhWtK/w720-h480-cfill-q80/taste/2016/11/chocolate-mousse-94477-1.jpeg","3":615,"4":410},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhr-ebNpH6DCz8ruTFyPewWRhFb48vs-caSp4PcIIlU2I7RNxZ","3":200,"4":133},"3":{"1":"Taste","2":"https://www.taste.com.au/recipes/chocolate-mousse-3/94e5c801-c5dc-49cd-9448-c7fc8b342ea6","3":"Chocolate mousse","4":"","10":"EadWIdbGSiBvvy"},"5":{"1":"YXdVQXdgvHEROtk"},"7":{"1":{"9":{"1":4.800000190734863,"2":11,"3":"Chocolate mousse","4":["200g milk chocolate, or dark chocolate, broken","4 eggs, separated","1 tablespoon Kahlua, or other liqueur of choice","300ml carton thickened cream","Whipped cream, extra, to serve"],"5":"It's hard to beat the classics so keep it traditional with this decadent  chocolate mousse treat.","6":"15 min"}}}},{"1":{"1":"https://thetoughcookie.com/wp-content/uploads/2016/06/Salted-Caramel-Chocolate-Mousse-Featured.jpg","3":680,"4":680},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTWRfOMxBP868Tf8ElksLubFwkKxO72o6jGOvW2SfgAJb0oJ1pl","3":200,"4":200},"3":{"1":"The Tough Cookie","2":"https://thetoughcookie.com/2016/06/04/salted-caramel-chocolate-mousse/","3":"Salted Caramel Chocolate Mousse","4":"","10":"CeLWFekJwycRDm"},"5":{"1":"JPMQWbsGqBiKvtG"},"7":{"1":{"9":{"3":"Salted Caramel Chocolate Mousse","4":["100g (or ½ cup) granulated sugar","2 tablespoons of water","80g (or â…“ cup + 1 teaspoon) unsalted butter, cubed","180ml (or ¾ cup) heavy cream","a pinch of table salt"],"5":"A thick layer of golden salted caramel topped with a delicious dark  chocolate mousse. The best!","6":"30 min","7":"6-8"}}}},{"1":{"1":"https://d3cizcpymoenau.cloudfront.net/images/26341/SFS_triple_chocolate_mousse_cake-15.jpg","3":2090,"4":2090},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRxByiQWbCWjcmc-JbrQ9VYr8CtY4ZkshQSg6F91sogjKeKhbkq6g","3":200,"4":200},"3":{"1":"Cook's Illustrated","2":"https://www.cooksillustrated.com/recipes/4958-triple-chocolate-mousse-cake","3":"Triple-Chocolate Mousse Cake","4":"","10":"vtSNnAVjUHgliG"},"5":{"1":"hqlCpdUtkiMSnxi"},"7":{"1":{"9":{"3":"Triple-Chocolate Mousse Cake","5":"To rate a perfect 10, this triple-decker confection would need to lighten  up and lose its one-note ...","7":"Serves 12 to 16"}}}},{"1":{"1":"https://www.thecookierookie.com/wp-content/uploads/2014/12/white-chocolate-mousse-8.jpeg","3":680,"4":859},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS96fuqccB37YN9XDwYbTYVoh5y9kKhq6WU2rfERutMWCKY14uI","3":158,"4":200},"3":{"1":"The Cookie Rookie","2":"https://www.thecookierookie.com/easy-white-chocolate-mousse/","3":"Super Easy White Chocolate Mousse","4":"White Chocolate Mousse layered into small glass jars","10":"cTpbSarnLdFYPE"},"5":{"1":"DInTFakOHyPQldd"},"7":{"1":{"9":{"1":4.599999904632568,"2":5,"3":"Super Easy White Chocolate Mousse","4":["12 ounces White Chocolate (chopped (you can also use dark or milk  chocolate))","1 1/2 cups heavy cream (divided)","Mini chocolate chips (optional (you can also use chopped fruit or other  garnishes you might like))"],"5":"White Chocolate Mousse is just so rich and creamy! There's nothing better  than a SUPER Easy White ...","6":"15 min","7":"6"}}}},{"1":{"1":"https://assets.epicurious.com/photos/54c94a9b1f13bb9b2edf4c3c/master/pass/51230220_olive-oil-dark-chocolate-mousse_6x4.jpg","3":1625,"4":1084},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMVVdshojOMfYOX7lMBM4GovM28xqkyyj2Gy0l5W5uLQgZdqR","3":200,"4":133},"3":{"1":"Epicurious","2":"https://www.epicurious.com/recipes/food/views/olive-oil-dark-chocolate-mousse-51230220","3":"Olive Oil Dark Chocolate Mousse","4":"","10":"dwOlpracQRKTAG"},"5":{"1":"XhpxHwGmQQlsOhN"},"7":{"1":{"9":{"1":4.0,"2":9,"3":"Olive Oil Dark Chocolate Mousse","4":["10 ounces high-quality 72% cacao bittersweet chocolate, finely chopped, or  chocolate chips","8 large eggs, separated, at room temperature","3/4 cup granulated sugar","1/2 cup extra virgin olive oil","1 teaspoon instant coffee granules dissolved in 2 tablespoons boiling water"],"5":"Kosher Status: Pareve I first learned about using fruity, high-quality  olive oil in ...","7":"6 servings"}}}},{"1":{"1":"http://www.ndtv.com/cooks/images/chocolate.mousse.jpg","3":620,"4":330},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSpzzGQYH5M9gmwVRkNDjGERaJyhUjLmxmCFuZYcMePG_97vyMD","3":200,"4":106},"3":{"1":"NDTV Food","2":"https://food.ndtv.com/recipe-eggless-chocolate-mousse-219658","3":"Eggless Chocolate Mousse Recipe","4":"Eggless Chocolate Mousse","10":"RRNhbBNmtNxLSg"},"5":{"1":"yBXDaMTanHBfkrA"},"7":{"1":{"9":{"1":5.0,"2":2,"3":"Eggless Chocolate Mousse Recipe","4":["2 cups hot milk","1 cup sugar","100 gm plain milk chocolate","1 cup cream-chilled","1 Tbsp gelatine"],"5":"Whip up a light and creamy chocolate mousse without eggs.","6":"1 hr 15 min","7":"4"}}}},{"1":{"1":"https://assets.marthastewart.com/styles/wmax-1500/d31/chocolate-mousse-0106-mla101821/chocolate-mousse-0106-mla101821_sq.jpg?itok=6_pcUxej","3":1500,"4":1500},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTK8e6IYmJkxBVn7akLOD6mI3T1r3uThbRu5rU7aBND0gh9N9AP6A","3":200,"4":200},"3":{"1":"Martha Stewart","2":"https://www.marthastewart.com/315307/individual-chocolate-mousse","3":"Individual Chocolate Mousse","4":"","10":"AGdFyQHJPdNaCy"},"5":{"1":"EeCnVxqGEXBvcYu"},"7":{"1":{"9":{"1":3.450000047683716,"2":95,"3":"Individual Chocolate Mousse","4":["3 1/3 cups heavy cream","8 large egg yolks, room temperature","1/2 cup sugar","1/4 cup light corn syrup","7 ounces bittersweet chocolate, melted"],"5":"This recipe makes two kinds of mousse: bittersweet chocolate and milk  chocolate.","6":"0 min","7":"Makes enough for 8 cakes"}}}},{"1":{"1":"https://cook.fnr.sndimg.com/content/dam/images/cook/fullset/2012/2/10/0/ek0109_mouse4.jpg.rend.hgtvcom.616.462.suffix/1391099484102.jpeg","3":616,"4":462},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRkHF2cBoiaNktwB_hF1d6oFUzz_FvmcICCsx3nI9rfyPEeH2KU","3":200,"4":149},"3":{"1":"Cooking Channel","2":"https://www.cookingchanneltv.com/recipes/ellie-krieger/dark-chocolate-mousse-1945893","3":"Dark Chocolate Mousse","4":"Dark Chocolate Mousse","10":"LJqbDRJGwUPsht"},"5":{"1":"kHhNwbUGEsncjCS"},"7":{"1":{"9":{"3":"Dark Chocolate Mousse","4":["1 (12.3-ounce) package silken tofu, drained","3 ounces high quality bittersweet chocolate, finely chopped","1/4 cup unsweetened cocoa powder, preferably Dutch-processed","1/4 cup water","1 tablespoon brandy"],"5":"Cooking Channel serves up this Dark Chocolate Mousse recipe from Ellie  Krieger plus many other ...","6":"1 hr 20 min","7":"5 servings"}}}},{"1":{"1":"https://www.deliaonline.com/sites/default/files/quick_media/chocolate-a-very-chocolatey-mousse.jpg","3":1348,"4":1542},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEx0oq8mkc2n2EtHhIRzN5rAYJlhsSftegHcaRrZ0Rup8dn_xJSQ","3":175,"4":200},"3":{"1":"Delia Online","2":"https://www.deliaonline.com/recipes/international/european/french/a-very-chocolatey-mousse","3":"A Very Chocolatey Mousse","4":"","10":"UgfjqXPRIGcnJs"},"5":{"1":"QmtOOeQtnaucgGr"},"7":{"1":{"9":{"3":"A Very Chocolatey Mousse","4":["7 oz (200 g) dark chocolate (75 per cent cocoa solids), broken into pieces","4fl oz (120ml) warm water","3 large eggs, separated","1½ oz (40 g) golden caster sugar","a little whipped cream (optional)"],"5":"This was the chocolate recipe of the 1960s, but it has now, sadly, been  eclipsed by other eras and ...","7":"Serves 6"}}}},{"1":{"1":"https://www.healthymummy.com/wp-content/uploads/2016/07/Mousse.jpg","3":960,"4":705},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS0eNWtlljCNY2Rz1V3tYBFpmv-cAH6t1DRbl4gCyNU7zAxCLBm","3":200,"4":146},"3":{"1":"The Healthy Mummy","2":"https://www.healthymummy.com/recipe/coconut-chocolate-mousse/","3":"Coconut and Chocolate Mousse","4":"Chocolate Mousse","10":"sOLpVJIlJNwjMs"},"5":{"1":"rpCMjBTUjAxYQgM"},"7":{"1":{"9":{"3":"Coconut and Chocolate Mousse","4":["400 ml can of coconut cream","5 tbsp good quality cocoa or cacao","4 tbsp honey or rice malt syrup","1 tsp vanilla bean paste or vanilla essence","1 tsp cinnamon"],"5":"Read our delicious recipe for Healthy One Bowl Coconut and Chocolate  Mousse, a recipe from The ...","7":"6 people"}}}},{"1":{"1":"https://platedcravings.com/wp-content/uploads/2018/02/Easy-Chocolate-Mousse-Recipe-Plated-Cravings-8-500x375.jpg","3":500,"4":375},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS4cS4DoviXJBXThmsL3j4w_I27aYWW_tYU7-DaFeCCsvF1B4VUug","3":200,"4":149},"3":{"1":"Plated Cravings","2":"https://platedcravings.com/easy-chocolate-mousse-recipe/","3":"Easy Chocolate Mousse Recipe","4":"","10":"expJObPwmlJAkU"},"5":{"1":"TBHCrHANrOnGqPH"},"7":{"1":{"9":{"1":5.0,"2":3,"3":"Easy Chocolate Mousse Recipe","4":["8 oz. semisweet chocolate (chopped)","1 tsp vanilla extract","1 pinch salt","3 cups heavy cream (divided)","1/4 cup powdered sugar"],"5":"This easy Chocolate Mousse recipe is super simple to make from scratch and  deliciously light and ...","6":"16 min","7":"8"}}}},{"1":{"1":"https://assets.epicurious.com/photos/583f3202e5ba7cdd0eb88201/master/pass/chocolate-mousse-pie.jpg","3":1000,"4":664},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS7MZyR4OdCuZhRTKrQxwfPhYFXwNRNP2PTBsGDiPykDzyVG2EH","3":200,"4":132},"3":{"1":"Epicurious","2":"https://www.epicurious.com/recipes/food/views/chocolate-mousse-pie-2687","3":"Chocolate Mousse Pie","4":"","10":"luvhIBOrsyqWKK"},"5":{"1":"XXfxypeCTaISdwC"},"7":{"1":{"9":{"1":4.0,"2":204,"3":"Chocolate Mousse Pie","4":["21 chocolate sandwich cookies (such as Oreos)","1/4 cup (1/2 stick) unsalted butter, cut into pieces, room temperature","12 ounces semisweet chocolate, finely chopped","1 teaspoon vanilla extract","Pinch of salt"],"5":"A quick and easy Chocolate Mousse Pie recipe","7":"Serves 8"}}}},{"1":{"1":"https://tipbuzz.com/wp-content/uploads/Raspberry-and-Chocolate-Mousse.jpg","3":735,"4":1102},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAAlQj6exF8tP1gKJk7jSkcXfK08AK3kpmGjXdEjN7NMa3ykS9","3":133,"4":200},"3":{"1":"TipBuzz","2":"https://tipbuzz.com/raspberry-chocolate-mousse/","3":"Easy Raspberry And Chocolate Mousse (with Video)","4":"Raspberry And Chocolate Mousse – looks so elegant with two layers and  tastes so delicious that","10":"dclspGcVrDXGBd"},"5":{"1":"dYwBNIssOSlaJEA"},"7":{"1":{"9":{"1":3.799999952316284,"2":94,"3":"Easy Raspberry And Chocolate Mousse (with Video)","4":["3 oz raspberry jello powder (1 small box)","1 cup boiling water","1/2 cup cold water","2 cups whipped cream (see note) (or Cool Whip)","1/2 cup half and half milk"],"5":"This Raspberry Chocolate Mousse is a delicious dessert with a stunning  presentation in stemless wine ...","6":"2 hr 35 min","7":"6 servings"}}}},{"1":{"1":"https://tastesbetterfromscratch.com/wp-content/uploads/2014/05/Chocolate-Cake-Chocolate-Mousse-8.jpg","3":683,"4":1024},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUJwrzOlkPXRGMw2MPkh8T6-iHmD_CO4FmbmCYpnCVAxbrHzAV","3":133,"4":200},"3":{"1":"Tastes Better from Scratch","2":"https://tastesbetterfromscratch.com/chocolate-cake-with-chocolate-mousse/","3":"Chocolate Cake with Chocolate Mousse Filling","4":"A slice of homemade chocolate cake with layers of chocolate mousse filling,  on a white","10":"lWreJgKIYKdycU"},"5":{"1":"iIctMJsvSGSSOTp"},"7":{"1":{"9":{"1":4.630000114440918,"2":27,"3":"Chocolate Cake with Chocolate Mousse Filling","4":["2 cup granulated sugar","1 3/4 cup all-purpose flour","3/4 cup unsweetened cocoa powder","1 1/2 teaspoon baking powder","1 1/2 teaspoon baking soda"],"5":"A delicious, moist chocolate cake with layers of dark chocolate mousse  filling and a warm chocolate ...","6":"2 hr 5 min","7":"15"}}}},{"1":{"1":"http://kitchenconfidante.com/wp-content/uploads/2012/02/Triple-Chocolate-Mousse-Kitchen-Confidante1.jpg","3":520,"4":781},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSC3nD5-E47uUf93VYRZrJ-nBGqR6OVd8O1U1dtArebfVLEgfTEjQ","3":133,"4":200},"3":{"1":"Kitchen Confidante","2":"https://kitchenconfidante.com/triple-chocolate-mousse-recipe","3":"Triple Chocolate Mousse","4":"Triple Chocolate Mousse","10":"bKqDNOFFguSowI"},"5":{"1":"iMaNKBNgKYsQQTB"},"7":{"1":{"9":{"3":"Triple Chocolate Mousse","5":"Now you know me, I don’t need a holiday as an excuse to make anything  chocolate-y. But of course, ...","7":"4 (generous) servings."}}}},{"1":{"1":"https://img.taste.com.au/nGjAovK2/taste/2016/11/layered-chocolate-mousse-cakes-101268-1.jpeg","3":3000,"4":2000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAYC-6BAF1KIL71PDZATnMc8c5P07p7iII3sWPh6JNggu98YW8","3":200,"4":133},"3":{"1":"Taste","2":"https://www.taste.com.au/recipes/layered-chocolate-mousse-cakes/9be6bd0a-fcf6-42ba-8410-a6ba5603d4e8","3":"Layered chocolate mousse cakes","4":"","10":"mFvYouYCpgjdMs"},"5":{"1":"WhnonbUhsFfKCPL"},"7":{"1":{"9":{"1":2.700000047683716,"2":3,"3":"Layered chocolate mousse cakes","4":["200g dark chocolate, chopped","200g butter, chopped","1 1/4 cups (275g) brown sugar","3 Coles Brand Australian Free Range Eggs, lightly whisked","3/4 cup (110g) plain flour"],"5":"A brownie base, chocolate mousse filling and dark chocolate sauce on top.  Can you think of any ...","6":"2 hr 5 min"}}}},{"1":{"1":"https://www.amymyersmd.com/wp-content/uploads/2018/02/Coconut-Cream-Chocolate-Mousse2.jpg","3":1200,"4":630},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2TAHGhBmzxrybZf7rljmVqeay8DwB5BIny97lcZL46tUoPBme","3":200,"4":105},"3":{"1":"Amy Myers MD","2":"https://www.amymyersmd.com/2018/02/coconut-cream-chocolate-mousse/","3":"Coconut Cream Chocolate Mousse","4":"Coconut Cream Chocolate Mousse","10":"CkKFxrlXnhUuhe"},"5":{"1":"lReGEEBDYtdWrEV"},"7":{"1":{"9":{"3":"Coconut Cream Chocolate Mousse","4":["1 can full fat coconut milk","1 Tbsp unsweetened cocoa powder","1/2 tsp vanilla extract","5-10 drops stevia","1 pinch cinnamon"],"5":"Looking for a sweet to enjoy without derailing your protocol? Try this  delicious homemade Coconut ...","7":"1"}}}},{"1":{"1":"https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Fcdn-image.foodandwine.com%2Fsites%2Fdefault%2Ffiles%2F1532533774%2Fultimate-chocolate-mousse-XL-RECIPE0918.jpg&w=1000&q=70","3":1000,"4":1000},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS9YyVHT8dcRWtWpCH85bE8g-00TuL-X8f4BYunjFXEPxU7NadV0g","3":200,"4":200},"3":{"1":"Food & Wine Magazine","2":"https://www.foodandwine.com/recipes/ultimate-chocolate-mousse","3":"Ultimate Chocolate Mousse","4":"Ultimate Chocolate Mousse","10":"yiPtIRsyVupAaY"},"5":{"1":"XoMIQmyxIVUFNOM"},"7":{"1":{"9":{"3":"Ultimate Chocolate Mousse","4":["8 ounces semisweet dark chocolate, broken into 1/2-inch pieces","6 large eggs, separated","3 tablespoon water","1/4 cup sweet liqueur (such as Chartreuse, amaretto, mandarin, or Grand  Marnier)","2 cups heavy cream"],"5":"In 2018, Food & Wine named this recipe one of our 40 best: To celebrate  chocolate in its most ...","6":"4 hr 30 min","7":"Serves : 12"}}}},{"1":{"1":"https://www.cookingclassy.com/wp-content/uploads/2017/11/chocolate-mousse-pie-17.jpg","3":1080,"4":1620},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSUEQeQarCpynWIXm6YbXUWVdiUQ4PVCc0VNxgyh44mEP5jmXPL","3":133,"4":200},"3":{"1":"Cooking Classy","2":"https://www.cookingclassy.com/easy-chocolate-mousse-pie/","3":"Easy Chocolate Mousse Pie","4":"Chocolate Mousse Pie","10":"JyvaMdqWbwqtNE"},"5":{"1":"uYqqOxFFEkbMExh"},"7":{"1":{"9":{"1":4.75,"2":16,"3":"Easy Chocolate Mousse Pie","4":["2 Tbsp salted butter, (diced into 4 pieces)","1 cup semi-sweet chocolate chips*","1/2 cup bittersweet chocolate chips ((or another 1/2 cup semi-sweet if you  don't want it quite as rich))","2 cups mini marshmallows","1/3 cup milk ((whole or 2%))"],"5":"This pie is purely irresistable! It's so chocolatey, so fluffy, so rich, so  creamy. It's absolutely ...","6":"4 hr 20 min","7":"10"}}}},{"1":{"1":"https://www.lifeloveandsugar.com/wp-content/uploads/2017/10/Chocolate-Mousse-Cake4.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm8WGK0UxwFPDDa1t2qB9EQfMVAyBZsg6BYW2yPgOzIk2pKN60Ag","3":133,"4":200},"3":{"1":"Life Love and Sugar","2":"https://www.lifeloveandsugar.com/2017/10/23/chocolate-mousse-cake/","3":"Chocolate Mousse Cake","4":"Chocolate Mousse Cake","10":"LGoFCNeaeWpiwp"},"5":{"1":"qgBJJasKxSTLVEX"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Chocolate Mousse Cake","4":["1 3/4 cups (228g) all purpose flour","2 cups (414g) sugar","3/4 cup (85g) natural unsweetened cocoa powder","2 1/4 tsp baking soda","1/2 tsp baking powder"],"5":"This Chocolate Mousse Cake is a classic! With three layers of moist  chocolate cake and two layers of ...","7":"12-14 Slices"}}}},{"1":{"1":"https://www.sbs.com.au/food/sites/sbs.com.au.food/files/2_3.jpg","3":1872,"4":1248},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQQwUiKk9ItX8NHEVxSPWjDJPmn79D0Gc0osHxQakgcKZ4njP9Cpg","3":200,"4":133},"3":{"1":"SBS","2":"https://www.sbs.com.au/food/recipes/belgian-chocolate-mousse","3":"Belgian chocolate mousse","4":"Belgian chocolate mousse https://www.sbs.com.au/food/recipes/belgian- chocolate-mousse","10":"CckKwtPXnRyCRI"},"5":{"1":"BiMeABecAAqrNOy"},"7":{"1":{"9":{"1":3.695310115814209,"2":256,"3":"Belgian chocolate mousse","5":"You can't get more decadent that this delicious Belgian chocolate dessert  recipe. It's best to make ...","6":"30 min","7":"6"}}}},{"1":{"1":"https://www.willcookforsmiles.com/wp-content/uploads/2014/11/Chocolate-Mousse-3-from-willcookforsmiles.com_.jpg","3":905,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS1IOQlPBqG1_SDmh7qX95Moe5GQ_B_ebSYTQ9IVIxW-s4JBG9R","3":200,"4":132},"3":{"1":"Will Cook For Smiles","2":"https://www.willcookforsmiles.com/chocolate-mousse/","3":"Chocolate Mousse","4":"Chocolate Mousse | from willcookforsmiles.com","10":"tldKqDuSAbXtnQ"},"5":{"1":"EiFGSBRDtQyLvYF"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Chocolate Mousse","4":["8 oz bittersweet baking chocolate","1/2 cup of water (split in two)","2 Tbsp unsalted butter","1 tsp vanilla extract","3 egg yolks"],"5":"Delicate yet rich dessert that goes perfectly for any celebration. This  Chocolate Mousse is made ...","6":"30 min","7":"6 servings"}}}},{"1":{"1":"https://img.taste.com.au/GAoU8PP5/w720-h480-cfill-q80/taste/2012/07/classic-chocolate-mousse-136368-1.jpg","3":720,"4":480},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKSHeb2idq49Hy3ZO1mL17JpQqNgpwZyskllnY8RbCCwQP6rTW8g","3":200,"4":133},"3":{"1":"Taste","2":"https://www.taste.com.au/recipes/classic-chocolate-mousse-2/9acca574-0e7b-4db9-8e75-9e36b02053ee","3":"Classic chocolate mousse","4":"","10":"QPOHNOVliBSibQ"},"5":{"1":"yqCdusrJeBAjAie"},"7":{"1":{"9":{"1":4.5,"2":29,"3":"Classic chocolate mousse","4":["200g dark cooking chocolate, finely chopped","25g butter","3 eggs, separated, at room temperature","1 teaspoon vanilla extract","250ml (1 cup) thickened cream"],"5":"Whip up perfectly smooth mousse in no time with this simple six-step recipe.","6":"25 min","7":"6"}}}},{"1":{"1":"http://www.bite.co.nz/images/recipes/three-ingredient-chocolate-mousse-recipe.jpg?width=1200&height=800","3":1200,"4":800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQW7hnqPuX8_hcn-EPyE8OtghyTdfsltkgs-coaNZDgi_Uy7k8SlA","3":200,"4":133},"3":{"1":"Bite","2":"http://www.bite.co.nz/recipe/15181/Three-ingredient-chocolate-mousse/","3":"Three ingredient chocolate mousse ( SERVES 2 )","4":"","10":"PqUbHOJMJlYeno"},"5":{"1":"nIilfAbGTehhyXU"},"7":{"1":{"9":{"3":"Three ingredient chocolate mousse ( SERVES 2 )","4":["Dark chocolate, ideally at least 70% cocoa solids, coarsely chopped","Cream","Marshmallows, chopped"],"5":"This delicious silken chocolate mousse is very rich, so you'll need only a  small glass or bowl each. ..."}}}},{"1":{"1":"http://assets.kraftfoods.com/recipe_images/opendeploy/53395_640x428.jpg","3":642,"4":428},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-keC9N7eStfilSNUrZU_fPxAJiaFSSro567cUOx0o2Tw1eBjTDw","3":200,"4":133},"3":{"1":"Kraft Recipes","2":"http://www.kraftrecipes.com/recipes/double-chocolate-mousse-recipe-53395.aspx","3":"Double-Chocolate Mousse Recipe","4":"Double-Chocolate Mousse Recipe","10":"OhJFCWUSWhdIlb"},"5":{"1":"yQnWRSTdtypKJiV"},"7":{"1":{"9":{"3":"Double-Chocolate Mousse Recipe","4":["2 oz. BAKER'S Semi-Sweet Chocolate","1-1/2 cups fat-free milk, divided","1 pkg. (1.4 oz.) JELL-O Chocolate Flavor Sugar Free Fat Free Instant Pudding","2 cups thawed COOL WHIP FREE Whipped Topping, divided","1/2 cup fresh raspberries"],"5":"Enjoy this Double-Chocolate Mousse Recipe. It's hard to believe this  luscious Double-Chocolate ...","6":"35 min","7":"6 servings"}}}},{"1":{"1":"https://img.delicious.com.au/sWSoXu5b/h506-w759-cfill/del/2018/05/double-chocolate-mousse-cake-79402-2.jpg","3":759,"4":506},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSdYzkyO8y9vDLut-n0pEa0cbZYOP1tgWTNWqhmmzrz65i6ZltNqg","3":200,"4":133},"3":{"1":"Delicious","2":"https://www.delicious.com.au/recipes/chocolate-mousse-fudge-brownie-cake/ju5kgajg","3":"Chocolate mousse fudge brownie cake","4":"Double-chocolate mousse cake","10":"chqrdknqidKMKM"},"5":{"1":"JMsAPWumpNlEiWY"},"7":{"1":{"9":{"3":"Chocolate mousse fudge brownie cake","4":["500g chocolate fudge brownie packet mix","400g dark (70%) chocolate, chopped","400g milk chocolate, chopped","6 eggs, separated","1 titanium-strength gelatine leaf"],"5":"Double the chocolate, double the deliciousness.","6":"50 min","7":"10"}}}},{"1":{"1":"https://www.creationsbykara.com/wp-content/uploads/2017/10/Easy-Chocolate-Mousse-011-2.jpg","3":800,"4":1055},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQeY3ZLajJbKFus6n9z7MzFf-iGkRXm_sqLwF2zRBlq4u1QBuY","3":151,"4":200},"3":{"1":"Creations by Kara","2":"https://www.creationsbykara.com/easy-chocolate-mousse-3-ingredient/","3":"Easy Chocolate Mousse (3 Ingredient)","4":"Easy 3 ingredient chocolate mousse. A simple but decadent dessert recipe.","10":"yBErsOSUwLpCdn"},"5":{"1":"RydapwVUymANmsv"},"7":{"1":{"9":{"1":5.0,"2":2,"3":"Easy Chocolate Mousse (3 Ingredient)","4":["1 cup good quality chocolate chips","1 cup whipping cream","1 tsp vanilla"],"5":"Rich and creamy chocolate mousse make with just three ingredients.","6":"15 min"}}}},{"1":{"1":"https://glutenfreeonashoestring.com/_main_site/wp-content/uploads/2016/06/closeup.jpg","3":685,"4":937},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ5bzseFXF-3kFO6yc6lE3tIgihZSuj2GBFTFmFG-4uExVZZ1c3ig","3":146,"4":200},"3":{"1":"Gluten Free on a Shoestring","2":"https://glutenfreeonashoestring.com/paleo-chocolate-mousse/","3":"Paleo Chocolate Mousse","4":"Paleo Chocolate Mousse","10":"IlxiFEKvKWUOLA"},"5":{"1":"QkhCQJjwCLeRvOV"},"7":{"1":{"9":{"3":"Paleo Chocolate Mousse","5":"Smooth and creamy Paleo chocolate mousse, made with chocolate, coconut  cream, cocoa powder, honey ...","6":"5 min","7":"4 servings"}}}},{"1":{"1":"https://cdn77-s3.lazycatkitchen.com/wp-content/uploads/2016/07/vegan-black-cherry-chocolate-mousse.jpg","3":1280,"4":1920},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQDdqbIpGTV48CT9YMCuxqbVnVOh_xd9oYffZFryk8Oli6E6OutXA","3":133,"4":200},"3":{"1":"Lazy Cat Kitchen","2":"https://www.lazycatkitchen.com/vegan-black-forest-chocolate-mousse/","3":"Vegan black forest chocolate mousse","4":"","10":"BqwvupophfNFSb"},"5":{"1":"aauwnpVSsGfHjwM"},"7":{"1":{"9":{"1":5.0,"2":2,"3":"Vegan black forest chocolate mousse","4":["170 g / 6 oz dark (70 % cacao) chocolate","135 ml / ½ cup + 1 tbsp gelatinous aquafaba* homemade or from a tin","135 ml / ½ cup + 1 tbsp coconut cream","2 tbsp caster sugar (optional)*","400 g / 14 oz sour or sweet cherries** halved and pitted"],"5":"... is a mean dessert! It's airy, effortlessly impressive and goes superbly  well with a strong ...","6":"30 min","7":"makes: 4"}}}},{"1":{"1":"https://www.annabel-langbein.com/images/blog/easter-made-easy/chocolate-mousse.jpg","3":1772,"4":1243},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ8hDwRc0WBZ6mqvqUfZMJ_U5NXzl_OpWGbBiiDzdtZq83l8xxksw","3":200,"4":140},"3":{"1":"Annabel Langbein","2":"https://www.annabel-langbein.com/recipes/velvet-chocolate-mousse/188/","3":"Velvet Chocolate Mousse - Annabel Langbein – Recipes","4":"","10":"aRUYADVBRKwyvJ"},"5":{"1":"unhFXeGrDhdHrMd"}},{"1":{"1":"https://assets.marthastewart.com/styles/wmax-1500/d37/triple-chocolate-mousse-cakes-a101821/triple-chocolate-mousse-cakes-a101821_horiz.jpg?itok=qjl3Tyyu","3":1324,"4":743},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB6ZucfnwjjD9CxJ17KOVs6CwkP-tXx-BXWXYM9gL0Rm-NBvWK","3":200,"4":112},"3":{"1":"Martha Stewart","2":"https://www.marthastewart.com/317890/triple-chocolate-mousse-cake","3":"Triple-Chocolate Mousse Cakes","4":"","10":"fmyIGBEBfkAXNw"},"5":{"1":"AhgPpPywjIRbTkO"},"7":{"1":{"9":{"1":3.5,"2":643,"3":"Triple-Chocolate Mousse Cakes","4":["Vegetable-oil cooking spray","2/3 cup all-purpose flour","1/3 cup unsweetened Dutch-process cocoa powder","2/3 cup sugar","3/4 teaspoon baking soda"],"5":"With three shades of chocolate, these cakes are as pleasing to the eye as  they are to the sweet ...","6":"0 min","7":"Makes 8"}}}},{"1":{"1":"https://www.chowstatic.com/assets/models/promotions/photos/28768/original/chowhound_white_chocolate_mousse_1.jpg","3":3000,"4":1999},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRo4DyXkcnY-RnA7ZCM-HNSv0YRsZF0b3TNOcXXTHOw2vPcmW7C1A","3":200,"4":133},"3":{"1":"Chowhound","2":"https://www.chowhound.com/recipes/white-chocolate-mousse-blackberry-compote-31821","3":"White Chocolate Mousse with Blackberry Compote","4":"","10":"dvVqXCxdxEmAFx"},"5":{"1":"BrNQDgJTTEJTrPB"},"7":{"1":{"9":{"3":"White Chocolate Mousse with Blackberry Compote","4":["8 ounces white chocolate bars (not morsels or chips)","1½ cup heavy cream","2 egg yolks","6 tablespoons sugar","1 teaspoon cornstarch"],"5":"mousse with blackberry compote","6":"1 hr","7":"4 to 5 servings"}}}},{"1":{"1":"https://tipbuzz.com/wp-content/uploads/Strawberry-Chocolate-Mousse-.jpg","3":1000,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPDe13slz50EIMYV1nBU-r3y0uatneBh-r-0lXpx6KhZyPLfLq","3":200,"4":120},"3":{"1":"TipBuzz","2":"https://tipbuzz.com/strawberry-chocolate-mousse/","3":"Strawberry Chocolate Mousse (with Video)","4":"Strawberry Chocolate Mousse","10":"BKokgkfaoNPyVL"},"5":{"1":"pwVkVPbEXrTqUSm"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Strawberry Chocolate Mousse (with Video)","4":["3 oz strawberry jello powder (1 small box)","1 cup boiling water","2 cups cold water","10 fresh strawberries (chopped)","1/2 cup half and half milk"],"5":"Strawberry Chocolate Mousse is a stunning make-ahead dessert that's perfect  for Valentine's Day, ...","6":"2 hr 35 min","7":"6 servings"}}}},{"1":{"1":"https://www.gnom-gnom.com/wp-content/uploads/2018/08/Low-Carb-Paleo-Keto-Chocolate-Mousse-by-Gnom-Gnom-1.jpg","3":700,"4":700},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS039cF8Xg2EhS8rKf_AX47EpRN8algumwFDSIiQf4Z5e6mmFZeCQ","3":200,"4":200},"3":{"1":"gnom-gnom","2":"https://www.gnom-gnom.com/paleo-keto-chocolate-mousse/","3":"Paleo, Low Carb & Keto Chocolate Mousse","4":"","10":"VINQGoLpoWYnoj"},"5":{"1":"JQQglyLIsPIgjmT"},"7":{"1":{"9":{"1":5.0,"2":6,"3":"Paleo, Low Carb & Keto Chocolate Mousse","4":["1/3 cup full fat coconut milk (*)","2-4 tablespoons xylitol (or sweetener of choice, to taste**)","1-3 tablespoons cocoa powder (use the smaller amount for milk chocolate and  the larger for dark (I use 3!))","pinch espresso powder (or instant coffee, optional)","pinch kosher salt (up to 1/8-1/4 tsp for a 'salted' version (my favorite!))"],"5":"Extra fluffy and easy-peasy to whip up, this paleo and keto chocolate  mousse is bound to satisfy any ...","6":"15 min","7":"2"}}}},{"1":{"1":"https://www.thatskinnychickcanbake.com/wp-content/uploads/2016/07/Chocolate-Peanut-Butter-Mousse-Cake-7-600x440.jpg","3":600,"4":440},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQyjKcnu0mQkTq_hu8vd5Gxynv8kOYlArQSamr6qKf2461QawQXpQ","3":200,"4":146},"3":{"1":"That Skinny Chick Can Bake","2":"https://www.thatskinnychickcanbake.com/peanut-butter-chocolate-mousse-cake/","3":"Peanut Butter Chocolate Mousse Cake","4":"Peanut Butter Chocolate Mousse Cake | A decadent brownie topped with  exquisite chocolate and peanut ...","10":"uSJFlwLvdiGbRS"},"5":{"1":"gxwuSQMtlsngXow"},"7":{"1":{"9":{"1":5.0,"2":5,"3":"Peanut Butter Chocolate Mousse Cake","4":["1 box brownie mix (I used my [url]One Bowl Fudgy  Brownies∞https://www.thatskinnychickcanbake.com/one-bowl-fudgy-brownies/[/url]  and baked for 35 minutes)","8 ounces Reese's minis (reserve extras from bag for garnishing)","1 1/8 teaspoon powdered gelatin","1 1/2 tablespoons water","9 ounces Reese's peanut butter chips"],"5":"A decadent chocolate and peanut butter dessert.","6":"1 hr 35 min","7":"16 servings"}}}},{"1":{"1":"https://images.food52.com/0vmCf5I5baS0CjzEASwEBP7FBYs=/753x502/2603cf44-4718-4ca5-ae35-6ccc9f208ab7--2018-0508_tricolor-chocolate-mousse_3x2_james-ransom-059.jpg","3":753,"4":502},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFgmeLJESN6R3P9rPa7li83kt-itrIIVRNvCmobELVEq6ligZF","3":200,"4":133},"3":{"1":"Food52","2":"https://food52.com/recipes/76975-tricolor-chocolate-mousse","3":"Tricolor Chocolate Mousse","4":"Tricolor Chocolate Mousse","10":"kHfidHgjoKtRfJ"},"5":{"1":"xfBTnkNSKRXArNW"},"7":{"1":{"9":{"1":4.5714287757873535,"2":7,"3":"Tricolor Chocolate Mousse","4":["Base<\\/em>:","1 ounce (30 grams) dark chocolate","Dark Chocolate Mousse<\\/em>:","10 ounces (280 grams) semisweet or bittersweet chocolate (not to exceed 62%  cacao), coarsely chopped","10 tablespoons (140 grams) unsalted butter"],"5":"Named “Dessert of the Year” by San Francisco Focusmagazine in 1987, this  dessert was all the ...","7":"Serves 10-12"}}}},{"1":{"1":"https://www.curiouscuisiniere.com/wp-content/uploads/2018/02/Mousse-Au-Chocolate-French-Chocolate-Mousse-Image-4974.21.jpg","3":500,"4":742},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3kiWXUN_7SlC9wX39ePh2JGlKgD2J2sS6ILh1ElE4qLVDmNPP","3":134,"4":200},"3":{"1":"Curious Cuisiniere","2":"https://www.curiouscuisiniere.com/french-chocolate-mousse/","3":"Mousse Au Chocolate (Easy French Chocolate Mousse)","4":"If you love creamy, rich, dark chocolate, then Mousse Au Chocolat is for","10":"FCADlrWhXEqKDa"},"5":{"1":"itIHFxSjrbREsRr"},"7":{"1":{"9":{"1":4.119999885559082,"2":17,"3":"Mousse Au Chocolate (Easy French Chocolate Mousse)","4":["6 oz bittersweet chocolate","4 eggs (divided, at room temp*)","1 Tbsp sugar","1 tsp pure vanilla extract","Pinch salt"],"5":"If you love creamy, rich, dark chocolate, then Mousse Au Chocolat is for  you. This classic French ...","6":"10 min","7":"4 people"}}}},{"1":{"1":"http://2.bp.blogspot.com/-s7Y4M28grcg/UeB2Uhr8PzI/AAAAAAAASu0/x_x4lNbGY_Y/s1600/Chocolate+Mousse+1.jpg","3":1600,"4":1359},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQDBfF5H0pz1oKGMbq4_M0oEilrat37uEQluSYVL8jHv-AFO67T","3":200,"4":169},"3":{"1":"Kitchen Simmer","2":"http://www.kitchensimmer.com/2013/07/2-ingredient-chocolate-mousse-made-with.html","3":"Kitchen Simmer: 2 Ingredient Chocolate Mousse made with with Tofu","4":"2 Ingredient Chocolate Mousse made with with Tofu","10":"nEQPNkHkyYrqOo"},"5":{"1":"RHQXOaTULmPkXPy"}},{"1":{"1":"https://images-gmi-pmc.edge-generalmills.com/a3dab23d-e8ba-4c6a-91e8-d665f435b7b9.jpg","3":800,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTL9fZkba8Rj5BLfKkLvNn-VH6nm_SAq_CZOc-ZqG0YSHECNxfh","3":200,"4":112},"3":{"1":"Betty Crocker","2":"https://www.bettycrocker.com/recipes/chocolate-mousse-torte/66b1d719-9130-466c-80e3-a43ba54957b3","3":"Chocolate Mousse Torte","4":"Chocolate Mousse Torte","10":"XXqhHhnhMHlkYc"},"5":{"1":"LjVOJVXvNqQnUMi"},"7":{"1":{"9":{"1":4.0,"2":122,"3":"Chocolate Mousse Torte","4":["1 pouch (10.25 oz) Betty Crocker™ fudge brownie mix Save $","1/4 cup vegetable oil Save $","1/4 cup water Save $","1 egg Save $","2 bags (11.5 oz each) semisweet chocolate chunks (3 1/2 cups) Save $"],"5":"You've gotta try this fudgy brownie with creamy mousse all wrapped up into  one deliciously decadent ...","6":"5 hr 10 min","7":"16"}}}},{"1":{"1":"https://www.recipetineats.com/wp-content/uploads/2018/09/Chocolate-Mousse_9.jpg","3":900,"4":1125},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSRTllyEUXSRStN0A_5HquR1O4e6RpolMgGA3vXMK2tzXjWIoWj","3":160,"4":200},"3":{"1":"RecipeTin Eats","2":"https://www.recipetineats.com/chocolate-mousse/","3":"Chocolate Mousse","4":"Chocolate Mousse in glasses topped with a dollop of cream and chocolate  shavings, ready to","10":"VbHnKQYaoxNJTA"},"5":{"1":"DCTUOiQAUcmrbAs"},"7":{"1":{"9":{"1":5.0,"2":18,"3":"Chocolate Mousse","4":["3 eggs ((~55g/2 oz each))","125 g / 4.5 oz dark chocolate (, bittersweet / 70% cocoa (Note 1))","10 g / 0.3 oz / 2 tsp unsalted butter","125 ml / 1/2 cup cream (, full fat (Note 2))","35 g / 3 tbsp caster sugar ((superfine white sugar))"],"5":"Recipe video above. Light and airy yet rich, the iconic Chocolate Mousse is  actually quite straight ...","6":"20 min","7":"4"}}}},{"1":{"1":"https://thebakermama.com/wp-content/uploads/2017/12/fullsizeoutput_b92f.jpg","3":800,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSBGlZFrrxhyoI7vVCRXpvPnSEFZd5QRtWLyVxO5gwhuVcmGNPY","3":133,"4":200},"3":{"1":"The BakerMama","2":"https://thebakermama.com/recipes/triple-chocolate-mousse-cheesecake/","3":"Triple Chocolate Mousse Cheesecake","4":"Triple Chocolate Mousse Cheesecake","10":"SnmceCuTRPAycF"},"5":{"1":"nKaKgkQmJyQDnYx"},"7":{"1":{"9":{"3":"Triple Chocolate Mousse Cheesecake","4":["20 Oreo cookies","4 tablespoons (1/2 stick) unsalted butter, melted","2 (8-ounce) packages cream cheese, at room temperature","â…” cup sugar","â…” cup sour cream"],"5":"Get your chocolate fix with this Triple Chocolate Mousse Cheesecake that  will wow the crowd for any ...","6":"1 hr 30 min","7":"One 9-inch Cheesecake (12 slices)"}}}},{"1":{"1":"https://www.ihearteating.com/wp-content/uploads/2016/06/chocolate-mousse-1000-wm.jpg","3":1000,"4":1545},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkg6HRrZv_PdRsTXh7mQ1-sIu5sdTrsD47NOoaLPJh06-TJ1HMDA","3":129,"4":200},"3":{"1":"I Heart Eating","2":"https://www.ihearteating.com/chocolate-mousse-recipe/","3":"Chocolate Mousse","4":"Chocolate Mousse Recipe","10":"AmryhXhIwGlTTu"},"5":{"1":"bhcysqtAhQCxRBI"},"7":{"1":{"9":{"1":5.0,"2":3,"3":"Chocolate Mousse","4":["4 ounces bittersweet baking chocolate (60% cacao, chopped)","4 ounces semisweet baking chocolate (chopped)","1 1/2 cups mini marshmallows","1/2 cup milk","2 1/2 cups heavy cream"],"5":"Light and creamy chocolate mousse","6":"10 min","7":"10 servings"}}}},{"1":{"1":"https://media4.s-nbcnews.com/j/newscms/2018_17/1334122/chocolate-mousse-today-180423-tease_6844913865e80416b7725903c4c7cc1d.today-inline-large.jpg","3":700,"4":394},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRflwrv45xsumf5B5_bw0R9XQlW-zazCnn9Mhwf1BGUKN5yd0O5","3":200,"4":112},"3":{"1":"Today Show","2":"https://www.today.com/recipes/nigella-lawson-s-chocolate-olive-oil-mousse-recipe-t127449","3":"Nigella Lawson's Chocolate Olive Oil Mousse","4":"TODAY","10":"gghNMUXymYQvqp"},"5":{"1":"pAkxRTmVUHIwFVx"},"7":{"1":{"9":{"1":3.71875,"2":32,"3":"Nigella Lawson's Chocolate Olive Oil Mousse","4":["6 ounces bittersweet chocolate, preferably 70% cocoa solids, roughly chopped","7 tablespoons extra virgin olive oil","4 large eggs, at room temperature, separated","1 pinch, plus 1/4 teaspoon sea salt flakes","1/4 cup superfine sugar"],"5":"You don't need to turn on the oven to make this sweet, easy and deeply  chocolatey treat."}}}},{"1":{"1":"http://www.notenoughcinnamon.com/wp-content/uploads/2018/02/A-rich-and-silky-healthy-chocolate-mousse-made-with-a-22secret22-ingredient-%E2%80%93-avocado.-Super-easy-to-make-and-perfect-for-Valentines-Day-Vegan-refined-sugar-free-1.jpg","3":800,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFF0p8GA87czK48anmffnMfkYWuaSnmkBIQGV2JANtC-Xol7V2fw","3":133,"4":200},"3":{"1":"Not Enough Cinnamon","2":"https://www.notenoughcinnamon.com/healthy-avocado-chocolate-mousse/","3":"Healthy Avocado Chocolate Mousse","4":"A rich and silky healthy chocolate mousse made with a secret ingredient –  avocado. Super","10":"ytDhNkolXKLxrT"},"5":{"1":"VyGFADafQvGeeOG"},"7":{"1":{"9":{"1":5.0,"2":6,"3":"Healthy Avocado Chocolate Mousse","4":["4 oz - 120 g dark or semisweet chocolate, roughly chopped (you can also use  dark chocolate chips)","2 large ripe avocados (about 8 oz - 225 g each), halved and pitted.","3 tbsp unsweetened cocoa powder","1/4 cup almond milk (or your favorite milk)","1 tsp pure vanilla extract"],"5":"A rich and silky healthy chocolate mousse made with a \"secret\" ingredient –  avocado. Super easy to ...","6":"2 hr","7":"4"}}}},{"1":{"1":"https://www.browneyedbaker.com/wp-content/uploads/2013/04/chocolate-mousse-34-600.jpg","3":600,"4":889},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSaWSLB9Ts2EbM91_3zSx8pgPzf_x9OL6kFP5X_ca3Ugt5vcBAy5A","3":134,"4":200},"3":{"1":"Brown Eyed Baker","2":"https://www.browneyedbaker.com/chocolate-mousse-recipe/","3":"Dark Chocolate Mousse","4":"Dark Chocolate Mousse Recipe","10":"nmptWAfCYnJDno"},"5":{"1":"JAntLcGdsxJmiqL"},"7":{"1":{"9":{"3":"Dark Chocolate Mousse","4":["8 ounces bittersweet chocolate (60% cacao), finely chopped","5 tablespoons water","2 tablespoons Dutch-process cocoa powder","1 tablespoon brandy","1 teaspoon instant espresso powder"],"5":"A fabulous recipe for classic chocolate mousse.","6":"3 hr 30 min","7":"6 to 8 servings"}}}},{"1":{"1":"https://www.runningtothekitchen.com/wp-content/uploads/2016/02/Paleo-Chocolate-Mousse-1.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfqPMOL-Lac3lKJI5YjgsS_DVLZOKqzQlKloR4VKClGPRjSqSu","3":133,"4":200},"3":{"1":"Running to the Kitchen","2":"https://www.runningtothekitchen.com/paleo-chocolate-mousse/","3":"Paleo Chocolate Mousse - Running to the Kitchen®","4":"This paleo chocolate mousse is decadent and creamy. It's topped with a  quick strawberry chia","10":"YeEQQIjcNBiSHI"},"5":{"1":"mAqvnPwpUuebaSd"}},{"1":{"1":"https://www.delscookingtwist.com/wp-content/uploads/2018/04/Dark-Chocolate-Mousse_1043b.jpg","3":1600,"4":2320},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXp--t9ud0joIn-mnU8DeajJP8eCHiDEUpRhzho6wnM0vRXwyGHQ","3":137,"4":200},"3":{"1":"Del's cooking twist","2":"https://www.delscookingtwist.com/2018/04/17/dark-chocolate-mousse-the-one-and-only/","3":"Dark Chocolate Mousse (the one and only)","4":"Dark Chocolate Mousse","10":"CKhvAHDMsduJRj"},"5":{"1":"uEAVsXuOFtKbynA"},"7":{"1":{"9":{"3":"Dark Chocolate Mousse (the one and only)","4":["7 oz (200g) dark chocolate, at 60% cocoa","1 large Tablespoon (20g) salted butter","6 large eggs, whites and yolks apart","1 pinch of salt"],"5":"The one and only chocolate mousse I ever make. Just three ingredients, no  added sugar, and it's ...","6":"12 min","7":"4-6 servings"}}}},{"1":{"1":"https://hips.hearstapps.com/del.h-cdn.co/assets/18/10/1520286740-delish-strawberry-chocolate-mousse-cake-pinterest-still003.jpg?crop=0.999546485260771xw:1xh;center,top&resize=480:*","3":480,"4":719},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqbPMc0kFlmM1Jt1exaJlR4xyXlorUszqLCRMNswhO500O8fHIrg","3":133,"4":200},"3":{"1":"Delish.com","2":"https://www.delish.com/cooking/recipe-ideas/recipes/a58500/strawberry-chocolate-mousse-cake-recipe/","3":"Strawberry Chocolate Mousse Cake","4":"Strawberry Chocolate Mousse Cake","10":"KvrLMxhNhLTjNu"},"5":{"1":"ptRLDVduVvnFFlW"},"7":{"1":{"9":{"3":"Strawberry Chocolate Mousse Cake","4":["Cooking spray, for pan","24 Oreos, crushed","6 tbsp. butter, melted","Pinch kosher salt","2 tsp. gelatin"],"5":"Impress everyone with this Strawberry Chocolate Mousse Cake from Delish.com.","6":"6 hr 30 min","7":"8-10"}}}},{"1":{"1":"https://www.simplyrecipes.com/wp-content/uploads/2005/10/chocolate-mousse-horiz-a-1800.jpg","3":1800,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQltJG3psfbGppJn0PErmPZohv2G8yav3UpThzPmjPpOzqBMuK0rQ","3":200,"4":133},"3":{"1":"Simply Recipes","2":"https://www.simplyrecipes.com/recipes/chocolate_mousse/","3":"Classic Chocolate Mousse","4":"Chocolate Mousse","10":"LNouTHKdMOycCp"},"5":{"1":"LRpylOyFmkAQMVv"},"7":{"1":{"9":{"1":5.0,"2":70,"3":"Classic Chocolate Mousse","4":["4 1/2 ounces bittersweet chocolate, finely chopped","2 Tbsp (1 ounce) unsalted butter, cubed","2 Tbsp espresso or very strong coffee (I used decaf espresso from a local  Starbucks)","1 cup cold heavy whipping cream","3 large eggs, separated*"],"5":"Chocolate mousse is a great dessert for entertaining because 1) it looks  pretty, 2) everyone gets ...","6":"8 hr 35 min","7":"Serves 5 to 8"}}}},{"1":{"1":"https://du7ybees82p4m.cloudfront.net/5954ce66d1cd02.64778504.jpg?width=910&height=512","3":910,"4":512},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQWCfvpEyu6fgnZVdGPOOL70Tuxoa8xk7b9yN5LO_QElmJOMJYc7Q","3":200,"4":112},"3":{"1":"Sorted Food","2":"https://sortedfood.com/recipe/chocolatemoussecakerecipe","3":"Triple Chocolate Mousse Cake","4":"","10":"myAAryDxieDtBP"},"5":{"1":"LNJudVEEKMwjVIR"},"7":{"1":{"9":{"3":"Triple Chocolate Mousse Cake","4":["100 ml water","1 tsp vanilla extract","70 g caster sugar","150 g unsalted butter","70 g soft brown sugar"],"5":"What's better than a chocolate mousse cake? A triple chocolate mousse cake!  Try this delicious ..."}}}},{"1":{"1":"https://www.barbarabakes.com/wp-content/uploads/2015/10/Chocolate-Mousse-Cups-Barbara-Bakes.jpg","3":640,"4":427},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRPJ0YD0gdjbG_RI-4XBf_oYs2nor4rOr6Nl1nCf0W2d-Xh2GXtiw","3":200,"4":133},"3":{"1":"Barbara Bakes","2":"https://www.barbarabakes.com/chocolate-mousse-cups-and-ubud-bali/","3":"Chocolate Mousse Cups and Ubud","4":"A pretty, ruffled chocolate cup filled with a rich, creamy milk chocolate  mousse topped","10":"cgoLLugSFUfoRv"},"5":{"1":"TNTlYSgeuvompMV"},"7":{"1":{"9":{"3":"Chocolate Mousse Cups and Ubud","5":"A pretty, ruffled chocolate cup filled with a rich, creamy milk chocolate  mousse topped with a sweet ...","7":"8 servings"}}}},{"1":{"1":"https://i1.wp.com/cafedelites.com/wp-content/uploads/2018/01/Low-Carb-Double-Chocoloate-Mousse-Coconut-IMAGE-22.jpg?resize=980%2C1470&ssl=1","3":980,"4":1470},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR4uZa1UWLSlYEd0JPPgBQP_h0SdFU65SzmdWufd1XpQrpqxz7zHQ","3":133,"4":200},"3":{"1":"Cafe Delites","2":"https://cafedelites.com/3-ingredient-double-chocolate-mousse-low-carb/","3":"3-Ingredient Double Chocolate Mousse (Low Carb) + VIDEO ...","4":"3-Ingredient Double Chocolate Mousse (Low Carb and Dairy Free) | http:","10":"iENUfhBLxcKFBT"},"5":{"1":"rvfaeHHmMinDFQn"}},{"1":{"1":"https://i1.wp.com/myvibrantkitchen.com/wp-content/uploads/2017/12/vegan-aquafaba-easy-fluffy-chocolate-mousse-1-1.jpg?resize=900%2C1350","3":900,"4":1350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQM6xf7BEk6-koJKGbwy9NFbgwbAVWQ0dyn6dSy7ngOoaNh_XAvQ","3":133,"4":200},"3":{"1":"My Vibrant Kitchen","2":"http://myvibrantkitchen.com/easy-vegan-aquafaba-chocolate-mousse/","3":"Easy Vegan Aquafaba Chocolate Mousse","4":"Easy Vegan Aquafaba Chocolate Mousse","10":"GQjqdpLHCxFfan"},"5":{"1":"BYOHYQHTrMWrfGK"},"7":{"1":{"9":{"1":4.5,"2":2,"3":"Easy Vegan Aquafaba Chocolate Mousse","4":["70 ml soy milk or coconut milk","185 g dairy-free dark chocolate","240 ml chickpea water (aka aquafaba)","½ tsp lemon juice (optional)","1 Tbsp white caster sugar"],"5":"This post has been along time coming… I’ve lost count of all the times I’ve…","6":"25 min","7":"4-5"}}}},{"1":{"1":"https://cdn.cpnscdn.com/static.coupons.com/ext/kitchme/images/recipes/800x1200/no-bake-death-by-chocolate-mousse-pie_44591.jpg","3":800,"4":1200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQog0BDyBHjvza7PY32qBbhNfsldmZoM4m6VBfWVmuuJV2jToJKHw","3":133,"4":200},"3":{"1":"KitchMe","2":"http://www.kitchme.com/recipes/no-bake-death-by-chocolate-mousse-pie","3":"No Bake Death by Chocolate Mousse Pie","4":"","10":"UmAfDvWwIqwEuv"},"5":{"1":"UHplnYftdTJtbmk"},"7":{"1":{"9":{"3":"No Bake Death by Chocolate Mousse Pie","4":["21 cream filled chocolate sandwich cookies, such as Oreo","1⁄4 cup butter, melted","1 cup heavy cream,","1 package (12 oz) semi-sweet chocolate chips,","1 tsp vanilla extract,"],"5":"Recipe including course(s): Dessert; and ingredients: butter, chocolate  sandwich cookies, heavy ...","6":"30 min","7":"Serves 8"}}}},{"1":{"1":"https://www.daringgourmet.com/wp-content/uploads/2017/12/White-Chocolate-Mousse-6-cropped.jpg","3":1024,"4":736},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSaOIXpH0XPJzc22BR6NEoEcb8IS8-akAT4nPmoODOgGpBtl5VTQ","3":200,"4":143},"3":{"1":"The Daring Gourmet","2":"https://www.daringgourmet.com/easy-white-chocolate-mousse/","3":"Easy White Chocolate Mousse","4":"... festive or special occasion, give this Easy White Chocolate Mousse a  try!","10":"xcyoPPhgKVJyHy"},"5":{"1":"xrhvLuXEKqVrkeM"},"7":{"1":{"9":{"1":5.0,"2":2,"3":"Easy White Chocolate Mousse","4":["2 cups heavy whipping cream","12 ounces white chocolate chips or bar broken into chunks","3 tablespoons powdered (confectioner's) sugar","Edible Glitter, optional ((for sprinkling))"],"5":"Easy, quick and classy, this deliciously rich and creamy White Chocolate  Mousse makes an elegant ...","7":"8 servings"}}}},{"1":{"1":"https://i1.wp.com/www.feastingonfruit.com/wp-content/uploads/2017/02/Chocolate-Mousse-Cake-8.jpg?resize=980%2C1470&ssl=1","3":980,"4":1470},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQMf6veD5XuruR71A-tJ3ySKIB1Cs10emN7IB42qDYz_MDwaGNM","3":133,"4":200},"3":{"1":"Feasting on Fruit","2":"https://www.feastingonfruit.com/chocolate-mousse-cake/","3":"Chocolate Mousse Cake","4":"Low-Fat Chocolate Mousse CakeSkip to Recipe","10":"lmMUDWOwAnEMvJ"},"5":{"1":"SnlTUklXjjOGHkx"},"7":{"1":{"9":{"1":4.800000190734863,"2":12,"3":"Chocolate Mousse Cake","4":["2 cups almonds","2 tbsp maple syrup","1 tbsp water (if needed)","1 cup baked and mashed sweet potato","1 cup Medjool dates"],"5":"This insanely decadent Chocolate Mousse Cake may taste like fudge frosting  but is made from just a ...","6":"1 hr 5 min","7":"6 \" round cake"}}}},{"1":{"1":"https://static01.nyt.com/images/2015/10/26/dining/26COOKING-FLOURLESSCHOCCAKE1/26COOKING-FLOURLESSCHOCCAKE1-articleLarge.jpg","3":600,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjBhgcxDj21rYQRKLe9Gg5evkd5jQOixJMy-VwlyHSj8KGa_KI","3":200,"4":133},"3":{"1":"NYT Cooking - The New York Times","2":"https://cooking.nytimes.com/recipes/11001-intense-chocolate-mousse-cake","3":"Intense Chocolate Mousse Cake","4":"Intense Chocolate Mousse Cake","10":"EbcrrHfipRSWqR"},"5":{"1":"fBQbuMkMKyLnDGP"},"7":{"1":{"9":{"1":5.0,"2":813,"3":"Intense Chocolate Mousse Cake","4":["10 ounces bittersweet chocolate","9 tablespoons unsalted butter","6 large eggs, room temperature and separated","Pinch of salt","¾ cup sugar"],"5":"There is very little that needs to be said about a chocolate mousse cake.  This one lives up to its ...","6":"1 hr 5 min","7":"One 9-inch cake"}}}},{"1":{"1":"https://www.tasteofhome.com/wp-content/uploads/2018/01/Triple-Chocolate-Mousse-Torte_EXPS_SDAM18_212092_C11_29_2b-696x696.jpg","3":696,"4":696},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcShzAmAXBRyn_Ha_oUg9dAvQ2mLbk6wdDAaOXA1AYdu8m_f3CeM","3":200,"4":200},"3":{"1":"Taste of Home","2":"https://www.tasteofhome.com/recipes/triple-chocolate-mousse-torte/","3":"Triple Chocolate Mousse Torte","4":"Triple Chocolate Mousse Torte","10":"lpqFjVlbVwUsmQ"},"5":{"1":"FXeXclSsYAkJYGJ"},"7":{"1":{"9":{"3":"Triple Chocolate Mousse Torte","4":["18 Oreo cookies","1/3 cup butter, melted","6 teaspoons unflavored gelatin, divided","3 tablespoons cold water, divided","5 ounces bittersweet chocolate, chopped"],"5":"When it's too hot to bake something sweet, but you're craving chocolate, my  triple chocolate mousse ...","6":"1 hr 55 min","7":"16 servings."}}}},{"1":{"1":"https://thelemonbowl.com/wp-content/uploads/2017/02/Vegan-Chocolate-Mousse-a-healthy-dessert-recipe.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFzpfvIEbn_mhVOAm9OjBWPF_H9NTJ1-vKJdUO3My1ZFFGbLhmAQ","3":133,"4":200},"3":{"1":"The Lemon Bowl","2":"https://thelemonbowl.com/vegan-chocolate-mousse/","3":"Vegan Chocolate Mousse","4":"Vegan Chocolate Mousse","10":"nexwCurfkLKRIu"},"5":{"1":"jlqYrUVtWGuHNgT"},"7":{"1":{"9":{"1":4.0,"2":3,"3":"Vegan Chocolate Mousse","4":["4 ounces bittersweet chocolate chips (60-70%) (or vegan chocolate chips)","3 ripe avocados (pitted)","1/2 cup full-fat coconut milk (or milk of choice)","1/4 cup cocoa powder","1 teaspoon vanilla"],"5":"This rich and creamy vegan chocolate mousse recipe is made with avocado and  topped with whipped ...","6":"10 min","7":"4"}}}},{"1":{"1":"https://4ebr313dmbeg4df5hm1uys8p-wpengine.netdna-ssl.com/wp-content/uploads/2014/03/chocolatemousse.jpg","3":570,"4":858},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTvzjlCDnc5wQiWcReLod0HYyWIHmZptf0xUR9G_d_kTHgBG59U","3":132,"4":200},"3":{"1":"Cookies & Cups","2":"https://cookiesandcups.com/easy-chocolate-mousse/","3":"Easy Chocolate Mousse","4":"Easy Chocolate Mousse in a jar","10":"phRcSUkOtBoamm"},"5":{"1":"YgYntDuGWruYycG"},"7":{"1":{"9":{"1":4.599999904632568,"2":19,"3":"Easy Chocolate Mousse","4":["2 eggs","1/4 cups granulated sugar","2 1/2 cups cold heavy whipping cream, divided","6 oz semi-sweet chocolate (about 1 cup semi-sweet chips)"],"5":"makes 8 servings","7":"serves 8"}}}},{"1":{"1":"https://www.chatelaine.com/wp-content/uploads/2017/12/chocolate-mousse-1.jpg","3":800,"4":800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRN_vKJ6e5dD_T6QWbgKK9WcVGjmc90HcH-AQ5S4C_JGR9BRcTc","3":200,"4":200},"3":{"1":"Chatelaine","2":"https://www.chatelaine.com/recipe/desserts/chocolate-mousse-with-whipped-cream/","3":"Chocolate mousse with whipped cream","4":"IngredientsInstructionsNutrition","10":"nBaqtfTuCRvgTP"},"5":{"1":"auraBvchaAqAolJ"},"7":{"1":{"9":{"3":"Chocolate mousse with whipped cream","4":["100 g bittersweet chocolate, chopped (2/3 cup)","60 g semi-sweet chocolate, chopped (1/3 cup)","3 tbsp unsalted butter, cubed","1 tsp vanilla","1/4 tsp salt"],"6":"15 min","7":"8"}}}},{"1":{"1":"https://www.lifeloveandsugar.com/wp-content/uploads/2017/10/Baileys-Chocolate-Mousse-Brownie-Cake4.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTosET9j-NPzteHftDDcr0sVQhS_bgH3tdUh1YK5UFwrV5OyGKT","3":133,"4":200},"3":{"1":"Life Love and Sugar","2":"https://www.lifeloveandsugar.com/2017/10/16/baileys-chocolate-mousse-brownie-cake/","3":"Baileys Chocolate Mousse Brownie Cake","4":"Baileys Chocolate Mousse Brownie Cake - a dense chocolate brownie topped  with Baileys chocolate ...","10":"MSYtxTYyAERGjI"},"5":{"1":"QdMTifpDBByVkpn"},"7":{"1":{"9":{"3":"Baileys Chocolate Mousse Brownie Cake","4":["1 1/2 cups (336g) unsalted butter, melted","2 cups (414g) sugar","2 tsp vanilla extract","6 tbsp Baileys Irish Cream","4 eggs"],"5":"This Baileys Chocolate Mousse Brownie Cake is our chocolate and Baileys  cake dreams come true! With ...","7":"12-15 Slices"}}}},{"1":{"1":"https://cookinglsl.com/wp-content/uploads/2017/02/baileys-mousse-1-1-660x925.jpg","3":660,"4":925},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQeV4NgUDvRBtYdRb_9EA5KjR95bQ2qg4osoxeDWhCBFMG-75h8","3":142,"4":200},"3":{"1":"Cooking LSL","2":"https://cookinglsl.com/easy-baileys-chocolate-mousse-recipe/","3":"Easy Baileys Chocolate Mousse Recipe","4":"Easy Baileys Chocolate Mousse Recipe","10":"epIkUtAcFpsbue"},"5":{"1":"iYUCCKccmaXMhHE"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Easy Baileys Chocolate Mousse Recipe","4":["3/4 cup Baileys (, divided)","2 cups heavy whipping cream (, divided)","200 grams / 1 1/4 cup semi-sweet chocolate ((or chocolate chips))","1 tbsp gelatin","1/4 cup cold water"],"5":"... - a boozy dessert for chocolate lovers. Made with Baileys Irish Cream.  Just in time for St ...","6":"25 min","7":"6"}}}},{"1":{"1":"https://beyondfrosting.com/wp-content/uploads/2017/03/Oreo-Chocolate-Mousse-Pie-029.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR2IfvrAtLKO1wTECgB7eLcodLShil4OxELsIF0b8nW-KNji7AX","3":133,"4":200},"3":{"1":"Beyond Frosting","2":"https://beyondfrosting.com/2017/03/13/no-bake-oreo-chocolate-mousse-pie/","3":"No-Bake Oreo Chocolate Mousse Pie","4":"It's all about the layers with this No-Bake Oreo Chocolate Mousse Pie. The","10":"hDIMNfEVVEdIwl"},"5":{"1":"yKnwKkQbGCKVlfB"},"7":{"1":{"9":{"3":"No-Bake Oreo Chocolate Mousse Pie","4":["For the crust","2 pkgs Oreo Cookies (14.03 oz), divided","8 tablespoons unsalted butter","For the chocolate layer","1 tablespoons cold water"],"5":"It’s all about the layers with this No-Bake Oreo Chocolate Mousse Pie. The  thick Oreo crust is ...","6":"4 hr 30 min"}}}},{"1":{"1":"https://www.bbcgoodfood.com/sites/default/files/styles/recipe/public/recipe/recipe-image/2017/12/chocolate-mousse.jpg?itok=v4PsEZ95","3":500,"4":454},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjqfdHQs0pRv0EAdRPIXtKXZSVydYrTaoC7sjoOlZxcrClTA60Ng","3":200,"4":181},"3":{"1":"BBC Good Food","2":"https://www.bbcgoodfood.com/recipes/easy-chocolate-mousse-","3":"Easy chocolate mousse","4":"Easy chocolate mousse","10":"tAvSFgdIXcWSdD"},"5":{"1":"RFFfGOUBWehRIwM"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Easy chocolate mousse","4":["150g 70% dark chocolate, plus extra to serve","6 egg whites","2 tbsp golden caster sugar","4 tbsp crème fraîcheand grated chocolate, to serve"],"5":"Make this classic chocolate dessert in minutes with just a few ingredients  – light yet delicious. ...","6":"7 min","7":"Serves 4"}}}},{"1":{"1":"https://static01.nyt.com/images/2018/05/08/dining/08COOKING-NOBAKEMOUSSE1/08COOKING-NOBAKEMOUSSE1-articleLarge-v2.jpg","3":600,"4":414},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3_8y3xenuC37UJsbcl7eFzp4oNhvBM7n6pWeNH3FXCkmoKLVo","3":200,"4":137},"3":{"1":"NYT Cooking - The New York Times","2":"https://cooking.nytimes.com/recipes/1019316-no-bake-chocolate-mousse-bars","3":"No-Bake Chocolate Mousse Bars","4":"No-Bake Chocolate Mousse Bars","10":"jMfULOMAKMKyvc"},"5":{"1":"APAWdyGGVoPVGdK"},"7":{"1":{"9":{"1":4.0,"2":660,"3":"No-Bake Chocolate Mousse Bars","4":["18 whole graham crackers (about 9 1/2 ounces/269 grams)","8 tablespoons/113 grams unsalted butter (1 stick), melted","2 tablespoons granulated sugar","¼ teaspoon kosher salt","1 pound/454 grams semisweet chocolate, finely chopped"],"5":"Ethereal and ready to melt in your mouth, chocolate mousse bars are easy to  make and even easier to ...","6":"30 min","7":"24 servings"}}}},{"1":{"1":"https://www.simplystacie.net/wp-content/uploads/2015/09/Chocoholics-Chocolate-Mousse-Cake-wide.jpg","3":736,"4":552},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTc8X8ax7pAeyj8cUviUNQ0tGs1EHoM4ssApf6FCvCGZBb1VqdF","3":200,"4":149},"3":{"1":"Simply Stacie","2":"https://www.simplystacie.net/2015/11/chocoholics-chocolate-mousse-cake/","3":"Chocoholics Chocolate Mousse Cake","4":"Chocoholics Chocolate Mousse Cake - Luscious and rich, this dessert recipe  will satisfy your sweet","10":"qXNFdcwHLgSQcR"},"5":{"1":"PmBvFwnmYUMsLKV"},"7":{"1":{"9":{"3":"Chocoholics Chocolate Mousse Cake","5":"Luscious and rich, this Chocoholics Chocolate Mousse Cake will satisfy your  sweet tooth!","6":"45 min","7":"6"}}}},{"1":{"1":"https://food-images.files.bbci.co.uk/food/recipes/celebration_chocolate_26103_16x9.jpg","3":5760,"4":3240},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQEOqt14rbAy7SyDf5C8iZrqZu6nI8rYgUvQyI68tsGKb4nionf0Q","3":200,"4":112},"3":{"1":"BBC.com","2":"https://www.bbc.com/food/recipes/celebration_chocolate_26103","3":"Celebration chocolate mousse cake","4":"","10":"CWatRJQqmSvgYE"},"5":{"1":"kHcSSinPLWLfHpR"},"7":{"1":{"9":{"3":"Celebration chocolate mousse cake","4":["25g/1oz cocoa powder, plus extra for dusting","3 tbsp boiling water","100g/3½oz caster sugar","100g/3½oz self-raising flour","1 level tsp baking powder"],"5":"Mary Berry's rich, indulgent dessert is fit for a celebration and makes a  stunning centrepiece., ...","6":"12 hr 30 min","7":"Serves 8-10"}}}},{"1":{"1":"https://www.afarmgirlsdabbles.com/wp-content/uploads/2015/07/Dark-Chocolate-Mousse-Cups_AFarmgirlsDabbles_AFD-600x900.jpg","3":600,"4":900},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRgdqtv_Cj2AhDxF7cB2gOi1aEGwJWkFPraLwVhF0scdQbBZ32T","3":133,"4":200},"3":{"1":"A Farmgirl's Dabbles","2":"https://www.afarmgirlsdabbles.com/chocolate-mousse-cups-recipe/","3":"Chocolate Mousse Cups","4":"Chocolate Mousse Cups","10":"iEjeNoadQdnDKP"},"5":{"1":"MIMiGtNACwSGsPC"},"7":{"1":{"9":{"3":"Chocolate Mousse Cups","4":["1/2 c. cold heavy cream","1 tsp. pure vanilla extract","4 large egg yolks","1 T. butter, at room temperature","1/4 c. espresso or strong coffee, at room temperature"],"5":"With this recipe, anyone and everyone is able to make delicious,  savor-every-spoonful Chocolate ...","7":"6 servings"}}}},{"1":{"1":"https://www.spendwithpennies.com/wp-content/uploads/2013/01/Easy-Chocolate-Mousse-spendwithpennies-23.jpg","3":700,"4":1050},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR_CLPJ2xigxExPYAcr08k9EOf5vx_tpNB30RyhhqihMIHV_iQ5","3":133,"4":200},"3":{"1":"Spend with Pennies","2":"https://www.spendwithpennies.com/chocolate-mousse-in-1-minute/","3":"Easy Chocolate Mousse","4":"dessert cups filled with chocolate mousse, whipped cream and a raspberry on  top","10":"QTcuoXeToOLeBp"},"5":{"1":"sQhduDgpkeIFqJR"},"7":{"1":{"9":{"1":5.0,"2":1,"3":"Easy Chocolate Mousse","4":["1 box instant chocolate pudding mix (4 serving size)","2 tablespoons unsweetened cocoa powder","2 1/2 cups heavy cream (30-35% mf)","1 cup whipped topping (optional)"],"5":"A rich creamy chocolate dessert that takes just a couple of minutes to  prepare!","6":"2 min","7":"4 servings"}}}},{"1":{"1":"https://www.kunersfoods.com/wp-content/uploads/2017/10/ChocMousse2_720x478_72_RGB-515x342.jpg","3":515,"4":342},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-y8NR-2I7fwSVMC0mQyM7dCTTK0H0JaxXTY_SXXneDd8AticffA","3":200,"4":132},"3":{"1":"Kuner's Foods","2":"https://www.kunersfoods.com/recipe/black-bean-chocolate-mousse/","3":"Black Bean Chocolate Mousse","4":"Black Bean Chocolate Mousse Servings: 5 (about 4oz each) Prep Time: 10  minutes Total Time: 1 hour 10 ...","10":"uKGicOGawSIaHx"},"5":{"1":"RQrBYmSDpOiEOnh"},"7":{"1":{"9":{"1":4.199999809265137,"2":5,"3":"Black Bean Chocolate Mousse","7":"5 (about 4oz each)"}}}},{"1":{"1":"https://www.halfbakedharvest.com/wp-content/uploads/2017/01/Chocolate-Lovers-Greek-Yogurt-Chocolate-Mousse-Cake-4.jpg","3":1200,"4":1800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTVc47mXlT63i5lHx1nQ_OBA9aRTF7ITemEejQPK215gMzdI_xB","3":133,"4":200},"3":{"1":"Half Baked Harvest","2":"https://www.halfbakedharvest.com/chocolate-lovers-greek-yogurt-chocolate-mousse-cake/","3":"Chocolate Lovers Greek Yogurt Chocolate Mousse Cake.","4":"Chocolate Lovers Greek Yogurt Chocolate Mousse Cake | halfbakedharvest.com  @hbharvest","10":"iWycSGhrbDsnet"},"5":{"1":"oGRyjdfvlWJPpKW"},"7":{"1":{"9":{"1":3.7799999713897705,"2":18,"3":"Chocolate Lovers Greek Yogurt Chocolate Mousse Cake.","4":["1 cup raw walnuts","1/2 cup raw (unsweetened coconut flakes)","1 1/2 cups pitted (packed dates (about 10 ounces))","1/2 cup cacao powder or unsweetened cocoa powder","pinch of flaky sea salt"],"5":"Chocolate lovers...this one is for you.","6":"1 hr 43 min","7":"8 Servings"}}}},{"1":{"1":"https://images.food52.com/YFlDbJw8F8GFolGJepl1XXj5Un8=/753x502/eb5300fa-1862-4ec7-8e73-5da38c2a1638--IMG_8848_web.jpg","3":753,"4":502},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMzy0H1PjQ7_6fYzOUPcVKIzwW4yc0ET3SzcF1pYH_0jZu7TaBmg","3":200,"4":133},"3":{"1":"Food52","2":"https://food52.com/recipes/73238-eggless-chocolate-mousse-cake","3":"Eggless chocolate mousse cake","4":"Eggless chocolate mousse cake","10":"OuRVdvQyJNFjIu"},"5":{"1":"FyvDAuHOSkXHVxg"},"7":{"1":{"9":{"3":"Eggless chocolate mousse cake","4":["CHOCOLATE CAKE","1 cup granulated sugar","3/4 cup all purpose flour","2 tablespoons all purpose flour","1/4 cup unsweetened cocoa powder"],"7":"Makes 6 mini cakes"}}}},{"1":{"1":"https://hungryhappenings.com/wp-content/uploads/2018/01/chocolate-mousse-cup-hearts-recipe-1.jpg","3":680,"4":680},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRQjD9OHvXLwUnN6Za9mGKLPTU8D0vUPIlNv5JcaU1XNIcw8ovRDw","3":200,"4":200},"3":{"1":"Hungry Happenings","2":"https://hungryhappenings.com/chocolate-mousse-cup-hearts/","3":"Chocolate Mousse Cup Hearts","4":"Chocolate Mousse Cup Hearts","10":"CTTGmjORhBeLnB"},"5":{"1":"CnaIBrYDIVYnYBP"},"7":{"1":{"9":{"3":"Chocolate Mousse Cup Hearts","4":["24 ounces melted and tempered pure dark chocolate or melted confectionery  coating/candy melts","3 tablespoons water","3 tablespoons sugar","3 large egg yolks","1/2 cup heavy whipping cream"],"5":"Chocolate heart shaped bowls filled with luxuriously smooth chocolate  mousse.","6":"35 min","7":"12"}}}},{"1":{"1":"https://flockler.com/thumbs/sites/192/jo_easy5_hero_cherries_chocolate_mousse_538_landscape_s600x600_c3467x2025_l0x190.jpg","3":600,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQA3S7YmPon_WNoASN_w3uVMr10QQjo_TAcYldF-5941POWlNXFag","3":200,"4":200},"3":{"1":"The Happy Foodie","2":"https://thehappyfoodie.co.uk/recipes/cherry-chocolate-mousse","3":"Cherry Chocolate Mousse","4":"Cherry Chocolate Mousse","10":"jXYXPYAtvXUoDt"},"5":{"1":"GHiNCjnUlImEjQr"},"7":{"1":{"9":{"3":"Cherry Chocolate Mousse","4":["200g dark chocolate (70%)","1 x 400g tin of black pitted cherries in syrup","200ml double cream","4 large eggs","2 tbsp golden caster sugar"],"5":"Jamie Oliver's recipe for Cherry Chocolate Mousse, from the book of his  Channel 4 series, Jamie's ...","6":"30 min"}}}},{"1":{"1":"https://www.cookingclassy.com/wp-content/uploads/2015/06/easy-chocolate-mousse9-srgb..jpg","3":575,"4":857},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRaxSGuYQTWN0IdkLiCm5bbCgB8yC-YSJBOgwmYrCWUl3lGV6II-A","3":134,"4":200},"3":{"1":"Cooking Classy","2":"https://www.cookingclassy.com/easy-chocolate-mousse/","3":"Easy Chocolate Mousse","4":"... Easy Chocolate Mousse | Cooking Classy ...","10":"cRfmXtkoQaNPij"},"5":{"1":"HKuHLnhAgfeTxUT"},"7":{"1":{"9":{"3":"Easy Chocolate Mousse","4":["3 1/2 cups mini marshmallows","1/4 cup salted butter (, diced into 1 tbsp pieces)","9 oz good quality semi-sweet chocolate (, chopped into small pieces)","1/4 cup hot water","1 cup heavy cream"],"5":"Yield: 6 servings","6":"50 min"}}}},{"1":{"1":"https://omgchocolatedesserts.com/wp-content/uploads/2017/07/Triple-Chocolate-Mouse-Cake-Minis-1.jpg","3":800,"4":1138},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6kthHuIBjSaP2JLUjxI1Z1vlnK2P0g1RBkwwfY7DQetSR_YAE","3":140,"4":200},"3":{"1":"OMG Chocolate Desserts","2":"https://omgchocolatedesserts.com/triple-chocolate-mousse-cake-minis/","3":"Triple Chocolate Mousse Cake Minis","4":"Triple Chocolate Mousse Cake Minis are rich and decadent layered dessert  with brownie bottom, dark, ...","10":"OHvXlsLUnBRFyW"},"5":{"1":"gupsGQNOgSdbvFu"},"7":{"1":{"9":{"3":"Triple Chocolate Mousse Cake Minis","4":["1/2 cup unsalted butter","7 oz. quality semi-sweet chocolate-chopped","¾ cup granulated sugar","2 large eggs","1 teaspoon vanilla"],"5":"Chocolate lovers dream come true!!!Triple Chocolate Mousse Cake Minis are  rich and decadent layered ..."}}}},{"1":{"1":"https://truffle-assets.imgix.net/pxqrocxwsjcc_1ExNApZWGsM6EgqwoySYou_eggless-chocolate-mousse_landscapeThumbnail_en.jpeg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS5peaglYDX3baXp9UgU9SLARAbGBl_qHWcj1Ez_In2WrZ7l16erw","3":200,"4":112},"3":{"1":"Tastemade","2":"https://www.tastemade.com/videos/eggless-chocolate-mousse","3":"Eggless Chocolate Mousse","4":"","10":"aHQpAUdxysLqDE"},"5":{"1":"SFepbKWHigjGXwP"},"7":{"1":{"9":{"3":"Eggless Chocolate Mousse","4":["3 ounces dark chocolate (over 65 percent cacao content)","7 fluid ounces heavy cream, very cold","For plating:","Little Mason jars","One can coconut milk, frozen so cream separates to the top, for garnish"],"5":"Satisfy your chocolate addiction with this ridiculously easy mousse."}}}},{"1":{"1":"https://homecookingadventure.com/images/recipes/triple_chocolate_mousse_cake_main.jpg","3":635,"4":423},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8sE2etmZ0WERxbuYUZmisFmy_QG5iPuDSSDL8HrzYWaJ549Jb","3":200,"4":133},"3":{"1":"Home Cooking Adventure","2":"https://www.homecookingadventure.com/recipes/no-bake-triple-chocolate-mousse-cake","3":"No-Bake Triple Chocolate Mousse Cake","4":"No-Bake Triple Chocolate Mousse Cake","10":"KbEUPKybruvwgj"},"5":{"1":"OvBJSbpjEucCXqd"},"7":{"1":{"9":{"3":"No-Bake Triple Chocolate Mousse Cake","4":["7 oz (200g) oreo cookies","4 tbsp (60g) butter, melted","5 oz (150g) semi-sweet chocolate","1/2 cup (120g) whipping cream","2/3 cup (160g) whipping cream (35% fat), chilled"]}}}},{"1":{"1":"https://cdn.apartmenttherapy.info/image/fetch/f_auto,q_45,w_600,h_750,c_fit,fl_strip_profile/https://s3.amazonaws.com/pixtruder/original_images/4292f1cd22e7a55c5c4b34e83dc164d78c62503d","3":500,"4":750},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiy5TAVbUDNxzQZqFJcdSN3ni5mMS4PCN1Cm6UtXACsvKGtfaROA","3":133,"4":200},"3":{"1":"The Kitchn","2":"https://www.thekitchn.com/chrissy-teigen-chocolate-mousse-recipe-review-261645","3":"Chrissy Teigen's Three-Ingredient Chocolate Mousse with Salty Rice  Krispies–Hazelnut Crackle","4":"","10":"xTcuUtyOnbIiVX"},"5":{"1":"WgjVRQiSQDUBoJq"},"7":{"1":{"9":{"1":4.5,"2":17,"3":"Chrissy Teigen's Three-Ingredient Chocolate Mousse with Salty Rice  Krispies–Hazelnut Crackle","4":["1 cup good-quality chocolate chips or coarsely chopped chocolate (6 ounces)","1/3 cup whole milk","3/4 cup cold heavy cream","Oil, for the pan","2/3 cup granulated sugar"],"5":"You'll want to make this every night.","6":"15 min","7":"Serves 4"}}}},{"1":{"1":"https://www.tasteofhome.com/wp-content/uploads/2018/01/Orange-Chocolate-Mousse-Mirror-Cake_EXPS_THCOM17_210212_D09_12_2b-1-696x696.jpg","3":696,"4":696},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR6CYbfzoObEcoBYObETRy19c6O_FuZlIfT-eNs_vD8s-OqymCC7w","3":200,"4":200},"3":{"1":"Taste of Home","2":"https://www.tasteofhome.com/recipes/orange-chocolate-mousse-mirror-cake/","3":"Orange Chocolate Mousse Mirror Cake","4":"Orange Chocolate Mousse Mirror Cake","10":"bccutWebwVRlAR"},"5":{"1":"jHtuHqOpytcagyC"},"7":{"1":{"9":{"1":4.0,"2":1,"3":"Orange Chocolate Mousse Mirror Cake","4":["2 cups crushed Oreo cookies (about 20 cookies)","1 teaspoon grated orange zest","1/4 cup butter, melted","FILLING:","1 envelope unflavored gelatin"],"5":"A shiny, mirror-like orange glaze covers a chocolate mousse cake to create  a delicious show-stopping ...","6":"45 min","7":"16 servings."}}}},{"1":{"1":"https://thethingswellmake.com/wp-content/uploads/2013/07/15-two-ingredient-easy-chocolate-mousse-recipe-4.jpg","3":720,"4":1079},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTixzsisXR_ct7wced_BTTByvghActd5JzbabwBT6WETpC3wIrF","3":133,"4":200},"3":{"1":"Oh, The Things We'll Make!","2":"https://thethingswellmake.com/how-to-make-chocolate-mousse-two-types/","3":"Two Ingredient, Easy Chocolate Mousse Recipe","4":"This two ingredient, easy chocolate mousse can be whipped up in a matter of  minutes","10":"FdBXMwoEnGACQJ"},"5":{"1":"flsvDnvpdIFUYxE"},"7":{"1":{"9":{"1":3.75,"2":8,"3":"Two Ingredient, Easy Chocolate Mousse Recipe","4":["4 eggs","100 g chocolate"],"5":"This two ingredient, easy chocolate mousse can be whipped up in a matter of  minutes, and it's rich, ...","6":"25 min","7":"8 small servings"}}}},{"1":{"1":"https://cdn.thisiswhyimbroke.com/images/radioactive-uranium-ore-640x533.jpg","3":640,"4":533},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlVDrWUi1LscguCB1Yj3yyVI_a1njoRRYb3IJ1DV7gP5cvS68Uow","3":200,"4":166},"3":{"1":"ThisIsWhyImBroke","2":"https://www.thisiswhyimbroke.com/radioactive-uranium-ore/","3":"Radioactive Uranium Ore","4":"","10":"tgCkyEelnhAMUx"},"5":{"1":"CGYCQOxeAVvJDdU"}},{"1":{"1":"https://i.ytimg.com/vi/3_7645Ep4Dg/maxresdefault.jpg","3":1920,"4":1080},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQA9FM_kk9sVeBrK649YPlhvBwnK-Tn5IHXrzJi_pUYsRQBqPpWpQ","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=3_7645Ep4Dg","3":"Radioactive Uranium ore, Rum jungle Northern Territory ...","4":"Radioactive Uranium ore, Rum jungle Northern Territory, Australia","10":"FuqIblHgNhtGnh"},"5":{"1":"hUMaBUtsTrmInKc"},"7":{"1":{"11":{"1":"Radioactive Uranium ore, Rum jungle Northern Territory, Australia","2":"Uranium ore specimen from Rum jungle country, Northern Territory. Tested  with a 3007a Dosimeter and Labgear fast Dekatron counter.","3":"2:42","4":"1374","5":"1420416000000","6":"rustymotor","7":"14","8":"7"}}}},{"1":{"1":"https://cdn.thisiswhyimbroke.com/images/fluorescent-uranium-ore-640x533.jpg","3":640,"4":533},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKbqgNyMbbiki1a-c1dPOKvdBhH_M1GlbLZHjSAZcQKSgm3ALT","3":200,"4":166},"3":{"1":"ThisIsWhyImBroke","2":"https://www.thisiswhyimbroke.com/fluorescent-uranium-ore/","3":"Fluorescent Uranium Ore","4":"","10":"vDobLHxiyuxUJm"},"5":{"1":"ilUYbeQvEMSaiGq"}},{"1":{"1":"http://www.ansnuclearcafe.org/wp-content/uploads/2012/05/uranium-ore.png","3":374,"4":226},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmU9YwfbSb3HA5fb6wEDVwLL4g7tFlg4kXkoSVmItr16PIDn45","3":200,"4":120},"3":{"1":"ANS Nuclear Cafe","2":"http://ansnuclearcafe.org/2012/05/19/105th-carnival-of-nuclear-energy-bloggers/uranium-ore-2/","3":"uranium ore | ANS Nuclear Cafe","4":"Uranium ore","10":"ucBMicCUggRoEY"},"5":{"1":"BdFrkpRGSIkHXya"}},{"1":{"1":"http://uraha.de/de/wp-content/uploads/2016/02/Uran_1_1_uraniumcircit.jpg","3":484,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYXbv-9XOvU7Be3K5-4KcMJbb_jWX88YgECOeR6kgbY1XUo1AlWA","3":200,"4":144},"3":{"1":"URAHA Foundation Germany eV","2":"http://uraha.de/de/?p=409&lang=en","3":"Uranium ore deposits – URAHA Foundation Germany e.V.","4":"Uraniumcircit (Photo: Lang)","10":"BSJPqVSgvBEbrQ"},"5":{"1":"MVxLPqbHMubLNSr"}},{"1":{"1":"https://cdn.thisiswhyimbroke.com/images/uranium-ore1-640x533.jpg","3":640,"4":533},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR1sJSAdreV-tpcQGvCDqxuJTzh9XYNRbqXtQsIyC-l4aBfyKHC","3":200,"4":166},"3":{"1":"ThisIsWhyImBroke","2":"https://www.thisiswhyimbroke.com/fluorescent-uranium-ore/","3":"Fluorescent Uranium Ore","4":"","10":"dqJIUarueXyCWj"},"5":{"1":"WVggkadJTcMCXgn"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Torbernite_-_Cuneo%2C_Italia_01.jpg/220px-Torbernite_-_Cuneo%2C_Italia_01.jpg","3":220,"4":165},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTTgxEh0wD7ohE1CVBSCVwbHqFrCuGXpZYfaVNWaS_C6su6PoxEFA","3":200,"4":150},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Uranium_ore","3":"Uranium ore - Wikipedia","4":"Torbernite, an important secondary uranium mineral","10":"iWOIIHWFYNlcfq"},"5":{"1":"vYhTmBdaSUrGAkL"}},{"1":{"1":"http://unitednuclear.com/images/oregenerica.jpg","3":500,"4":424},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRfr9T5f37v30ppVmlZD8YQozfb5WBC1GA5gHlrCkNxi24GgBlA","3":200,"4":169},"3":{"1":"United Nuclear","2":"http://unitednuclear.com/index.php?main_page=product_info&products_id=460","3":"Generic Uranium Ore, range 'A ' 1,000 to 3,000 CPM : United ...","4":"Generic Uranium Ore, range 'A ' 1,000 to 3,000 CPM","10":"AqIrNMrWQlnvWt"},"5":{"1":"VqdNlIqLFBgvaJP"}},{"1":{"1":"https://cna.ca/wp-content/uploads/2014/06/Uranium-ore-2.jpg","3":1444,"4":916},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSoGKwXryzTIu5CLl-0KJgiJ-mJRBPTKNOJ_C6h12QuDPrATgOjQ","3":200,"4":126},"3":{"1":"Canadian Nuclear Association","2":"https://cna.ca/technology/energy/uranium-mining/","3":"Uranium mining - Canadian Nuclear Association","4":"Uranium ore","10":"IxNjLhyxSUqpUD"},"5":{"1":"mGuODpmVFesTMfq"}},{"1":{"1":"https://i.pinimg.com/originals/da/e7/31/dae731639771cc01af9baf342af42e5b.jpg","3":400,"4":315},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJXZB6Uoa72FIyOu687kMmo8CBlk32eFN1ywlmN03VJrTrqtl10Q","3":200,"4":157},"3":{"1":"Pinterest","2":"https://www.pinterest.com/pin/397935317044389548/","3":"Uranium ore! | christmas list | Pinterest | Mushroom fungi","4":"Uranium ore!","10":"YClYGRtfYuKJak"},"5":{"1":"dSyPSaEeHVWDqfI"}},{"1":{"1":"http://www.sott.net/image/s13/269853/full/Uraniumore.jpg","3":640,"4":409},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSGNSiJrU5IjB9SD-lavkngAd7vYEVpFm7umnqTqQPkObwJ-2C0","3":200,"4":127},"3":{"1":"Sott","2":"https://www.sott.net/article/302699-Truck-carrying-uranium-ore-catches-fire-near-Illinois-nuclear-plant","3":"Truck carrying uranium ore catches fire near Illinois nuclear ...","4":"uranium ore","10":"WlVtKUAhLJNfhk"},"5":{"1":"QOEQBiRDmPrVWBF"}},{"1":{"1":"http://unitednuclear.com/images/oregenericc.jpg","3":500,"4":374},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQreIUjsDelu90Hrb-2tdtoxvNQoBd3xdADZ1b_ybbmFX547dTX","3":200,"4":149},"3":{"1":"United Nuclear","2":"http://unitednuclear.com/index.php?main_page=product_info&products_id=462","3":"Generic Uranium Ore, range 'C' 5,500 to 7,000 CPM : United ...","4":"Generic Uranium Ore, range 'C' 5,500 to 7,000 CPM","10":"njnvvBUVetEuQS"},"5":{"1":"bDBBAxsHfTAYina"}},{"1":{"1":"https://www.sciencelearn.org.nz/system/images/images/000/001/928/full/A-lump-of-uranium-ore20160913-2996-18tz440.jpg?1522304554","3":350,"4":233},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQxCEaTAsqIuSl67rkGv4MI8Ju45c73JGkOHJbQXTt-3AncL-JrVg","3":200,"4":133},"3":{"1":"Science Learning Hub","2":"https://www.sciencelearn.org.nz/images/1928-a-lump-of-uranium-ore","3":"A lump of uranium ore — Science Learning Hub","4":"A lump of uranium ore","10":"EiNQYOwJthGmeV"},"5":{"1":"bELJSUXdwPDGErp"}},{"1":{"1":"https://www.atomicheritage.org/sites/default/files/Shinkolobwe%20Uranophane.jpg","3":600,"4":542},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQnRaRstptBcxVfjvPstHfsAlobXzGAgOWHmKRy85UYnRw7h1CDzw","3":200,"4":180},"3":{"1":"Atomic Heritage Foundation","2":"http://www.atomicheritage.org/history/combined-development-trust","3":"Combined Development Trust | Atomic Heritage Foundation","4":"... was an effort spearheaded by General Leslie Groves to control the world  market of uranium ore.","10":"GXposUWyOYUjOA"},"5":{"1":"MLrJwcEqglWkjHP"}},{"1":{"1":"https://www.researchgate.net/profile/Harald_Dill/publication/225633139/figure/fig1/AS:302565414719493@1449148624739/Yellow-uranium-ore-minerals-a-Aggregates-of-slender-prisms-of-brown-b-uranophane.png","3":733,"4":547},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEKjfsWqMGl4hFqfGy-lzXKWwBoYh6wOaNO3N0cRNBgr6QZUe4","3":200,"4":149},"3":{"1":"ResearchGate","2":"https://www.researchgate.net/figure/Yellow-uranium-ore-minerals-a-Aggregates-of-slender-prisms-of-brown-b-uranophane_fig1_225633139","3":"Fig. 5 Yellow uranium ore minerals. a Aggregates of slender ...","4":"5 Yellow uranium ore minerals. a Aggregates of slender prisms of brown β  -uranophane.","10":"rmDEmetocgXAKg"},"5":{"1":"dvPqyYaaipTTMAV"}},{"1":{"1":"https://images-na.ssl-images-amazon.com/images/I/51LrKbS8ajL._SX342_.jpg","3":342,"4":323},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3RP2p3i33znUvJ6fbjNFc9-qYwYGO1tu1wu0CSeqQVabLJG6ZiA","3":200,"4":188},"3":{"1":"Amazon.com","2":"https://www.amazon.com/Images-SI-Uranium-Ore/dp/B000796XXM","3":"Amazon.com: Uranium Ore: Industrial & Scientific","4":"Uranium Ore","10":"bhYHaPCiSXkTvX"},"5":{"1":"onKaEPQLbBfVatM"},"7":{"1":{"10":{"1":3.5,"2":1293,"3":"Uranium Ore","4":"Images SI","5":"Radioactive sample of uranium ore. The ore sample material is Naturally  Occurring Radioactive Materials (NORM). Counts Per Minute (CPM) activity  rate ...","6":true,"7":39.95000076293945,"8":"USD"}}}},{"1":{"1":"https://c8.alamy.com/comp/BKJ16C/uranium-ore-rocks-west-cornwall-BKJ16C.jpg","3":1300,"4":956},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYlZK2UaapmUqrLpDu70rVzqTT6NA61fAeyCo317iFFtPshmHW","3":200,"4":146},"3":{"1":"Alamy","2":"https://www.alamy.com/stock-photo-uranium-ore-rocks-west-cornwall-29284932.html","3":"Uranium ore; rocks; west Cornwall Stock Photo: 29284932 - Alamy","4":"Uranium ore; rocks; west Cornwall","10":"lJAXaGnSHpRfoU"},"5":{"1":"JBRendfBGTuTvxW"}},{"1":{"1":"https://i.ytimg.com/vi/DBXrr7N9kKs/maxresdefault.jpg","3":1304,"4":1032},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBXs9nco7zuFLKLk-tNGc9ZuMLjsra9buptZfLoNGXNW113UEW","3":200,"4":158},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=DBXrr7N9kKs","3":"HOW IT WORKS: Uranium Deposits - YouTube","4":"","10":"iBejAnpsixRNpa"},"5":{"1":"EIPCUcvIBEVlmhd"},"7":{"1":{"11":{"1":"HOW IT WORKS: Uranium Deposits","2":"The formation of uranium deposits in the earth is explained and where to  find them.","3":"24:01","4":"145842","5":"1404864000000","6":"DOCUMENTARY TUBE","7":"337","8":"96"}}}},{"1":{"1":"https://antinuclearinfo.files.wordpress.com/2013/05/uranium-ore.gif?w=300&h=229","3":300,"4":229},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ8T_qLbyYQkzuowvWo8HBjwL-HAwWXhc6Lloi8ubq7NxSAJPn9","3":200,"4":152},"3":{"1":"Nuclear-News.net","2":"https://nuclear-news.net/2015/07/10/investigation-at-last-into-radioactive-pollution-of-johannesburg-from-uranium-mining/","3":"Investigation at last into radioactive pollution of ...","4":"Investigation at last into radioactive pollution of Johannesburg, from uranium  mining","10":"HnrxEBILvQkpOy"},"5":{"1":"nRucRoeKfJXqFxP"}},{"1":{"1":"http://www.cca.org/blog/images/uranium-ore.jpg","3":1000,"4":665},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS_uexaGHzyyA8K0Qm2td_dIcrgvTmcOFPyLDcphsR4gpJoxeI-","3":200,"4":133},"3":{"1":"Dave Fischer Weblog","2":"http://www.cca.org/blog/20120305-Uranium-Ore.shtml","3":"Dave Fischer Weblog","4":"Uranium Ore.","10":"RkChWglXYuHiCm"},"5":{"1":"LforPPQgUJdQwtW"}},{"1":{"1":"https://www.miningafrica.net/wp-content/uploads/2016/08/Gummite-Uraninite-Zircon-62299.jpg","3":600,"4":493},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8Em1d_798dXwXjgbatsQuQ56eeOmcKHmXeCu1cDObKXlJgwIqWA","3":200,"4":163},"3":{"1":"Mining Africa","2":"https://www.miningafrica.net/natural-resources-africa/mining-uranium-in-africa/","3":"Mining Uranium in Africa","4":"It only became known that Uranium is radioactive in the 1890s. The French  physicist Antoine Henri ...","10":"BEtTejSuTPBcBv"},"5":{"1":"fwMhNLexWVpLyHL"}},{"1":{"1":"http://uraha.de/de/wp-content/uploads/2016/02/Uran_1_1_torbernite.jpg","3":476,"4":331},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS079SrqlTpBo1n1dmw30F4aV154GvSSPPjm0f4lx2-ODMaw_lQ","3":199,"4":139},"3":{"1":"URAHA Foundation Germany eV","2":"http://uraha.de/de/?p=409&lang=en","3":"Uranium ore deposits – URAHA Foundation Germany e.V.","4":"Torbernite, an important secondary uranium mineral (Photo: Aangelo)","10":"QKcgvUhHbwCTrJ"},"5":{"1":"oxDhPBfwnEUdPAq"}},{"1":{"1":"http://unitednuclear.com/images/oregenericb.jpg","3":500,"4":412},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRouW9zQOLSAsQ7gTV6GskfzJRe0YE3xwtSmHRrNdORK7pSUNVi","3":200,"4":165},"3":{"1":"United Nuclear","2":"http://unitednuclear.com/index.php?main_page=product_info&products_id=461","3":"Generic Uranium Ore, range 'B' 3,500 to 5,000 CPM : United ...","4":"Generic Uranium Ore, range 'B' 3,500 to 5,000 CPM","10":"wngjWxwrNFdpfY"},"5":{"1":"suepfIIYjVLClCr"}},{"1":{"1":"http://nevada-outback-gems.com/mineral_information/carnotite02.jpg","3":481,"4":385},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLm3Pc7sHZ97mDx8dVQeW0IO-_R5J75qt5ddm2zgQrTpaRox9r6w","3":200,"4":160},"3":{"1":"Nevada Outback Gems","2":"http://nevada-outback-gems.com/Base_ores/Vanadium_ore.htm","3":"Photos of Natural Vanadium Ore, Vanadium minerals and specimens","4":"","10":"hJwcXLvYUKeohc"},"5":{"1":"fXvuWbanhBKavSa"}},{"1":{"1":"https://image.slidesharecdn.com/topic5-uraniumoredeposits-151123233751-lva1-app6891/95/uranium-ore-deposits-1-638.jpg?cb=1515416471","3":638,"4":479},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRp9WyI3pu5dWpY7YwW-Ye9kSrE3ekVEytb6SAXpjwHhbX1ODrKFw","3":200,"4":149},"3":{"1":"SlideShare","2":"https://www.slideshare.net/hzharraz/uranium-ore-deposits","3":"Uranium Ore Deposits","4":"Topic 5: Uranium Ore Deposits Hassan Z. Harraz hharraz2006@yahoo.com 2012  ...","10":"sRmdBVvmonxEpy"},"5":{"1":"rIlPJsVLKNgkDAX"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Pitchblende_schlema-alberoda.JPG/220px-Pitchblende_schlema-alberoda.JPG","3":220,"4":164},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS7EEEtGcfbvzMoNY8dn5zY5aO6HmrB12mbY8LuQI8Kd_VmgmTfMg","3":200,"4":149},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Uranium_ore","3":"Uranium ore - Wikipedia","4":"Uranium minerals[edit]","10":"RSiPQByYGTChQJ"},"5":{"1":"BLCmBsMpofnWKno"}},{"1":{"1":"http://www.ioffer.com/img/item/643/193/629/uraninite-pitchblende-uranium-ore-410-309e.jpg","3":580,"4":326},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcScBLPgjcic6PoDFMVuNxcGz6fXcJfTYTnoia2NbqeLz2l-fUcfgQ","3":200,"4":112},"3":{"1":"iOffer","2":"http://www.ioffer.com/i/uraninite-pitchblende-uranium-ore-410-643193629","3":"URANINITE PITCHBLENDE URANIUM ORE 410 for sale","4":"URANINITE PITCHBLENDE URANIUM ORE 410. «","10":"fCAEhnojVGLbXe"},"5":{"1":"UopSkuqGDGHgqYI"},"7":{"1":{"10":{"1":5.0,"3":"URANINITE PITCHBLENDE URANIUM ORE 410","5":"botryoidal uraninite , from Shaft 4 /Pribram , Czech Rep. , 410 µsv/h with  SBM-20@ 1cm , in 6x4cm box, paypal or skrill only, , Shipping Included!!!!  ...","6":false,"7":69.0,"8":"USD"}}}},{"1":{"1":"https://wiki.factorio.com/images/Electric_mining_drill-Uranium_ore.png","3":300,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFhukFSWQx7eHxhvZcQdOUT7H5iozgUhW1LXULfNXMNy_0TSpINw","3":200,"4":200},"3":{"1":"Official Factorio Wiki - Factorio","2":"https://wiki.factorio.com/Uranium_ore","3":"Uranium ore - Factorio Wiki","4":"Electric mining drill placed on uranium ore, pipe input/output visible.","10":"rpsNWfGUeFhSFH"},"5":{"1":"xSbqhsPwkeNJJwj"}},{"1":{"1":"https://d32ogoqmya1dw8.cloudfront.net/images/research_education/nativelands/Navajo_mine.jpg","3":1536,"4":1024},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrK3Fn7KNQLi-7ex_egj4jahjSGX8MDMSr9jV6fJk8qnKWiRO7","3":200,"4":133},"3":{"1":"SERC - Carleton","2":"https://serc.carleton.edu/research_education/nativelands/navajo/uraniumdeposits.html","3":"Uranium Deposits","4":"","10":"OPpSedewOjOjFm"},"5":{"1":"IwasypKdPbbkdbm"}},{"1":{"1":"https://vignette.wikia.nocookie.net/feed-the-beast/images/3/3f/Uranium_Ore_Block.png/revision/latest?cb=20130214161003","3":256,"4":256},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ0h1LlRX57eB5Seh1DZ7kRPEZBjmdO6Oi2L2vET1ZuAi2LTsyV","3":200,"4":200},"3":{"1":"Feed The Beast Wiki - Fandom","2":"http://feed-the-beast.wikia.com/wiki/Uranium_Ore_(Block)","3":"Uranium Ore (Block) | Feed The Beast Wiki | FANDOM powered by ...","4":"Uranium Ore","10":"cjtOgJKjdrbTlM"},"5":{"1":"FHxEnUGGXWIXGvM"}},{"1":{"1":"http://www.abc.net.au/news/image/189970-3x2-940x627.jpg","3":940,"4":627},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR26n4Kg9hDPNpZZfP9sKNtDgObRqfssUpAuqj2V-48xc0HJhK0KQ","3":200,"4":133},"3":{"1":"ABC","2":"http://www.abc.net.au/news/2017-07-18/a-haul-truck-carries-uranium-ore/8718504","3":"A haul truck carries uranium ore - ABC News (Australian ...","4":"A haul truck carries uranium ore","10":"mxShrEfddOaeoO"},"5":{"1":"RBmTMcuVHqUjext"}},{"1":{"1":"https://carlwillis.files.wordpress.com/2008/05/lv_forsale.jpg","3":1000,"4":608},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT-6KvJESWkqhrOnLp92rsyDglAWSo25nQ6XgS7Pz8vLbYangT07w","3":200,"4":121},"3":{"1":"Special Nuclear Material - WordPress.com","2":"https://carlwillis.wordpress.com/2008/05/05/for-sale-uranium-ore/","3":"For Sale: Uranium Ore | Special Nuclear Material","4":"","10":"emOhCdmtvWuqxy"},"5":{"1":"KaHBJwWvAnWHxWU"}},{"1":{"1":"https://3c1703fe8d.site.internapcdn.net/newman/gfx/news/hires/2015/1-scientistsse.jpg","3":3654,"4":1998},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPtwII-3qnD47udpLTwGERykilZ63nZpdyFngPEX_NSu8XB2ONZQ","3":200,"4":109},"3":{"1":"Phys.org","2":"https://phys.org/news/2015-01-scientists-ways-uranium-ore-legacy.html","3":"Scientists search for new ways to deal with US uranium ore ...","4":"Scientists search for new ways to deal with US uranium ore processing legacy","10":"fxhnuqMXKASHgD"},"5":{"1":"NXKnOHjeFeBlMhU"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Pitchblende371.JPG/220px-Pitchblende371.JPG","3":220,"4":165},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR55Fad8E_lL6V6bCKaBdTczoSYdZVbCDBHajNr0O65HLmBr5GV","3":200,"4":150},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Uranium_ore","3":"Uranium ore - Wikipedia","4":"Uranium ore (pitchblende in dolomite) from the vein-type deposit  Niederschlema-Alberoda","10":"DRckVycLowVDNu"},"5":{"1":"VDlQeLSNRXHBbsC"}},{"1":{"1":"http://www.republicoflakotah.com/wp-content/uploads/2010/03/ISL-Diagram2.gif","3":420,"4":293},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQxBQbzOxWVYByDlrNOJS2meHl-effFoxlYbokZmSyCQlqKINUXLw","3":199,"4":139},"3":{"1":"TU Freiberg","2":"https://tu-freiberg.de/umh-vii-2014","3":"Uranium Mining and Hydrogeology 2014 International Conference ...","4":"Session I: Uranium mining","10":"PQiLQrvMaQoOHn"},"5":{"1":"YUuAOodADCEBjAi"}},{"1":{"1":"https://images-na.ssl-images-amazon.com/images/I/51sOTDswZ0L._SX425_.jpg","3":425,"4":319},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSi0-trSU79rMckw3x4ZOwC1lQpTQNTqnyrRrDeKd8-3CL4VlYZzQ","3":200,"4":149},"3":{"1":"Amazon.com","2":"https://www.amazon.com/uranium-unrefined-uraninite-radiation-detector/dp/B00CQ9LLR4","3":"Rare earth uranium oxide, high grade unrefined uranium ore ...","4":"Rare earth uranium oxide, high grade unrefined uranium ore uraninite, for  Geiger counter &","10":"fpeVKHGKMYkVvG"},"5":{"1":"hMJKYgbarWYolsf"},"7":{"1":{"10":{"1":4.0,"2":69,"3":"Rare earth uranium oxide, high grade unrefined uranium ore uraninite, for  Geiger counter & radiation detector test source!","4":"LifeTech","5":"The rare earth uranium oxide, naturally high grade uranium ore contains  high concentration of uraninite which can be used to test your Geiger  counter, ...","6":true,"7":79.9000015258789,"8":"USD"}}}},{"1":{"1":"https://thumbs.dreamstime.com/b/uranium-ore-7968842.jpg","3":800,"4":642},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRfDCPo3aFV1FsQ-Co0GUw8rjQwkrlKTnVsmmbSqJLKC-OuYzMfKw","3":200,"4":160},"3":{"1":"Dreamstime.com","2":"https://www.dreamstime.com/stock-photography-uranium-ore-image7968842","3":"Uranium ore stock photo. Image of rock, industry, activity ...","4":"Uranium ore - isolated object on white background","10":"lFgPMffOrsdglO"},"5":{"1":"GAGCRvPsInlrCVp"}},{"1":{"1":"https://www.dnddice.com/media/catalog/product/cache/1/image/650x/613132e0f270af58849e99a6dbb00be2/m/a/marbled_nick_yellow.jpg","3":650,"4":655},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTWFIWTzKbGt_-X5vW437tZv8qB2KM0WIPIonWHMox4yfraI85s","3":199,"4":200},"3":{"1":"DnD Dice","2":"https://www.dnddice.com/sets-of-dice/uranium-ore-dice-set-opaque.html","3":"Uranium Ore Dice Set (Marbled) - Sets of Dice","4":"Uranium Ore Dice Set (Marbled)","10":"lDtobcULsHuDEs"},"5":{"1":"CUfvqkkkYhexTmG"}},{"1":{"1":"https://i.ebayimg.com/images/g/ZUAAAOSw8jVapWYd/s-l300.jpg","3":300,"4":281},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSLL-gQGDHliqAAkwizhTCbydcVOftQGPQw3rRqIgN7635H4oSc","3":200,"4":187},"3":{"1":"eBay","2":"https://www.ebay.com/itm/URANIUM-ORE-ELEMENT-92-COLLECTORS-SAMPLE-IN-JAR-5-0-to-6-0-GM-/153034952406","3":"URANIUM ORE, ELEMENT #92, COLLECTOR'S SAMPLE IN JAR, 5.0 to ...","4":"Image is loading URANIUM-ORE-ELEMENT-92-COLLECTOR-039-S-SAMPLE-","10":"mNpopJVFxQrnya"},"5":{"1":"iVvPpnldBUCGNXi"},"7":{"1":{"10":{"3":"Details about URANIUM ORE, ELEMENT #92, COLLECTOR'S SAMPLE IN JAR, 5.0 to  6.0 GM +","5":"URANIUM ORE, ELEMENT #92, COLLECTOR'S SAMPLE IN JAR, 5.0 to 6.0 GM + |  Collectibles, Rocks, Fossils & Minerals, Crystals & Mineral Specimens |  eBay!","7":6.5,"8":"USD"}}}},{"1":{"1":"https://blogs.sap.com/wp-content/uploads/2013/08/uranium_ore_256462.jpg","3":274,"4":184},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT-B4iVhhSn-aSVkwhaNBxj-EVvYpXqAot_xaFQl8zFaqpdtvwENA","3":200,"4":134},"3":{"1":"SAP Blogs","2":"https://blogs.sap.com/2013/08/03/uranium-mining/","3":"Uranium Mining | SAP Blogs","4":"About Uranium Uranium Ore.jpg","10":"FMUDYvtjGcwkkY"},"5":{"1":"tKaSxPOctyupeuH"}},{"1":{"1":"https://greentumble.com/wp-content/uploads/2016/11/Environmental-impacts-of-uranium-mining.jpg","3":800,"4":500},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTaNnLOEdRMnLDqAb99SNc7wfxtk58huSsUi4vinIsNrf7-PHw4gg","3":200,"4":124},"3":{"1":"Greentumble","2":"https://greentumble.com/environmental-impacts-of-uranium-mining/","3":"Environmental Impacts of Uranium Mining | Greentumble","4":"Environmental impacts of uranium mining","10":"mrFxmtNXvpHlNt"},"5":{"1":"KuerxbEKttWuPLV"}},{"1":{"1":"https://c1.staticflickr.com/3/2566/4058064866_ce4a2b2c53_b.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvky2ZpyEH6n11HPYAXDRzG6dV1ljdU5jr9CL6vJSF_T_6kwa02g","3":200,"4":149},"3":{"1":"Flickr","2":"https://www.flickr.com/photos/bionerd/4058064866/in/pool-10372360@N00/","3":"pitchblende uranium ore blisters | very beautiful, big black ...","4":"... pitchblende uranium ore blisters | by bionerd23 ☢","10":"VTmkPJKhTRRdsW"},"5":{"1":"KTPrWoVlIutiblb"}},{"1":{"1":"http://energyeducation.ca/wiki/images/thumb/8/82/Openpit.jpg/300px-Openpit.jpg","3":300,"4":200},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQv2IpxKcOVjZRoPvYLl2RPSCYdJYo23xr4QQvY2HKf7VT7HoRj","3":200,"4":133},"3":{"1":"Energy Education","2":"http://energyeducation.ca/encyclopedia/Uranium_mining","3":"Uranium mining - Energy Education","4":"Uranium mining","10":"PSSeQtHLcKjsyy"},"5":{"1":"pdbvTOCwHmiiCNm"}},{"1":{"1":"https://www.wnti.co.uk/media/3990/1.jpeg","3":750,"4":562},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQiA78QEyJ33i6F2Yj3KXy_JaaEnAAcAXcB42oNpYA1CYwlQ3E6","3":200,"4":149},"3":{"1":"World Nuclear Transport Institute","2":"https://www.wnti.co.uk/media-centre/nuclear-fuel-cycle/uranium-mining-and-refining.aspx","3":"Uranium Mining and Refining | World Nuclear Transport Institute","4":"Uranium Ore Concentrate, Courtesy of the Nuclear Decommissioning Authority 3","10":"IWjAlvHXuPBbmR"},"5":{"1":"XAxhsMHqiMGnxOO"}},{"1":{"1":"https://geoinfo.nmt.edu/resources/uranium/images/upitmine.jpg","3":363,"4":236},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR4H1t_VZ9t1VuHddmc7crKQypetQIwqrCigzUVmE1HzZHvxAYZ","3":200,"4":129},"3":{"1":"New Mexico Bureau of Geology & Mineral Resources","2":"https://geoinfo.nmt.edu/resources/uranium/mining.html","3":"Uranium: How is it Mined?","4":"Rabbit Lake Mine","10":"jiWduexAsVAXgW"},"5":{"1":"CLeQJcVQBoFIagE"}},{"1":{"1":"https://wiki.factorio.com/images/thumb/Glow.png/300px-Glow.png","3":300,"4":288},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT1MSj1u7c97J9C2EtjqGIWe2EKHJ8rJ5EdAw6SQ4fxe4FjgMyNtQ","3":200,"4":192},"3":{"1":"Official Factorio Wiki - Factorio","2":"https://wiki.factorio.com/Uranium_ore","3":"Uranium ore - Factorio Wiki","4":"Uranium ore","10":"PcQGCwoVlQSrIY"},"5":{"1":"FPqpErYdeYDiUGO"}},{"1":{"1":"https://ground-force-training.s3.amazonaws.com/upload/user/image/M&M-Commodities-Uranium20170924192443101.jpg","3":920,"4":520},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRPz1yX-sSLLaN3o0YdR68gr_YkcMccvWjMoumhmTL04h9zTjND","3":200,"4":113},"3":{"1":"Ausenco","2":"http://www.ausenco.com/en/commodity-uranium","3":"Uranium Ore Mining, Processing, Production; Ausenco","4":"Uranium","10":"hlctXrnNGrVTPx"},"5":{"1":"ARHLSTwSQUCvDVa"}},{"1":{"1":"https://d32ogoqmya1dw8.cloudfront.net/images/research_education/nativelands/UraniumDeposits.jpg","3":1069,"4":696},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqi77ywwiUP56AbW7lpI-ephJN9JpUDZRwLXjeeFtcr0DMKFkA","3":200,"4":130},"3":{"1":"SERC - Carleton","2":"https://serc.carleton.edu/research_education/nativelands/navajo/uraniumdeposits.html","3":"UraniumDeposits.jpg","4":"Uranium Deposits on the Navajo Nation","10":"RqykeJkdrEJoox"},"5":{"1":"qyToUXsGyIkStsP"}},{"1":{"1":"https://i.ytimg.com/vi/bCYiBXolKLg/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRr6MOvrW_Z_bzPWGrYowSudjGz8BBDA48LVqROH57ksR6dQBef","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=bCYiBXolKLg","3":"Uraninite hunting - finding Uranium ore at shaft 4 - YouTube","4":"","10":"DfjhwMoDvFmhjw"},"5":{"1":"xSLsTRSSAwJXOeU"},"7":{"1":{"11":{"1":"Uraninite hunting - finding Uranium ore at shaft 4","2":"this is at the shaft #4 dump near Pribram /Czech Rep., Tube is SI-15BG,  Geiger counter is Mygeiger V2.0 with SBM-20 from rhelectronics.net *new  video*: https...","3":"10:24","4":"7888","5":"1431648000000","6":"weirdmeister inc.","7":"86","8":"17"}}}},{"1":{"1":"http://www.mining.com/wp-content/uploads/2016/09/namibias-new-uranium-mine-to-triple-countrys-output-by-2017.jpg","3":900,"4":505},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFG-Dff9s5BHT2F1F6K6UjYae_OLK-y2vLBIDOSmIJit7IAWnOYg","3":200,"4":112},"3":{"1":"MINING.com","2":"http://www.mining.com/namibias-new-uranium-mine-triple-countrys-output-2017/","3":"Namibia's new uranium mine to triple country's output by 2017 ...","4":"Namibia's new uranium mine to triple country's output by 2017","10":"jxnEOGqQAmQeID"},"5":{"1":"IOpOLAIRwJAWxKU"}},{"1":{"1":"https://www3.epa.gov/radtown/images/uranium-ore-small.jpg","3":209,"4":188},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTg_rtmpXq9c9BUYEXHb9Y7V0kw6B_xV0735UXESJhESvyiYHO5","3":200,"4":179},"3":{"1":"EPA","2":"https://www3.epa.gov/radtown/uranium-mines-mills.html","3":"Uranium Mines and Mills | RadTown USA | US EPA","4":"Uranium ore.","10":"EnbXhrObjPNjlK"},"5":{"1":"MlWPlauEsaDgTqc"}},{"1":{"1":"http://www.walletwrecker.com/wp-content/uploads/2017/02/uranium-ore-paperweight.jpg","3":780,"4":690},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDwWe9IuEuH7JtF6l36LPGt84oX1M30KMIR3Rtb3XW-JMd0b4L","3":200,"4":176},"3":{"1":"Cool Stuff","2":"http://www.walletwrecker.com/uranium-ore-paperweight/","3":"Uranium Ore Paperweight - WalletWrecker","4":"Uranium Ore Paperweight","10":"VTykOlfiIMxIEj"},"5":{"1":"ChvBQDrmkJAWaoA"}},{"1":{"1":"https://bloximages.chicago2.vip.townnews.com/azdailysun.com/content/tncms/assets/v3/editorial/8/ae/8aedbad9-4c22-51f9-a5a4-c3ea8515d944/59e2c68821afb.image.jpg","3":228,"4":341},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRnVE4UYV0Qs53XdLGrePAjB6TbFkXI_d2AgiaZ-I7AW70d2U7O","3":133,"4":200},"3":{"1":"Arizona Daily Sun","2":"http://azdailysun.com/news/local/new-uranium-mines-no-simple-answers/article_20522e2c-98ed-58c4-a6cf-93ee27da9aa2.html","3":"New uranium mines: no simple answers | Local | azdailysun.com","4":"Pinenut Mine underground","10":"qkNfYeDKPPEKYU"},"5":{"1":"IutbavLAJOjFHen"}},{"1":{"1":"https://c8.alamy.com/comp/M14C80/fort-davis-texas-uranium-ore-in-the-chihuahuan-desert-mining-heritage-M14C80.jpg","3":1300,"4":956},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcST-CQ0gKpU0YteBEcSBmB8Ev-LBuw-HuMgXJXxD80hNJ-HlGLFHw","3":200,"4":146},"3":{"1":"Alamy","2":"https://www.alamy.com/stock-photo-fort-davis-texas-uranium-ore-in-the-chihuahuan-desert-mining-heritage-172815776.html","3":"Fort Davis, Texas - Uranium ore in the Chihuahuan Desert ...","4":"Fort Davis, Texas - Uranium ore in the Chihuahuan Desert Mining Heritage  Exhibit at the Chihuahuan ...","10":"UBxpddAFAwRjgw"},"5":{"1":"AGIGVWDfGiJCbtH"}},{"1":{"1":"https://image.slidesharecdn.com/uraniumoredepositsinegypt-161030181530/95/uranium-ore-deposits-in-egypt-5-638.jpg?cb=1515416002","3":638,"4":479},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTnp6u3T7uXrv_Yibxe3DR1agjgkXYg_EGhM1yPJ8ZIV0MI-8zS","3":200,"4":149},"3":{"1":"SlideShare","2":"https://www.slideshare.net/hzharraz/uranium-ore-deposits-in-egypt","3":"URANIUM ORE DEPOSITS IN EGYPT","4":"","10":"WEgTtqKJfVTjNc"},"5":{"1":"LenKYmayTuHJGvq"}},{"1":{"1":"https://vignette.wikia.nocookie.net/starboundgame/images/f/f3/Uranium-0.png/revision/latest?cb=20150430191627","3":278,"4":274},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTRd0RMVJF-9eJ2p2QKYGwneLGVCf7koVrhrdMP3F0fTmwynjLH","3":200,"4":197},"3":{"1":"Starbound Wiki - Fandom","2":"http://starbound.wikia.com/wiki/Uranium_Ore","3":"Uranium Ore | Starbound Wiki | FANDOM powered by Wikia","4":"Uranium-0","10":"NAUrpgvWASmJnt"},"5":{"1":"JWELSnTbteHvAJV"}},{"1":{"1":"https://file.ejatlas.org/docs/Rossing-uranium-mine-near-008.jpg","3":460,"4":276},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZgMEJmhy8irJjPAZWmgbkoURXeAImcsUXN-W-SnWU0rz5Zlxmhg","3":199,"4":119},"3":{"1":"EJAtlas","2":"https://ejatlas.org/conflict/rio-tintos-rossing-uranium-mine-namibia","3":"Rio Tinto's Rössing Uranium Mine, Namibia | EJAtlas","4":"Rio Tinto's Rössing Uranium Mine, Namibia","10":"OhVbJHbOaxpJTm"},"5":{"1":"yhFGyEGORtvxyiT"}},{"1":{"1":"https://thumbs3.ebaystatic.com/d/l225/m/mKiNHUomL_2vUOfQwaPTtAQ.jpg","3":225,"4":169},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKRhLsXJdCdro31Ub7eNF_LhDdM1jfMcJqF35fpIOLtvUrBQiL","3":200,"4":150},"3":{"1":"eBay","2":"https://www.ebay.com/bhp/uranium-ore","3":"Uranium Ore: Crystals & Mineral Specimens | eBay","4":"RARE URANIUM Ore HAYNESITE type locale Repete Mine Blanding Utah LARGE!","10":"BmEyAvaFQTxYHs"},"5":{"1":"PRRWIHqYNnbEhku"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Uranium_production_world.PNG/300px-Uranium_production_world.PNG","3":300,"4":132},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQWPwZFkWSmelETZtm3W8ytFo3f8MAkVQGVv9xR6g2poaYN6tebDQ","3":200,"4":88},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Uranium_mining","3":"Uranium mining - Wikipedia","4":"World Uranium production in 2005.","10":"lsykkyWvdhGkhI"},"5":{"1":"DiIqNhbruIGsROR"}},{"1":{"1":"https://www.researchgate.net/profile/Tyler_Spano/publication/320569651/figure/fig1/AS:560662205210624@1510683694153/Example-of-uranium-ore-samples-and-their-associated-alteration-rinds-Great-Bear-Lake-and.png","3":850,"4":232},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQGakvvuKcktkpJwUfcIEetuPkAFoyaFJamqY9nG8KwajgWL66cTA","3":200,"4":54},"3":{"1":"ResearchGate","2":"https://www.researchgate.net/figure/Example-of-uranium-ore-samples-and-their-associated-alteration-rinds-Great-Bear-Lake-and_fig1_320569651","3":"Example of uranium ore samples and their associated ...","4":"Example of uranium ore samples and their associated alteration rinds (Great  Bear Lake and Jefferson","10":"PjnvTFesdEKBRe"},"5":{"1":"VSDXIHQtDjEYvMK"}},{"1":{"1":"https://www.grandcanyontrust.org/sites/default/files/e_uranium_ore.jpg","3":600,"4":660},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRV2vkJir6j5M9GGj9Daws2_5mmfJLHHlMuYlvD-tFgFQq50LJa","3":182,"4":200},"3":{"1":"Grand Canyon Trust","2":"https://www.grandcanyontrust.org/colorado-plateau-uranium","3":"Uranium | Grand Canyon Trust","4":"Uranium - deposits","10":"tixmKKALwfPbAV"},"5":{"1":"gMjqkkdkgUNeyLy"}},{"1":{"1":"http://uranium.csis.org/wp-content/uploads/2014/09/uranium_mine.jpg","3":2318,"4":880},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfTlqkUotU-2s86KZPoKTei68672JI0c3bTzX3Owc_I46nRApIUA","3":200,"4":75},"3":{"1":"Governing Uranium - Center for Strategic and International ...","2":"http://uranium.csis.org/production/","3":"1 - Governing Uranium","4":"01_minephoto_1of2","10":"rdtbvLcLoNbFWF"},"5":{"1":"LjeRklRSOmSTOBV"}},{"1":{"1":"https://vignette.wikia.nocookie.net/thetekkit/images/4/4e/Uranium_Ore_2.png/revision/latest?cb=20121011054332","3":1613,"4":1032},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-2NIuZvYepV4lvhDpyZxosb6pf5BbQ3yke9xkWMnknU3MSriD","3":200,"4":127},"3":{"1":"The Tekkit Classic Wiki - Fandom","2":"http://tekkitclassic.wikia.com/wiki/File:Uranium_Ore_2.png","3":"Image - Uranium Ore 2.png | The Tekkit Classic Wiki | FANDOM ...","4":"Uranium Ore 2.png","10":"fVoMdmhrsqQnoA"},"5":{"1":"DfOlohDTbnVvKyp"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Uraninite-usa32abg.jpg/220px-Uraninite-usa32abg.jpg","3":220,"4":217},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z_u2G5UCMhp9M5MEZVGO39z_Ek0FiZM7ffNguWI1YK56MtGshQ","3":200,"4":197},"3":{"1":"911 Metallurgist","2":"https://www.911metallurgist.com/blog/pitchblende-uraninite-ore","3":"Pitchblende Uranium Ore","4":"... in deposits of this type. pitchblende uraninite","10":"PxpNofJwxlbdey"},"5":{"1":"vmYLxMtxKDQFWxF"}},{"1":{"1":"https://vignette.wikia.nocookie.net/technicpack/images/8/88/Uranium_Ore.png/revision/latest?cb=20121230105240","3":1366,"4":706},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkvZjnZRf1MTyPRxcA5_fUUC7v4ZfluKLN-NPuYBZTpqB_afEB","3":200,"4":103},"3":{"1":"Technic Pack Wiki - Fandom","2":"http://technicpack.wikia.com/wiki/File:Uranium_Ore.png","3":"Image - Uranium Ore.png | Technic Pack Wiki | FANDOM powered ...","4":"Uranium Ore.png","10":"eoRoWdBXHUsICT"},"5":{"1":"RGVYNJSonUGgGTn"}},{"1":{"1":"http://media.kenanaonline.com/photos/1238066/1238066871/large_1238066871.gif?1289334469","3":287,"4":350},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTGTmdR9WCI6pYTw4vspENHpWOi7BVS-K1s4lp2uiVsJ-80XTY5uw","3":163,"4":200},"3":{"1":"بوابات كنانة أونلاين","2":"https://kenanaonline.com/users/absalman/posts/187419","3":"THE URANIUM ORE MINERALS - عبدالعاطي سالمان- مشروع العصر ...","4":"THE URANIUM ORE MINERALS","10":"mNHAuArniWXJRj"},"5":{"1":"CVNwppputpGlJil"}},{"1":{"1":"https://ae01.alicdn.com/kf/HTB1Yg6DIpXXXXalXFXXq6xXFXXXE/Phosphorus-tin-mine-uranium-ore-chalcopyrite-crystal-gem-stone-raw-ore-samples-mathematics-Tian-Yu-mineral.jpg_640x640.jpg","3":640,"4":600},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgmUKhyf7JDiE73fHSE4_cq6M4OLT7bBWQofzuvUCRKK8-a9ws","3":200,"4":187},"3":{"1":"AliExpress.com","2":"https://www.aliexpress.com/item/Phosphorus-tin-mine-uranium-ore-chalcopyrite-crystal-gem-stone-raw-ore-samples-mathematics-Tian-Yu-mineral/32379491924.html","3":"Phosphorus tin mine uranium ore chalcopyrite crystal gem ...","4":"Phosphorus tin mine uranium ore chalcopyrite crystal gem stone raw ore  samples mathematics Tian Yu ...","10":"VROMXGJiTLfNcm"},"5":{"1":"fOtJguCFMFFiTGM"},"7":{"1":{"10":{"3":"Phosphorus tin mine uranium ore chalcopyrite crystal gem stone raw ore  samples mathematics Tian Yu mineral stones-in Aerators from Home  Improvement on ...","6":false,"7":2719.0,"8":"USD"}}}},{"1":{"1":"https://thehightechsociety.com/wp-content/uploads/2017/12/uraniumorefacts-1000x720.jpg","3":1000,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTTzm_aIsh8drvWBOgUN-fCco8pfiWe6D9ZdCZYdZ0MeKuipCmJ","3":199,"4":143},"3":{"1":"The High Tech Society","2":"https://thehightechsociety.com/is-uranium-dangerous-facts-about-uranium-you-may-not-know/","3":"Is Uranium Dangerous - Facts About Uranium You May Not Know ...","4":"Is Uranium Dangerous – Facts About Uranium You May Not Know","10":"XGijdDsAQoSvIl"},"5":{"1":"amATHrpPAUxWKDa"}},{"1":{"1":"https://media.nature.com/m685/nature-assets/ngeo/journal/v5/n2/images/ngeo1386-f1.jpg","3":685,"4":432},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQgjRj8o_JLV2wZN-swnguCcXuW9-Zx2AKuEELmIqiUa4VuULfudg","3":200,"4":125},"3":{"1":"Nature","2":"https://www.nature.com/articles/ngeo1386","3":"Uranium-ore giants | Nature Geoscience","4":"Richard et al. show that the giant high-grade uranium ore found in the  Athabasca Basin could have ...","10":"CKCkDIIYUrnDPb"},"5":{"1":"XbggxJvpqFKrTft"}},{"1":{"1":"http://www.abc.net.au/radionational/image/6593820-3x2-700x467.jpg","3":700,"4":467},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQU2lHa-Tht79z6V7T3AUOMhUz2uPtB8TRSCXcsixKWMHTPp2hX","3":200,"4":133},"3":{"1":"ABC","2":"http://www.abc.net.au/radionational/programs/rearvision/history-of-uranium-mining-in-australia/6607212","3":"The long and controversial history of uranium mining in ...","4":"Ranger uranium mine","10":"AYUiOOonsQcudS"},"5":{"1":"ysejMaDMnehJEVo"}},{"1":{"1":"http://www.ioffer.com/img/item/642/410/160/uraninite-pitchblende-uranium-ore-240-4ae7.jpg","3":580,"4":388},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS6ek08_PoH4HNHBj37nkhiLBztekkXmHHyVxxhfeXKLysCXL_lPg","3":200,"4":133},"3":{"1":"iOffer","2":"http://www.ioffer.com/i/uraninite-pitchblende-uranium-ore-240-642410160","3":"URANINITE PITCHBLENDE URANIUM ORE 240 for sale","4":"URANINITE PITCHBLENDE URANIUM ORE 240. «","10":"VsvtUbUcmgWOtd"},"5":{"1":"TaBEXnwLcVoSGRF"},"7":{"1":{"10":{"1":5.0,"3":"URANINITE PITCHBLENDE URANIUM ORE 240","5":"rare negative botryoidal pitchblende, from Shaft 4 ,Pribram , Czech Rep. ,  240 µsv/h with SBM-20@ 1cm, 4 cm x 3 cm x 2.3 cm , paypal or skrill only,  ...","6":false,"7":44.0,"8":"USD"}}}},{"1":{"1":"https://antinuclear.files.wordpress.com/2012/07/mary-kathleen-uranium-mine.gif","3":504,"4":511},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRbQ8QiG595QEeGQbszjBqy3NSD10vD6HpMDRBbYl-uWgnz_14PEg","3":197,"4":200},"3":{"1":"Antinuclear","2":"https://antinuclear.net/2013/06/12/mary-kathleen-uranium-mine-still-toxic-decades-after-closure/","3":"Mary Kathleen uranium mine – still toxic decades after ...","4":"Mary-Kathleen-Uranium-mine-","10":"fLxfEgPYxMQMvS"},"5":{"1":"SGYSjGfHCKKNkgE"}},{"1":{"1":"https://stationeers-wiki.com/images/2/27/Uranium_ore_dropped.jpg","3":450,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSLJH30zkMiPth0cKLDb2Qlk2SN5BiTM_w_4LlZYthhktUasVRK","3":200,"4":200},"3":{"1":"Unofficial Stationeers Wiki","2":"https://stationeers-wiki.com/Uranium_Ore/en","3":"Uranium Ore - Unofficial Stationeers Wiki","4":"Uranium Ore","10":"XvrtvsArUYHKUS"},"5":{"1":"vKpjKTxbqkQXpom"}},{"1":{"1":"http://teachnuclear.ca/wp-content/uploads/2013/05/McClean-Lake-open-pit.jpg","3":640,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4RMtnL-xV_tEftv9YPNCde6Vo9HV_ZPeWz5wQ7h7l_KC3rnc4","3":200,"4":112},"3":{"1":"Teach Nuclear","2":"http://teachnuclear.ca/all-things-nuclear/nuclear-energy/uranium-mining/","3":"Uranium Mining | Teach Nuclear","4":"Open-pit mine at the McClean Lake facility","10":"scBFjbTjRhqPbE"},"5":{"1":"MjaBBUKfsXDRiUd"}},{"1":{"1":"https://media.istockphoto.com/photos/closeup-of-uranium-ore-on-white-background-picture-id183637629","3":1024,"4":1007},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR6H-joeozc8MoqQeO-qeGFLBp4M_2aUtIRkixABJY6Jye_Zu5d","3":200,"4":197},"3":{"1":"iStock","2":"https://www.istockphoto.com/photo/close-up-of-uranium-ore-on-white-background-gm183637629-27561251","3":"Closeup Of Uranium Ore On White Background Stock Photo & More ...","4":"Close-up of Uranium ore on white background royalty-free stock photo","10":"JjKfCVANlcxWUc"},"5":{"1":"KuRMAoXyPQEJKmd"}},{"1":{"1":"http://www.nsfwallet.com/wp-content/uploads/2013/09/41KH6M0LWJL._SL500_AA300_1.jpg","3":300,"4":300},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR00Ch9vyoO0x--dLLmB0io09RBtdpPBUn0rXF6_EEd4qwrnM6i","3":200,"4":200},"3":{"1":"Not Safe For Wallet","2":"http://www.nsfwallet.com/uranium-ore/","3":"Uranium Ore","4":"","10":"ROirCLHUnEFQbb"},"5":{"1":"bxMXuPXMbeiLMMR"}},{"1":{"1":"http://www.mirarr.net/media/W1siZiIsIjIwMTcvMDcvMDUvNWtocWNwZXp3eV9yYW5nZXIuanBnIl0sWyJwIiwidGh1bWIiLCIxMzIweDU4MSMiXV0/ranger.jpg","3":1320,"4":581},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_57SBkrYkxBS8nDl83hytJAgPncjLdd9EltlBrhZuy20i1NUl","3":199,"4":87},"3":{"1":"The Gundjeihmi Aboriginal Corporation","2":"http://www.mirarr.net/uranium-mining","3":"Uranium Mining – The Gundjeihmi Aboriginal Corporation","4":"Ranger. `","10":"lGQWpalAtncdQk"},"5":{"1":"wFBEtCKIsXalNQq"}},{"1":{"1":"http://1boidr1j8wt01itylm7cszo5r8.wpengine.netdna-cdn.com/wp-content/uploads/AUMmap.jpg","3":480,"4":360},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtC0T56zTdoq3_XYpKrDW0Ssf1EroyWwXmXG8wASNsk2Yk1rCr","3":200,"4":149},"3":{"1":"The Colorado Independent","2":"http://www.coloradoindependent.com/147740/feds-open-door-to-more-uranium-mining-in-southwest-colorado","3":"Feds open door to more uranium mining in Southwest Colorado ...","4":"AUMmap","10":"TTnEbOQmDQMaKs"},"5":{"1":"GBNPxaatFaXEPnN"}},{"1":{"1":"http://eraengineers.com/wp-content/uploads/2016/03/uranium-yellowcake.jpg","3":620,"4":368},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ4pLb2LZOXRVSOtufN0gaWFlxWAtgQ_F-4Z9b1rmuhmd_SIT2xXQ","3":200,"4":118},"3":{"1":"Environmental Resource Associates","2":"http://eraengineers.com/portfolio-view/design-air-pollution-control-ventilation/","3":"Design of Air Pollution Controls and Local Ventilation for ...","4":"Design of Air Pollution Controls and Local Ventilation for Uranium Ore  Processing Plant. «","10":"KOKKEMynLHcTBb"},"5":{"1":"WPQaqJyajPCkeqv"}},{"1":{"1":"http://unitednuclear.com/images/boxorocks.jpg","3":500,"4":535},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSkFRN9gmdSflSkBhW4q2lxTEq6qNFQnZ2hepJf0E7Xv1TcJFmrJA","3":187,"4":200},"3":{"1":"United Nuclear","2":"http://unitednuclear.com/index.php?main_page=product_info&products_id=863","3":"Bulk Uranium Ore Assortment - 5 Pounds : United Nuclear ...","4":"Bulk Uranium Ore Assortment - 5 Pounds","10":"yQyqhXaFvEoueR"},"5":{"1":"CQwbSsHmGnpLwXy"}},{"1":{"1":"https://i.pinimg.com/736x/9b/74/fa/9b74fa1a6c617880f3c027713b8ed0f0--uranium-nerdy.jpg","3":300,"4":232},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQgJUBQCVgGFCbVgsnD-uOQNuJ2lvpplHQYUQ7ce8lC54CiwVvJAg","3":200,"4":154},"3":{"1":"Pinterest","2":"https://www.pinterest.com/michaels0582/uranium-ore/","3":"31 best Uranium Ore images on Pinterest | Crystals, Petroleum ...","4":"Bulk Uranium Ore - 5 Pounds : United Nuclear , Scientific Equipment &  Supplies","10":"VmLBugwkJfYpdv"},"5":{"1":"bRwiTmKbMptmoFd"}},{"1":{"1":"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Marienberg_ore.jpg/220px-Marienberg_ore.jpg","3":220,"4":165},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTVSeTQx_j1CbsN7N3OlSt3Y_ze7MRNPycZj_A07Dn24YEuLRYf","3":200,"4":150},"3":{"1":"Wikipedia","2":"https://en.wikipedia.org/wiki/Uranium_ore","3":"Uranium ore - Wikipedia","4":"Polymetallic uranium ore, Marienberg, Erzgebirge Mts, Germany","10":"oBhUVtBxxpQMct"},"5":{"1":"oGENeuUvxqvGwhY"}},{"1":{"1":"https://www.researchgate.net/profile/Dr_Yamuna_Singh/publication/316716402/figure/fig4/AS:491343119163393@1494156736236/Megascopic-view-of-uranium-ore-sample-used-for-study-Note-a-relict-core-of-black-mineral.png","3":626,"4":538},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ0B9_kwbnm5JXAw-YOZPCMB9sfJyyO9ady26FX7tbJWS-pPZyJ","3":199,"4":171},"3":{"1":"ResearchGate","2":"https://www.researchgate.net/figure/Megascopic-view-of-uranium-ore-sample-used-for-study-Note-a-relict-core-of-black-mineral_fig4_316716402","3":"Fig. 4. Megascopic view of uranium ore sample used for study ...","4":"Megascopic view of uranium ore sample used for study. Note a relict core of  black mineral (uraninite) ...","10":"duflncOKBLXPEx"},"5":{"1":"bwNLaAuVAWvOYxj"}},{"1":{"1":"http://cdn.iofferphoto.com/img3/item/640/729/747/uraninite-pyrite-pitchblende-uranium-ore-230-0ac1.jpg","3":580,"4":386},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTV9n1j2oibvPRX86LkJXrUwHuavrxaNZ41wi4gmV7jOEI-SGcbjg","3":200,"4":133},"3":{"1":"iOffer","2":"http://payments.ioffer.com/i/uraninite-pyrite-pitchblende-uranium-ore-230-640729747","3":"URANINITE + Pyrite PITCHBLENDE URANIUM ORE 230 for sale","4":"URANINITE + Pyrite PITCHBLENDE URANIUM ORE 230. «","10":"BXSwLQenDcTqYd"},"5":{"1":"llsvaTDqVOyMdSS"},"7":{"1":{"10":{"1":5.0,"3":"URANINITE + Pyrite PITCHBLENDE URANIUM ORE 230","5":"uraninite with pyrite (stable) on matrix from Dubenec, Pribram , Czech Rep.  , 230 µsv/h with SBM-20@ 1cm , 6.4 cm x 4.7 cm x 3.5 cm , boxed , 155g, ...","6":false,"7":65.0,"8":"USD"}}}},{"1":{"1":"https://thumbs.dreamstime.com/b/uranium-ore-9727818.jpg","3":800,"4":800},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmOQiJLTEC8IUbP-J8cA1Lk04kgZBnfCs03hjz8XxFcUnULkVg","3":200,"4":200},"3":{"1":"Dreamstime.com","2":"https://www.dreamstime.com/royalty-free-stock-photos-uranium-ore-image9727818","3":"Uranium ore stock photo. Image of radium, rays, environmental ...","4":"Download Uranium ore stock photo. Image of radium, rays, environmental -  9727818","10":"PpKDilVVidtdAh"},"5":{"1":"BCPoeqSVHwLqKpu"}},{"1":{"1":"https://www.sciencephoto.com/image/78646/530wm","3":530,"4":364},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSzl6fxehVSwPTJDfNmmKM0e9GD6mKJ2TFvP-fhFUmE9G0xiGkJsA","3":200,"4":137},"3":{"1":"Science Photo Library","2":"https://www.sciencephoto.com/media/78646/view/-autunite-a-uranium-ore-","3":"Autunite, a Uranium Ore' - Stock Image C001/4244 - Science ...","4":"'Autunite, a Uranium Ore'","10":"EDmfQyiLaYeGiq"},"5":{"1":"cLFDrRSdxooTyfX"}},{"1":{"1":"https://i.kinja-img.com/gawker-media/image/upload/s--GJZHACFy--/c_scale,f_auto,fl_progressive,q_80,w_800/1444652809032333604.jpg","3":800,"4":450},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS7eJp8DHn5uknUUaBQM8FX1ZbrP6BFLG5Hcxgl1QN5k7nFf2sm","3":200,"4":112},"3":{"1":"io9 - Gizmodo","2":"https://io9.gizmodo.com/what-happens-when-you-put-acid-on-uranium-ore-find-out-1732733166","3":"What Happens When You Put Acid on Uranium Ore? Find Out!","4":"","10":"ivMcBfdMUrSuTq"},"5":{"1":"NmYiuMoOFDeXWFB"}},{"1":{"1":"https://quatr.us/wp-content/uploads/2017/06/uranium.jpg","3":250,"4":268},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcShlD81v12IPVrUwlby7X_gfp_lPKFcgjAlbZ8sfTjRoBp9p6ekCg","3":187,"4":200},"3":{"1":"Quatr.us","2":"https://quatr.us/chemistry/uranium-atoms-elements-chemistry.htm","3":"What is uranium? Atoms, elements, chemistry | Quatr.us Study ...","4":"A piece of uranium ore","10":"LggyIdLfTHPoUE"},"5":{"1":"PDBjsuOVuDrmnRH"}},{"1":{"1":"http://www.radioactivethings.com/_Media/full-size-2.jpeg","3":1537,"4":1920},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ03YLxtAgZB6haLu1HOHiWCqtFIxFH-y27WA-xJN9B0Fi7B3X5","3":160,"4":200},"3":{"2":"http://www.radioactivethings.com/","3":"RadioactiveThings.com","4":"As Major General Nichols of the Manhattan project put it: \"Our best source,  the Shinkolobwe mine, ...","10":"kcddveXePECqkk"},"5":{"1":"FsqBhrfUURQcKHI"}},{"1":{"1":"http://talknuclear.ca/wp-content/uploads/2014/08/radiation-from-bananas.jpg","3":599,"4":641},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSlhqhU7yHlFVuI5YFnhnudkAOouIrYTetWsAPQ8OSwYbz8AFr1","3":187,"4":200},"3":{"1":"TalkNuclear","2":"http://talknuclear.ca/2014/08/just-how-radioactive-is-uranium-ore/","3":"Just How Radioactive is Uranium Ore? | TalkNuclear","4":"radiation from bananas","10":"JeIVstWCOVqrYN"},"5":{"1":"JbifUMcnhPfcvxU"}},{"1":{"1":"https://previews.123rf.com/images/merial1/merial11205/merial1120500076/13672876-uranium-ore-uraninite-from-pribram-czech-republic.jpg","3":1300,"4":1038},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQCyxlmproQBZz6Vw97Xu0No5l7N8s0BTt_HrvRm7HI4jL7fNmb","3":200,"4":160},"3":{"1":"123RF.com","2":"https://www.123rf.com/photo_13672876_uranium-ore-uraninite-from-pribram-czech-republic.html","3":"Uranium Ore (uraninite) From Pribram, Czech Republic Stock ...","4":"Uranium ore (uraninite) from Pribram, Czech republic Stock Photo - 13672876","10":"jGfydBHejDNsUv"},"5":{"1":"spMNHbdmpmkhhPI"}},{"1":{"1":"https://images.enca.com/encadrupal/styles/600_383/s3/WEB_PHOTO_KAROO_RYSTKUIL_05032016.jpg","3":600,"4":383},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9dFVWftqcZ4hgMriqLFGNOhcDPD9iiwWipfkxyFbYTgyG5N7u","3":200,"4":127},"3":{"1":"eNCA","2":"http://www.enca.com/south-africa/uranium-mining-karoo-south-africas-new-gold","3":"Uranium mining in the Karoo South Africa's new gold?","4":"The entrance to the Cameron shaft, an old uranium trial mine 40km from  Beaufort West.","10":"TuhPBLPjSHnFFr"},"5":{"1":"TfETPSaOJhXBxDu"}},{"1":{"1":"http://www.world-nuclear.org/getattachment/Nuclear-Basics/How-is-uranium-ore-made-into-nuclear-fuel/yellowcake-(Cameco).jpg.aspx?","3":709,"4":915},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfCvtqHk8x539fQ_UFrgd5sKuAEKtHeVifrIrAnyqoLFfyijEKUQ","3":155,"4":200},"3":{"1":"World Nuclear Association","2":"http://www.world-nuclear.org/nuclear-basics/how-is-uranium-ore-made-into-nuclear-fuel.aspx","3":"How uranium ore is made into nuclear fuel - World Nuclear ...","4":"yellowcake-(Cameco).jpg","10":"EgOqgwGpPvWtNo"},"5":{"1":"deoFQVqsXRHBxDx"}},{"1":{"1":"https://media.gettyimages.com/photos/kilogram-of-uranium-ore-gives-merely-37-grams-of-yellow-cake-in-mine-picture-id844444270","3":1024,"4":683},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8FrUCgyfEdOSaMt3n3diQQK_CofwQcGS85fOnJg07RMeM71ec","3":200,"4":133},"3":{"1":"Getty Images","2":"https://www.gettyimages.com/detail/news-photo/kilogram-of-uranium-ore-gives-merely-37-grams-of-yellow-news-photo/844444270","3":"Inside Indias secure uranium processing facility Pictures ...","4":"JADUGODA, JHARKAHND, INDIA - SEPTEMBER 03: A 100 kilogram of uranium ore  gives","10":"CBBCmdctDTjUYS"},"5":{"1":"wcimccDXRxrPPYo"}},{"1":{"1":"https://ae01.alicdn.com/kf/HTB1X_yaLpXXXXbtXXXXq6xXFXXXS/Domestic-rare-autunite-fluorescent-Mica-natural-uranium-ore-original-stone-mineral-specimens-H1024.jpg_640x640.jpg","3":639,"4":640},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvFFjVksCk-mht4Bki6CGFuGeLDrzAn8RxL84tEauRoyuuuS1t","3":199,"4":200},"3":{"1":"AliExpress.com","2":"https://www.aliexpress.com/item/Domestic-rare-autunite-fluorescent-Mica-natural-uranium-ore-original-stone-mineral-specimens-H1024/32594437365.html","3":"Domestic rare autunite fluorescent Mica natural uranium ore ...","4":"Domestic rare autunite fluorescent Mica natural uranium ore original stone  mineral specimens H1024","10":"LGJotHvCumpisG"},"5":{"1":"PHYmmwVGNgxyWXQ"},"7":{"1":{"10":{"3":"Domestic rare autunite fluorescent Mica natural uranium ore original stone  mineral specimens H1024 on Aliexpress.com | Alibaba Group","6":false,"7":856.7999877929688,"8":"USD"}}}},{"1":{"1":"https://vignette.wikia.nocookie.net/thetekkit/images/8/88/Uranium_Ore.png/revision/latest?cb=20121011054131","3":256,"4":256},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhqcbjnHtAH4CZb_F1qk6JU_T4vSYyE8PnZduQj3Wc8nBV1OUw","3":200,"4":200},"3":{"1":"The Tekkit Classic Wiki - Fandom","2":"http://tekkitclassic.wikia.com/wiki/Uranium_Ore","3":"Uranium Ore | The Tekkit Classic Wiki | FANDOM powered by Wikia","4":"Uranium Ore","10":"fbHJlnOSnoAlXg"},"5":{"1":"LKECMxeYlJQYQvx"}},{"1":{"1":"http://pcbheaven.com/opendir/images/thumbs/od_1281_4_1340220138.png","3":500,"4":334},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTfyHMiuy7oPGB1SaoPbdwAvG0u32Vc-nBmQX64YIqQvoP3vByYUg","3":200,"4":133},"3":{"1":"Hesed.info","2":"http://hesed.info/blog/yellowcake-uranium-ore.abp","3":"Yellowcake Uranium Ore","4":"","10":"bEvuSpOOWAaPlY"},"5":{"1":"CSCohElwJwuXNPc"}},{"1":{"1":"https://keanchancom.files.wordpress.com/2016/06/uranium-ore.jpg","3":1024,"4":768},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZjU6qvNMW95223xEEvNN3XYlPx8R12QV3dbjh1-5vTpHLkDmCHw","3":200,"4":149},"3":{"1":"Hitman Game","2":"http://the.hitmangame.info/jpg/fluorescent-uranium-ore.php","3":"Fluorescent Uranium Ore - Hitman Game","4":"Fluorescent Uranium Ore","10":"KwgdiKaesnYMur"},"5":{"1":"XirjwbBuBUlIjJX"}},{"1":{"1":"https://i.ytimg.com/vi/vNbV4whWHsQ/maxresdefault.jpg","3":1280,"4":720},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqKbVcx3LMW1wZ8aghfTW9JKDQPYXD0LqNrjPLPPwLE09ABedF9A","3":200,"4":112},"3":{"1":"YouTube","2":"https://www.youtube.com/watch?v=vNbV4whWHsQ","3":"Uranium Ores -The Better - YouTube","4":"Uranium Ores -The Better","10":"cmwKHdELShqVIL"},"5":{"1":"uLnJXqtjVcLJSBT"},"7":{"1":{"11":{"1":"Uranium Ores -The Better","2":"If you collect rocks, its a good idea to part the specimens in 3 groups:  good - better - best These specimens in the video are in my group \"better\"  The \"best...","3":"12:25","4":"737","5":"1484438400000","6":"weirdmeister inc.","7":"18","8":"15"}}}},{"1":{"1":"https://www.mining-technology.com/wp-content/uploads/sites/8/2017/10/1-image-Australia.jpg","3":600,"4":400},"2":{"1":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDRzupy-lorOlAP0d-CEOFeHwOPm3o79KIYPpZ_yeQZvwIt3uB","3":200,"4":133},"3":{"1":"Mining Technology","2":"https://www.mining-technology.com/features/featureradioactive-riches-the-five-biggest-uranium-rich-countries-4274059/","3":"Radioactive riches – the five countries with the biggest ...","4":"Australia's Ranger mine is the world's third biggest uranium producing mine.","10":"YfKTBasdlWQntu"},"5":{"1":"DtGOUiEJFvqvbnO"}}],"2":3}
\ No newline at end of file
diff --git a/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart b/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
index 070edd0..5742568 100644
--- a/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
+++ b/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 import 'dart:isolate';
 import 'dart:math';
 
@@ -11,10 +10,10 @@
 
 import 'package:compiler/src/dart2js.dart' as dart2js_main;
 
-class SpawnLatencyAndMemory {
-  SpawnLatencyAndMemory(this.name);
+class SpawnLatency {
+  SpawnLatency(this.name);
 
-  Future<ResultMessageLatencyAndMemory> run() async {
+  Future<ResultMessageLatency> run() async {
     final completerResult = Completer();
     final receivePort = ReceivePort()..listen(completerResult.complete);
     final Completer<DateTime> isolateExitedCompleter = Completer<DateTime>();
@@ -24,14 +23,12 @@
       });
     final DateTime beforeSpawn = DateTime.now();
     await Isolate.spawn(
-        isolateCompiler,
-        StartMessageLatencyAndMemory(
-            receivePort.sendPort, beforeSpawn, ProcessInfo.currentRss),
+        isolateCompiler, StartMessageLatency(receivePort.sendPort, beforeSpawn),
         onExit: onExitReceivePort.sendPort,
         onError: onExitReceivePort.sendPort);
     final DateTime afterSpawn = DateTime.now();
 
-    final ResultMessageLatencyAndMemory result = await completerResult.future;
+    final ResultMessageLatency result = await completerResult.future;
     receivePort.close();
     final DateTime isolateExited = await isolateExitedCompleter.future;
     result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
@@ -42,8 +39,7 @@
     return result;
   }
 
-  Future<AggregatedResultMessageLatencyAndMemory> measureFor(
-      int minimumMillis) async {
+  Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
     final minimumMicros = minimumMillis * 1000;
     final watch = Stopwatch()..start();
     final Metric toAfterIsolateSpawnUs = LatencyMetric("${name}ToAfterSpawn");
@@ -51,26 +47,24 @@
     final Metric toFinishRunningCodeUs =
         LatencyMetric("${name}ToFinishRunning");
     final Metric toExitUs = LatencyMetric("${name}ToExit");
-    final Metric deltaRss = MemoryMetric("${name}Delta");
     while (watch.elapsedMicroseconds < minimumMicros) {
-      final ResultMessageLatencyAndMemory result = await run();
+      final ResultMessageLatency result = await run();
       toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
       toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
       toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
       toExitUs.add(result.timeToExitUs);
-      deltaRss.add(result.deltaRss);
     }
-    return AggregatedResultMessageLatencyAndMemory(toAfterIsolateSpawnUs,
-        toStartRunningCodeUs, toFinishRunningCodeUs, toExitUs, deltaRss);
+    return AggregatedResultMessageLatency(toAfterIsolateSpawnUs,
+        toStartRunningCodeUs, toFinishRunningCodeUs, toExitUs);
   }
 
-  Future<AggregatedResultMessageLatencyAndMemory> measure() async {
+  Future<AggregatedResultMessageLatency> measure() async {
     await measureFor(500); // warm-up
     return measureFor(4000); // actual measurement
   }
 
   Future<void> report() async {
-    final AggregatedResultMessageLatencyAndMemory result = await measure();
+    final AggregatedResultMessageLatency result = await measure();
     print(result);
   }
 
@@ -106,60 +100,50 @@
 }
 
 class LatencyMetric extends Metric {
-  LatencyMetric(String name) : super(prefix: "${name}(Latency", suffix: " us.");
+  LatencyMetric(String name) : super(prefix: "$name(Latency", suffix: " us.");
 }
 
-class MemoryMetric extends Metric {
-  MemoryMetric(String name) : super(prefix: "${name}Rss(MemoryUse", suffix: "");
-
-  toString() => "$prefix): ${_average()}$suffix\n";
-}
-
-class StartMessageLatencyAndMemory {
-  StartMessageLatencyAndMemory(this.sendPort, this.spawned, this.rss);
+class StartMessageLatency {
+  StartMessageLatency(this.sendPort, this.spawned);
 
   final SendPort sendPort;
   final DateTime spawned;
-  final int rss;
 }
 
-class ResultMessageLatencyAndMemory {
-  ResultMessageLatencyAndMemory(
+class ResultMessageLatency {
+  ResultMessageLatency(
       {this.timeToStartRunningCodeUs,
       this.timeToFinishRunningCodeUs,
-      this.deltaRss});
+      this.deltaHeap});
 
   final int timeToStartRunningCodeUs;
   final int timeToFinishRunningCodeUs;
-  final int deltaRss;
+  final int deltaHeap;
 
   int timeToIsolateSpawnUs;
   int timeToExitUs;
 }
 
-class AggregatedResultMessageLatencyAndMemory {
-  AggregatedResultMessageLatencyAndMemory(
+class AggregatedResultMessageLatency {
+  AggregatedResultMessageLatency(
     this.toAfterIsolateSpawnUs,
     this.toStartRunningCodeUs,
     this.toFinishRunningCodeUs,
     this.toExitUs,
-    this.deltaRss,
   );
 
   String toString() => """$toAfterIsolateSpawnUs
 $toStartRunningCodeUs
 $toFinishRunningCodeUs
-$toExitUs
-$deltaRss""";
+$toExitUs""";
 
   final Metric toAfterIsolateSpawnUs;
   final Metric toStartRunningCodeUs;
   final Metric toFinishRunningCodeUs;
   final Metric toExitUs;
-  final Metric deltaRss;
 }
 
-Future<void> isolateCompiler(StartMessageLatencyAndMemory start) async {
+Future<void> isolateCompiler(StartMessageLatency start) async {
   final DateTime timeRunningCodeUs = DateTime.now();
   await runZoned(
       () => dart2js_main.internalMain(<String>[
@@ -169,14 +153,13 @@
       zoneSpecification: ZoneSpecification(
           print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
   final DateTime timeFinishRunningCodeUs = DateTime.now();
-  start.sendPort.send(ResultMessageLatencyAndMemory(
+  start.sendPort.send(ResultMessageLatency(
       timeToStartRunningCodeUs:
           timeRunningCodeUs.difference(start.spawned).inMicroseconds,
       timeToFinishRunningCodeUs:
-          timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds,
-      deltaRss: ProcessInfo.currentRss - start.rss));
+          timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds));
 }
 
 Future<void> main() async {
-  await SpawnLatencyAndMemory("IsolateSpawn.Dart2JS").report();
+  await SpawnLatency("IsolateSpawn.Dart2JS").report();
 }
diff --git a/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart b/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
new file mode 100644
index 0000000..7969877
--- /dev/null
+++ b/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:compiler/src/dart2js.dart' as dart2js_main;
+import 'package:vm_service/vm_service.dart' as vm_service;
+import 'package:vm_service/vm_service_io.dart' as vm_service_io;
+
+class Result {
+  const Result(
+      this.rssOnStart, this.rssOnEnd, this.heapOnStart, this.heapOnEnd);
+
+  final int rssOnStart;
+  final int rssOnEnd;
+  final int heapOnStart;
+  final int heapOnEnd;
+}
+
+class StartMessage {
+  const StartMessage(this.wsUri, this.groupRefId, this.sendPort);
+
+  final String wsUri;
+  final String groupRefId;
+  final SendPort sendPort;
+}
+
+class SpawnMemory {
+  SpawnMemory(this.name, this.wsUri, this.groupRefId);
+
+  Future<void> report() async {
+    const numberOfRuns = 3;
+
+    int sumDeltaRssOnStart = 0;
+    int sumDeltaRssOnEnd = 0;
+    int sumDeltaHeapOnStart = 0;
+    int sumDeltaHeapOnEnd = 0;
+    for (int i = 0; i < numberOfRuns; i++) {
+      final receivePort = ReceivePort();
+      final beforeRss = ProcessInfo.currentRss;
+      final beforeHeap = await currentHeapUsage(wsUri, groupRefId);
+
+      final startMessage =
+          StartMessage(wsUri, groupRefId, receivePort.sendPort);
+      await Isolate.spawn(isolateCompiler, startMessage);
+
+      final Result result = await receivePort.first;
+      sumDeltaRssOnStart += result.rssOnStart - beforeRss;
+      sumDeltaRssOnEnd += result.rssOnEnd - beforeRss;
+      sumDeltaHeapOnStart += result.heapOnStart - beforeHeap;
+      sumDeltaHeapOnEnd += result.heapOnEnd - beforeHeap;
+    }
+    print(
+        "${name}RssOnStart(MemoryUse): ${sumDeltaRssOnStart ~/ numberOfRuns}");
+    print("${name}RssOnEnd(MemoryUse): ${sumDeltaRssOnEnd ~/ numberOfRuns}");
+    print(
+        "${name}HeapOnStart(MemoryUse): ${sumDeltaHeapOnStart ~/ numberOfRuns}");
+    print("${name}HeapOnEnd(MemoryUse): ${sumDeltaHeapOnEnd ~/ numberOfRuns}");
+  }
+
+  final String name;
+  final String wsUri;
+  final String groupRefId;
+  RawReceivePort receivePort;
+}
+
+Future<void> isolateCompiler(StartMessage startMessage) async {
+  final rssOnStart = ProcessInfo.currentRss;
+  final heapOnStart =
+      await currentHeapUsage(startMessage.wsUri, startMessage.groupRefId);
+  await runZoned(
+      () => dart2js_main.internalMain(<String>[
+            "benchmarks/IsolateSpawnMemory/dart/helloworld.dart",
+            '--libraries-spec=sdk/lib/libraries.json'
+          ]),
+      zoneSpecification: ZoneSpecification(
+          print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
+  startMessage.sendPort.send(Result(
+      rssOnStart,
+      ProcessInfo.currentRss,
+      heapOnStart,
+      await currentHeapUsage(startMessage.wsUri, startMessage.groupRefId)));
+  ReceivePort(); // prevent isolate from exiting to ensure Rss monotonically grows
+}
+
+Future<int> currentHeapUsage(String wsUri, String groupRefId) async {
+  final vm_service.VmService vmService =
+      await vm_service_io.vmServiceConnectUri(wsUri);
+  final vm_service.MemoryUsage usage =
+      await vmService.getIsolateGroupMemoryUsage(groupRefId);
+  vmService.dispose();
+  return usage.heapUsage + usage.externalUsage;
+}
+
+Future<void> main() async {
+  final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  final Uri observatoryUri = info.serverUri;
+  final String wsUri =
+      'ws://${observatoryUri.authority}${observatoryUri.path}ws';
+  final vm_service.VmService vmService =
+      await vm_service_io.vmServiceConnectUri(wsUri);
+  final String mainGroupRefId = await getMainGroupRefId(vmService);
+  vmService.dispose();
+
+  await SpawnMemory("IsolateSpawnMemory.Dart2JSDelta", wsUri, mainGroupRefId)
+      .report();
+}
+
+Future<String> getMainGroupRefId(vm_service.VmService vmService) async {
+  final vm = await vmService.getVM();
+  for (vm_service.IsolateGroupRef groupRef in vm.isolateGroups) {
+    final vm_service.IsolateGroup group =
+        await vmService.getIsolateGroup(groupRef.id);
+    for (vm_service.IsolateRef isolateRef in group.isolates) {
+      final isolateOrSentinel = await vmService.getIsolate(isolateRef.id);
+      if (isolateOrSentinel is vm_service.Isolate) {
+        final vm_service.Isolate isolate = isolateOrSentinel;
+        if (isolate.name == 'main') {
+          return groupRef.id;
+        }
+      }
+    }
+  }
+  throw "Could not find main isolate";
+}
diff --git a/benchmarks/IsolateSpawnMemory/dart/helloworld.dart b/benchmarks/IsolateSpawnMemory/dart/helloworld.dart
new file mode 100644
index 0000000..8977e0f
--- /dev/null
+++ b/benchmarks/IsolateSpawnMemory/dart/helloworld.dart
@@ -0,0 +1,3 @@
+main() {
+  print('Hello, world!');
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index ee4e500..3e51f3c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -1336,7 +1336,8 @@
     if (newType == null || typeOperations.isSameType(newType, previousType)) {
       return new ExpressionInfo<Variable, Type>(this, this, this);
     }
-    assert(typeOperations.isSubtypeOf(newType, previousType));
+    assert(typeOperations.isSubtypeOf(newType, previousType),
+        "Expected $newType to be a subtype of $previousType.");
     return _finishTypeTest(typeOperations, variable, info, newType);
   }
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index cc75d4f..29f32d1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1680,6 +1680,35 @@
 const Template<
     Message Function(
         String
+            name)> templateDeferredExtensionImport = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Extension '#name' cannot be imported through a deferred import.""",
+    tipTemplate: r"""Try adding the `hide #name` to the import.""",
+    withArguments: _withArgumentsDeferredExtensionImport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeDeferredExtensionImport =
+    const Code<Message Function(String name)>(
+  "DeferredExtensionImport",
+  templateDeferredExtensionImport,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDeferredExtensionImport(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDeferredExtensionImport,
+      message:
+          """Extension '${name}' cannot be imported through a deferred import.""",
+      tip: """Try adding the `hide ${name}` to the import.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
             name)> templateDeferredPrefixDuplicated = const Template<
         Message Function(String name)>(
     messageTemplate:
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index e838b3c..cb751ab 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -2421,7 +2421,7 @@
     }
 
     Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == name);
+    assert(token.next == name || token.next.isEof);
 
     IdentifierContext context = kind == DeclarationKind.TopLevel
         ? IdentifierContext.topLevelVariableDeclaration
@@ -3402,6 +3402,9 @@
         // TODO(danrubel): report invalid constructor name
         // Currently multiple listeners report this error, but that logic should
         // be removed and the error reported here instead.
+        if (isOperator) {
+          isConstructor = false;
+        }
       }
       if (getOrSet != null) {
         // Recovery
@@ -4343,6 +4346,10 @@
         token = parseSend(next, IdentifierContext.expressionContinuation);
         next = token.next;
         listener.endBinaryExpression(period);
+      } else if (optional('!', next)) {
+        listener.handleNonNullAssertExpression(next);
+        token = next;
+        next = token.next;
       }
       TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
       if (typeArg != noTypeParamOrArg) {
diff --git a/pkg/front_end/lib/src/fasta/quote.dart b/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
similarity index 89%
rename from pkg/front_end/lib/src/fasta/quote.dart
rename to pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
index 71ace2d..6303272 100644
--- a/pkg/front_end/lib/src/fasta/quote.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
@@ -30,9 +30,7 @@
         hexDigitValue,
         isHexDigit;
 
-import 'problems.dart' show unhandled;
-
-import 'fasta_codes.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/messages/codes.dart' as codes;
 
 enum Quote {
   Single,
@@ -54,7 +52,7 @@
   if (first.startsWith('r"')) return Quote.RawDouble;
   if (first.startsWith("'")) return Quote.Single;
   if (first.startsWith("r'")) return Quote.RawSingle;
-  return unhandled(first, "analyzeQuote", -1, null);
+  return throw UnsupportedError("'$first' in analyzeQuote");
 }
 
 // Note: based on [StringValidator.quotingFromString]
@@ -104,7 +102,7 @@
     case Quote.RawMultiLineDouble:
       return lengthOfOptionalWhitespacePrefix(first, 4);
   }
-  return unhandled("$quote", "firstQuoteLength", -1, null);
+  return throw UnsupportedError("'$quote' in  firstQuoteLength");
 }
 
 int lastQuoteLength(Quote quote) {
@@ -121,7 +119,7 @@
     case Quote.RawMultiLineDouble:
       return 3;
   }
-  return unhandled("$quote", "lastQuoteLength", -1, null);
+  return throw UnsupportedError("'$quote' in lastQuoteLength");
 }
 
 String unescapeFirstStringPart(String first, Quote quote, Object location,
@@ -174,7 +172,7 @@
           ? string
           : unescapeCodeUnits(string.codeUnits, true, location, listener);
   }
-  return unhandled("$quote", "unescape", -1, null);
+  return throw new UnsupportedError("'$quote' in unescape");
 }
 
 // Note: based on
@@ -195,7 +193,7 @@
     } else if (!isRaw && code == $BACKSLASH) {
       if (codeUnits.length == ++i) {
         listener.handleUnescapeError(
-            fasta.messageInvalidUnicodeEscape, location, i, 1);
+            codes.messageInvalidUnicodeEscape, location, i, 1);
         return new String.fromCharCodes(codeUnits);
       }
       code = codeUnits[i];
@@ -224,7 +222,7 @@
         // Expect exactly 2 hex digits.
         int begin = i;
         if (codeUnits.length <= i + 2) {
-          listener.handleUnescapeError(fasta.messageInvalidHexEscape, location,
+          listener.handleUnescapeError(codes.messageInvalidHexEscape, location,
               begin, codeUnits.length + 1 - begin);
           return new String.fromCharCodes(codeUnits);
         }
@@ -233,7 +231,7 @@
           int digit = codeUnits[++i];
           if (!isHexDigit(digit)) {
             listener.handleUnescapeError(
-                fasta.messageInvalidHexEscape, location, begin, i + 1 - begin);
+                codes.messageInvalidHexEscape, location, begin, i + 1 - begin);
             return new String.fromCharCodes(codeUnits);
           }
           code = (code << 4) + hexDigitValue(digit);
@@ -241,7 +239,7 @@
       } else if (code == $u) {
         int begin = i;
         if (codeUnits.length == i + 1) {
-          listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+          listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
               location, begin, codeUnits.length + 1 - begin);
           return new String.fromCharCodes(codeUnits);
         }
@@ -249,21 +247,21 @@
         if (code == $OPEN_CURLY_BRACKET) {
           // Expect 1-6 hex digits followed by '}'.
           if (codeUnits.length == ++i) {
-            listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+            listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
                 location, begin, i + 1 - begin);
             return new String.fromCharCodes(codeUnits);
           }
           code = 0;
           for (int j = 0; j < 7; j++) {
             if (codeUnits.length == ++i) {
-              listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+              listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
                   location, begin, i + 1 - begin);
               return new String.fromCharCodes(codeUnits);
             }
             int digit = codeUnits[i];
             if (j != 0 && digit == $CLOSE_CURLY_BRACKET) break;
             if (!isHexDigit(digit)) {
-              listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+              listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
                   location, begin, i + 2 - begin);
               return new String.fromCharCodes(codeUnits);
             }
@@ -272,7 +270,7 @@
         } else {
           // Expect exactly 4 hex digits.
           if (codeUnits.length <= i + 4) {
-            listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+            listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
                 location, begin, codeUnits.length + 1 - begin);
             return new String.fromCharCodes(codeUnits);
           }
@@ -280,7 +278,7 @@
           for (int j = 0; j < 4; j++) {
             int digit = codeUnits[++i];
             if (!isHexDigit(digit)) {
-              listener.handleUnescapeError(fasta.messageInvalidUnicodeEscape,
+              listener.handleUnescapeError(codes.messageInvalidUnicodeEscape,
                   location, begin, i + 1 - begin);
               return new String.fromCharCodes(codeUnits);
             }
@@ -289,7 +287,7 @@
         }
         if (code > 0x10FFFF) {
           listener.handleUnescapeError(
-              fasta.messageInvalidCodePoint, location, begin, i + 1 - begin);
+              codes.messageInvalidCodePoint, location, begin, i + 1 - begin);
           return new String.fromCharCodes(codeUnits);
         }
       } else {
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
similarity index 86%
rename from pkg/front_end/lib/src/fasta/source/stack_listener.dart
rename to pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
index 89a515c..a9b9681 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
@@ -2,34 +2,27 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library fasta.stack_listener;
+library _fe_analyzer_shared.stack_listener;
 
-import 'package:_fe_analyzer_shared/src/parser/parser.dart'
-    show Listener, MemberKind, Parser, lengthOfSpan;
-
-import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
-    show IdentifierContext;
-
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
-import 'package:kernel/ast.dart'
-    show AsyncMarker, Expression, FunctionNode, TreeNode;
-
-import '../fasta_codes.dart'
+import '../messages/codes.dart'
     show
         Code,
         LocatedMessage,
         Message,
         codeCatchSyntaxExtraParameters,
         codeNativeClauseShouldBeAnnotation,
-        templateInternalProblemStackNotEmpty;
+        templateInternalProblemStackNotEmpty,
+        templateInternalProblemUnhandled;
 
-import '../problems.dart'
-    show internalProblem, unhandled, unimplemented, unsupported;
+import '../scanner/scanner.dart' show Token;
 
-import '../quote.dart' show unescapeString;
+import 'identifier_context.dart' show IdentifierContext;
 
-import 'value_kinds.dart';
+import 'parser.dart' show Listener, MemberKind, lengthOfSpan;
+
+import 'quote.dart' show unescapeString;
+
+import 'value_kind.dart';
 
 enum NullValue {
   Arguments,
@@ -80,6 +73,9 @@
 abstract class StackListener extends Listener {
   final Stack stack = new Stack();
 
+  /// Used to report an internal error encountered in the stack listener.
+  dynamic internalProblem(Message message, int charOffset, Uri uri);
+
   /// Checks that [value] matches the expected [kind].
   ///
   /// Use this in assert statements like
@@ -214,37 +210,13 @@
     }
   }
 
-  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
-  // and ast_builder.dart.
-  void finishFunction(
-      covariant formals, AsyncMarker asyncModifier, covariant body) {
-    return unsupported("finishFunction", -1, uri);
-  }
-
-  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
-  // and ast_builder.dart.
-  dynamic finishFields() {
-    return unsupported("finishFields", -1, uri);
-  }
-
-  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
-  // and ast_builder.dart.
-  List<Expression> finishMetadata(TreeNode parent) {
-    return unsupported("finishMetadata", -1, uri);
-  }
-
-  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
-  // and ast_builder.dart.
-  void exitLocalScope() => unsupported("exitLocalScope", -1, uri);
-
-  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart.
-  dynamic parseSingleExpression(
-      Parser parser, Token token, FunctionNode parameters) {
-    return unsupported("finishSingleExpression", -1, uri);
-  }
-
   void push(Object node) {
-    if (node == null) unhandled("null", "push", -1, uri);
+    if (node == null) {
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments("null", "push"),
+          -1,
+          uri);
+    }
     stack.push(node);
   }
 
@@ -282,7 +254,10 @@
   @override
   void logEvent(String name) {
     printEvent(name);
-    unhandled(name, "$runtimeType", -1, uri);
+    internalProblem(
+        templateInternalProblemUnhandled.withArguments(name, "$runtimeType"),
+        -1,
+        uri);
   }
 
   @override
@@ -453,7 +428,11 @@
       Token token = pop();
       push(unescapeString(token.lexeme, token, this));
     } else {
-      unimplemented("string interpolation", endToken.charOffset, uri);
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments(
+              "string interpolation", "endLiteralString"),
+          endToken.charOffset,
+          uri);
     }
   }
 
@@ -490,8 +469,8 @@
       Message message, Token startToken, Token endToken) {
     debugEvent("Error: ${message.message}");
     if (isIgnoredError(message.code, startToken)) return;
-    addProblem(message, offsetForToken(startToken),
-        lengthOfSpan(startToken, endToken));
+    addProblem(
+        message, startToken.charOffset, lengthOfSpan(startToken, endToken));
   }
 
   bool isIgnoredError(Code<dynamic> code, Token token) {
@@ -627,9 +606,3 @@
 
   String toString() => "ParserRecovery(@$charOffset)";
 }
-
-/// A null-aware alternative to `token.offset`.  If [token] is `null`, returns
-/// `TreeNode.noOffset`.
-int offsetForToken(Token token) {
-  return token == null ? TreeNode.noOffset : token.offset;
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart
new file mode 100644
index 0000000..92549f0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'stack_listener.dart' show NullValue;
+
+/// [ValueKind] is used in [StackListener.checkState] to document and check the
+/// expected values of the stack.
+///
+/// Add new value kinds as needed for documenting and checking the various stack
+/// listener implementations.
+abstract class ValueKind {
+  const ValueKind();
+
+  /// Checks the [value] an returns `true` if the value is of the expected kind.
+  bool check(Object value);
+}
+
+/// A [ValueKind] for a particular type [T], optionally with a recognized
+/// [NullValue].
+class SingleValueKind<T> implements ValueKind {
+  final NullValue nullValue;
+
+  const SingleValueKind([this.nullValue]);
+
+  @override
+  bool check(Object value) {
+    if (nullValue != null && value == nullValue) {
+      return true;
+    }
+    return value is T;
+  }
+
+  String toString() {
+    if (nullValue != null) {
+      return '$T or $nullValue';
+    }
+    return '$T';
+  }
+}
+
+/// A [ValueKind] for the union of a list of [ValueKind]s.
+class UnionValueKind implements ValueKind {
+  final List<ValueKind> kinds;
+
+  const UnionValueKind(this.kinds);
+
+  @override
+  bool check(Object value) {
+    for (ValueKind kind in kinds) {
+      if (kind.check(value)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    String or = '';
+    for (ValueKind kind in kinds) {
+      sb.write(or);
+      sb.write(kind);
+      or = ' or ';
+    }
+    return sb.toString();
+  }
+}
+
+/// Helper method for creating a list of [ValueKind]s of the given length
+/// [count].
+List<ValueKind> repeatedKinds(ValueKind kind, int count) {
+  return new List.generate(count, (_) => kind);
+}
+
+/// Helper method for creating a union of a list of [ValueKind]s.
+ValueKind unionOfKinds(List<ValueKind> kinds) {
+  return new UnionValueKind(kinds);
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
index 39006b3..d76d643 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
@@ -41,6 +41,6 @@
 questionEq_rhs_not_guaranteed_to_execute() {
   late int v;
   int? i;
-  i ??= (v = 0);
-  /*unassigned*/ v;
+  /*cfe.unassigned*/ i ??= (v = 0);
+  /*analyzer.unassigned*/ v;
 }
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart
new file mode 100644
index 0000000..9a0cf4f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*cfe.library: nnbd=true*/
+
+import 'opt_out.dart';
+
+/*class: Class1:Class1,LegacyClass1,Object*/
+class Class1 extends LegacyClass1 {}
+
+/*class: Class2:Class2<T*>,LegacyClass2<T>,Object*/
+class Class2<T> extends LegacyClass2<T> {}
+
+/*class: Class3a:Class3a<T*>,GenericInterface<T*>,LegacyClass3<T>,Object*/
+class Class3a<T> extends LegacyClass3<T> {}
+
+/*class: Class3b:Class3b<T*>,GenericInterface<T*>,LegacyClass3<T>,Object*/
+class
+// TODO(johnniwinther): Avoid this error.
+/*error: AmbiguousSupertypes*/
+    Class3b<T> extends LegacyClass3<T> implements GenericInterface<T> {}
+
+/*class: Class4a:Class4a,GenericInterface<num*>,LegacyClass4,Object*/
+class Class4a extends LegacyClass4 {}
+
+/*class: Class4b:Class4b,GenericInterface<num!>,Object*/
+class Class4b implements GenericInterface<num> {}
+
+/*class: Class4c:Class4c,GenericInterface<num?>,Object*/
+class Class4c implements GenericInterface<num?> {}
+
+/*class: Class4d:Class4d,GenericInterface<num*>,LegacyClass4,Object*/
+class
+// TODO(johnniwinther): Avoid this error.
+/*error: AmbiguousSupertypes*/
+    Class4d extends LegacyClass4 implements GenericInterface<num> {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/opt_out.dart
new file mode 100644
index 0000000..d35f46c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/opt_out.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*library: nnbd=false*/
+
+/*class: GenericInterface:GenericInterface<T*>,Object*/
+abstract class GenericInterface<T> {}
+
+/*class: LegacyClass1:LegacyClass1,Object*/
+class LegacyClass1 {}
+
+/*class: LegacyClass2:LegacyClass2<T*>,Object*/
+class LegacyClass2<T> {}
+
+/*class: LegacyClass3:GenericInterface<T*>,LegacyClass3<T*>,Object*/
+class LegacyClass3<T> implements GenericInterface<T> {}
+
+/*class: LegacyClass4:GenericInterface<num*>,LegacyClass4,Object*/
+class LegacyClass4 implements GenericInterface<num> {}
diff --git a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
index 85f6a7f..a5d402b 100644
--- a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
@@ -51,37 +51,25 @@
     }
     // int timeStamp = int.parse(fields[0], onError: (_) => -1);
     String opCode = fields[1];
-    if (opCode == InstrumentationService.TAG_NOTIFICATION) {
+    if (opCode == InstrumentationLogAdapter.TAG_NOTIFICATION) {
       return convertNotification(decodeJson(line, fields[2]));
     } else if (opCode == 'Read') {
       // 1434096943209:Read:/some/file/path:1434095535000:<file content>
       //String filePath = fields[2];
       readBuffer = new StringBuffer(fields.length > 4 ? fields[4] : '');
       return null;
-    } else if (opCode == InstrumentationService.TAG_REQUEST) {
+    } else if (opCode == InstrumentationLogAdapter.TAG_REQUEST) {
       return convertRequest(decodeJson(line, fields[2]));
-    } else if (opCode == InstrumentationService.TAG_RESPONSE) {
+    } else if (opCode == InstrumentationLogAdapter.TAG_RESPONSE) {
       // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}}
       return convertResponse(decodeJson(line, fields[2]));
-    } else if (opCode == InstrumentationService.TAG_ANALYSIS_TASK) {
-      // 1434096943208:Task:/Users/
-      return null;
-    } else if (opCode == InstrumentationService.TAG_LOG_ENTRY) {
+    } else if (opCode == InstrumentationLogAdapter.TAG_LOG_ENTRY) {
       // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}}
       return null;
-    } else if (opCode == InstrumentationService.TAG_PERFORMANCE) {
-      //1434096960092:Perf:analysis_full:16884:context_id=0
-      return null;
-    } else if (opCode == InstrumentationService.TAG_SUBPROCESS_START) {
-      // 1434096938634:SPStart:0:/Users/da
-      return null;
-    } else if (opCode == InstrumentationService.TAG_SUBPROCESS_RESULT) {
-      // 1434096939068:SPResult:0:0:"{\"packages\"::{\"rpi_lidar\"::\"/Users
-      return null;
-    } else if (opCode == InstrumentationService.TAG_VERSION) {
+    } else if (opCode == InstrumentationLogAdapter.TAG_VERSION) {
       // 1434096937358:Ver:1421765742287333878467:org.dartlang.dartplugin
       return null;
-    } else if (opCode == InstrumentationService.TAG_WATCH_EVENT) {
+    } else if (opCode == InstrumentationLogAdapter.TAG_WATCH_EVENT) {
       // 1434097460414:Watch:/some/file/path
       return null;
     }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index f00140f..1c6f2de 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -41,6 +41,7 @@
 import 'package:analysis_server/src/search/search_domain.dart';
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/error_notifier.dart';
 import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/services/flutter/widget_descriptions.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
@@ -354,11 +355,9 @@
         channel.sendResponse(new Response.unknownRequest(request));
       });
     }, onError: (exception, stackTrace) {
-      sendServerErrorNotification(
-          'Failed to handle request: ${request.toJson()}',
-          exception,
-          stackTrace,
-          fatal: true);
+      AnalysisEngine.instance.instrumentationService.logException(
+          FatalException('Failed to handle request: ${request.toJson()}',
+              exception, stackTrace));
     });
   }
 
@@ -410,6 +409,7 @@
   }
 
   /// Sends a `server.error` notification.
+  @override
   void sendServerErrorNotification(
     String message,
     dynamic exception,
@@ -432,17 +432,6 @@
         new ServerErrorParams(fatal, message, buffer.toString())
             .toNotification());
 
-    // send to crash reporting
-    if (options.crashReportSender != null) {
-      options.crashReportSender
-          .sendReport(exception,
-              stackTrace: stackTrace is StackTrace ? stackTrace : null)
-          .catchError((_) {
-        // Catch and ignore any exceptions when reporting exceptions (network
-        // errors or other).
-      });
-    }
-
     // remember the last few exceptions
     if (exception is CaughtException) {
       stackTrace ??= exception.stackTrace;
@@ -895,8 +884,9 @@
       if (result.contextKey != null) {
         message += ' context: ${result.contextKey}';
       }
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.wrapInMessage(message, result.exception));
+          new SilentException.wrapInMessage(message, result.exception));
     });
     analysisServer.driverMap[folder] = analysisDriver;
     return analysisDriver;
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index d631698..018a4fd 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -282,7 +282,10 @@
 
     return driver
         .getResult(path, sendCachedToStream: sendCachedToStream)
-        .catchError((_) => null);
+        .catchError((e, st) {
+      AnalysisEngine.instance.instrumentationService.logException(e, st);
+      return null;
+    });
   }
 
   /// Notify the declarations tracker that the file with the given [path] was
@@ -292,6 +295,14 @@
     analysisDriverScheduler.notify(null);
   }
 
+  /// Sends an error notification to the user.
+  void sendServerErrorNotification(
+    String message,
+    dynamic exception,
+    /*StackTrace*/ stackTrace, {
+    bool fatal = false,
+  });
+
   void updateContextInDeclarationsTracker(nd.AnalysisDriver driver) {
     declarationsTracker?.discardContext(driver.analysisContext);
     declarationsTracker?.addContext(driver.analysisContext);
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 5d3c4f4..258e444 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -19,7 +19,9 @@
 import 'package:analysis_server/src/services/completion/token_details/token_detail_builder.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
@@ -254,10 +256,11 @@
       }
       return null;
     }, onError: (exception, stackTrace) {
-      server.sendServerErrorNotification(
-          'Failed to handle completion domain request: ${request.toJson()}',
-          exception,
-          stackTrace);
+      AnalysisEngine.instance.instrumentationService.logException(
+          CaughtException.withMessage(
+              'Failed to handle completion domain request: ${request.toJson()}',
+              exception,
+              stackTrace));
     });
   }
 
diff --git a/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
index ee06820..9a7d05f 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 
 void addDartOccurrences(OccurrencesCollector collector, CompilationUnit unit) {
   _DartUnitOccurrencesComputerVisitor visitor =
@@ -55,9 +54,6 @@
     if (element is PropertyAccessorElement) {
       element = (element as PropertyAccessorElement).variable;
     }
-    if (element is Member) {
-      element = (element as Member).baseElement;
-    }
-    return element;
+    return element?.declaration;
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 1cfb93f..267a8c9 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -13,6 +13,7 @@
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/preview/http_preview_server.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -46,8 +47,14 @@
   /// as if in a directory structure rooted at [includedRoot].
   final String includedRoot;
 
+  /// The absolute path of the directory to which preview pages are to be
+  /// written, or `null` if no preview pages should be written to disk.
   final String outputDir;
 
+  /// The port on which preview pages should be served, or `null` if no preview
+  /// server should be started.
+  final int port;
+
   InstrumentationListener instrumentationListener;
 
   NullabilityMigration migration;
@@ -57,12 +64,12 @@
   /// If this occurs, then don't update any code.
   bool _packageIsNNBD = true;
 
-  NonNullableFix(this.listener, this.outputDir,
+  NonNullableFix(this.listener, this.outputDir, this.port,
       {List<String> included = const []})
       : this.includedRoot =
             _getIncludedRoot(included, listener.server.resourceProvider) {
     instrumentationListener =
-        outputDir == null ? null : InstrumentationListener();
+        outputDir == null && port == null ? null : InstrumentationListener();
     migration = new NullabilityMigration(
         new NullabilityMigrationAdapter(listener),
         permissive: _usePermissiveMode,
@@ -75,7 +82,7 @@
   @override
   Future<void> finish() async {
     migration.finish();
-    if (outputDir != null) {
+    if (outputDir != null && port == null) {
       OverlayResourceProvider provider = listener.server.resourceProvider;
       Folder outputFolder = provider.getFolder(outputDir);
       if (!outputFolder.exists) {
@@ -83,6 +90,29 @@
       }
       await _generateOutput(provider, outputFolder);
     }
+    if (port != null) {
+      OverlayResourceProvider provider = listener.server.resourceProvider;
+      InfoBuilder infoBuilder =
+          InfoBuilder(instrumentationListener.data, listener);
+      Set<UnitInfo> unitInfos = await infoBuilder.explainMigration();
+      var pathContext = provider.pathContext;
+      MigrationInfo migrationInfo = MigrationInfo(
+          unitInfos, infoBuilder.unitMap, pathContext, includedRoot);
+      PathMapper pathMapper = PathMapper(provider, outputDir, includedRoot);
+      // TODO(brianwilkerson) Print a URL that users can paste into the browser.
+      //  The code below is close to right, but computes the wrong path. We
+      //  don't have enough information to pick a single library inside `lib`,
+      //  so we might want to consider alternatives, such as a directory listing
+      //  page or an empty file page.
+//      print(Uri(
+//          scheme: 'http',
+//          host: 'localhost',
+//          port: 10501,
+//          path: pathMapper.map('$includedRoot/lib/logging.dart')));
+      // TODO(brianwilkerson) Capture the server so that it can be closed
+      //  cleanly.
+      HttpPreviewServer(migrationInfo, pathMapper).serveHttp(port);
+    }
   }
 
   /// If the package contains an analysis_options.yaml file, then update the
@@ -224,8 +254,8 @@
         InfoBuilder(instrumentationListener.data, listener);
     Set<UnitInfo> unitInfos = await infoBuilder.explainMigration();
     var pathContext = provider.pathContext;
-    MigrationInfo migrationInfo =
-        MigrationInfo(unitInfos, pathContext, includedRoot);
+    MigrationInfo migrationInfo = MigrationInfo(
+        unitInfos, infoBuilder.unitMap, pathContext, includedRoot);
     PathMapper pathMapper = PathMapper(provider, folder.path, includedRoot);
 
     /// Produce output for the compilation unit represented by the [unitInfo].
@@ -267,7 +297,8 @@
 
   static void task(DartFixRegistrar registrar, DartFixListener listener,
       EditDartfixParams params) {
-    registrar.registerCodeTask(new NonNullableFix(listener, params.outputDir,
+    registrar.registerCodeTask(new NonNullableFix(
+        listener, params.outputDir, params.port,
         included: params.included));
   }
 
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index a13283c..c5592b5 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -43,12 +43,16 @@
   /// The listener used to gather the changes to be applied.
   final DartFixListener listener;
 
+  /// A flag indicating whether types that were not changed (because they should
+  /// be non-nullable) should be explained.
+  final bool explainNonNullableTypes;
+
   /// A map from the path of a compilation unit to the information about that
   /// unit.
   final Map<String, UnitInfo> unitMap = {};
 
   /// Initialize a newly created builder.
-  InfoBuilder(this.info, this.listener);
+  InfoBuilder(this.info, this.listener, {this.explainNonNullableTypes = false});
 
   /// The analysis server used to get information about libraries.
   AnalysisServer get server => listener.server;
@@ -178,18 +182,6 @@
     return capitalize("$nullableValue is assigned");
   }
 
-  /// Return detail text for a fix built from an edge with [node] as a
-  /// destination.
-  String _buildDescriptionForDestination(AstNode node) {
-    // Other found types:
-    // - ConstructorDeclaration
-    if (node.parent is FormalParameterList) {
-      return "A nullable value can't be passed as an argument";
-    } else {
-      return "A nullable value can't be used here";
-    }
-  }
-
   /// Return a description of the given [origin].
   String _buildDescriptionForOrigin(EdgeOriginInfo origin) {
     String description = _baseDescriptionForOrigin(origin);
@@ -253,8 +245,7 @@
         NullabilityNodeInfo destination = reason.destinationNode;
         var nodeInfo = info.nodeInfoFor(destination);
         if (nodeInfo != null) {
-          details.add(RegionDetail(
-              _buildDescriptionForDestination(nodeInfo.astNode),
+          details.add(RegionDetail(nodeInfo.descriptionForDestination,
               _targetForNode(nodeInfo.filePath, nodeInfo.astNode)));
         } else {
           details.add(RegionDetail('node with no info ($destination)', null));
@@ -330,6 +321,34 @@
     return details;
   }
 
+  /// Explain the type annotations that were not changed because they were
+  /// determined to be non-nullable.
+  void _explainNonNullableTypes(SourceInformation sourceInfo,
+      List<RegionInfo> regions, OffsetMapper mapper) {
+    Iterable<MapEntry<TypeAnnotation, NullabilityNodeInfo>> nonNullableTypes =
+        sourceInfo.explicitTypeNullability.entries
+            .where((entry) => !entry.value.isNullable);
+    for (MapEntry<TypeAnnotation, NullabilityNodeInfo> nonNullableType
+        in nonNullableTypes) {
+      Iterable<EdgeInfo> upstreamTriggeredEdgeInfos = info.edgeOrigin.keys
+          .where((e) =>
+              e.sourceNode == nonNullableType.value &&
+              e.isUpstreamTriggered &&
+              !e.destinationNode.isNullable);
+      if (upstreamTriggeredEdgeInfos.isNotEmpty) {
+        List<RegionDetail> details =
+            _computeUpstreamTriggeredDetails(upstreamTriggeredEdgeInfos);
+        TypeAnnotation node = nonNullableType.key;
+        regions.add(RegionInfo(
+            mapper.map(node.offset),
+            node.length,
+            "This type is not changed; it is determined to be non-nullable",
+            details,
+            RegionType.nonNullableType));
+      }
+    }
+  }
+
   /// Return the migration information for the unit associated with the
   /// [result].
   UnitInfo _explainUnit(SourceInformation sourceInfo, ResolvedUnitResult result,
@@ -366,27 +385,8 @@
             details, RegionType.fix));
       }
     }
-    Iterable<MapEntry<TypeAnnotation, NullabilityNodeInfo>> nonNullableTypes =
-        sourceInfo.explicitTypeNullability.entries
-            .where((entry) => !entry.value.isNullable);
-    for (MapEntry<TypeAnnotation, NullabilityNodeInfo> nonNullableType
-        in nonNullableTypes) {
-      Iterable<EdgeInfo> upstreamTriggeredEdgeInfos = info.edgeOrigin.keys
-          .where((e) =>
-              e.sourceNode == nonNullableType.value &&
-              e.isUpstreamTriggered &&
-              !e.destinationNode.isNullable);
-      if (upstreamTriggeredEdgeInfos.isNotEmpty) {
-        List<RegionDetail> details =
-            _computeUpstreamTriggeredDetails(upstreamTriggeredEdgeInfos);
-        TypeAnnotation node = nonNullableType.key;
-        regions.add(RegionInfo(
-            mapper.map(node.offset),
-            node.length,
-            "This type is not changed; it is determined to be non-nullable",
-            details,
-            RegionType.nonNullableType));
-      }
+    if (explainNonNullableTypes) {
+      _explainNonNullableTypes(sourceInfo, regions, mapper);
     }
     regions.sort((first, second) => first.offset.compareTo(second.offset));
     unitInfo.offsetMapper = mapper;
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
index 60e7d38..6510931 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
@@ -13,10 +13,6 @@
   /// The node used for type sources that are always `null`.
   NullabilityNodeInfo always;
 
-  /// A map from elements outside of the code being migrated, to the nullability
-  /// nodes associated with the type of the element.
-  final Map<Element, DecoratedTypeInfo> externalDecoratedType = {};
-
   /// A map from the graph edges between nullability nodes, to information about
   /// the edge that was created and why it was created.
   final Map<EdgeInfo, EdgeOriginInfo> edgeOrigin = {};
@@ -24,6 +20,9 @@
   /// The node used for type sources that are never `null`.
   NullabilityNodeInfo never;
 
+  /// A map associating [NodeInformation] with [NullabilityNodeInfo] objects.
+  Map<NullabilityNodeInfo, NodeInformation> nodeInformation = {};
+
   /// A list of the steps in the propagation of nullability information through
   /// the nullability graph, to report details of the step that was performed
   /// and why it was performed.
@@ -37,40 +36,7 @@
 
   /// Return information about the given [node].
   NodeInformation nodeInfoFor(NullabilityNodeInfo node) {
-    for (MapEntry<Source, SourceInformation> sourceEntry
-        in sourceInformation.entries) {
-      SourceInformation sourceInfo = sourceEntry.value;
-      for (MapEntry<AstNode, DecoratedTypeInfo> entry
-          in sourceInfo.implicitReturnType.entries) {
-        if (entry.value.node == node) {
-          return NodeInformation(
-              sourceEntry.key.fullName, entry.key, entry.value);
-        }
-      }
-      for (MapEntry<AstNode, DecoratedTypeInfo> entry
-          in sourceInfo.implicitType.entries) {
-        if (entry.value.node == node) {
-          return NodeInformation(
-              sourceEntry.key.fullName, entry.key, entry.value);
-        }
-      }
-      for (MapEntry<AstNode, List<DecoratedTypeInfo>> entry
-          in sourceInfo.implicitTypeArguments.entries) {
-        for (var type in entry.value) {
-          if (type.node == node) {
-            return NodeInformation(sourceEntry.key.fullName, entry.key, type);
-          }
-        }
-      }
-    }
-    // The loop below doesn't help because we still don't have access to an AST
-    // node.
-//    for (MapEntry<Element, DecoratedTypeInfo> entry in externalDecoratedType.entries) {
-//      if (entry.value.node == node) {
-//        return NodeInformation(null, null, entry.value);
-//      }
-//    }
-    return null;
+    return nodeInformation[node];
   }
 
   /// Return the type annotation associated with the [node] or `null` if the
@@ -95,9 +61,20 @@
 
   final AstNode astNode;
 
-  final DecoratedTypeInfo decoratedType;
+  final Element element;
 
-  NodeInformation(this.filePath, this.astNode, this.decoratedType);
+  final String descriptionPrefix;
+
+  NodeInformation(
+      this.filePath, this.astNode, this.element, this.descriptionPrefix);
+
+  /// Return detail text for a fix built from an edge with this node as a
+  /// destination.
+  String get descriptionForDestination {
+    // TODO(paulberry): describe AST nodes
+    var description = (element ?? '???').toString();
+    return "A nullable value can't be used as $descriptionPrefix$description";
+  }
 }
 
 /// The instrumentation information gathered from the migration engine that is
@@ -105,43 +82,13 @@
 class SourceInformation {
   /// A map from the type annotations found in the source code, to the
   /// nullability nodes that are associated with that type.
+  ///
+  /// TODO(paulberry): we should probably get rid of this data structure.
   final Map<TypeAnnotation, NullabilityNodeInfo> explicitTypeNullability = {};
 
   /// A map from the fixes that were decided on to the reasons for the fix.
   final Map<SingleNullabilityFix, List<FixReasonInfo>> fixes = {};
 
-  /// A map from AST nodes that have an implicit return type to the nullability
-  /// node associated with the implicit return type of the AST node. The node
-  /// can be an
-  /// - executable declaration,
-  /// - function-typed formal parameter declaration,
-  /// - function type alias declaration,
-  /// - generic function type, or
-  /// - function expression.
-  final Map<AstNode, DecoratedTypeInfo> implicitReturnType = {};
-
-  /// A map from AST nodes that have an implicit type to the nullability node
-  /// associated with the implicit type of the AST node. The node can be a
-  /// - formal parameter,
-  /// - declared identifier, or
-  /// - variable in a variable declaration list.
-  final Map<AstNode, DecoratedTypeInfo> implicitType = {};
-
-  /// Called whenever the migration engine encounters an AST node with implicit
-  /// type arguments, to report the nullability nodes associated with the
-  /// implicit type arguments of the AST node.
-  ///
-  /// A map from AST nodes that have implicit type arguments to the nullability
-  /// nodes associated with the implicit type arguments of the AST node. The
-  /// node can be a
-  /// - constructor redirection,
-  /// - function expression invocation,
-  /// - method invocation,
-  /// - instance creation expression,
-  /// - list/map/set literal, or
-  /// - type annotation.
-  final Map<AstNode, List<DecoratedTypeInfo>> implicitTypeArguments = {};
-
   /// Initialize a newly created holder of instrumentation information that is
   /// specific to a single source.
   SourceInformation();
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
index b51c370..0f977ed 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
@@ -21,12 +22,21 @@
   @override
   void explicitTypeNullability(
       Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node) {
+    data.nodeInformation[node] = NodeInformation(
+        _filePathForSource(source), typeAnnotation, null, 'the explicit type ');
     _sourceInfo(source).explicitTypeNullability[typeAnnotation] = node;
   }
 
   @override
   void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
-    data.externalDecoratedType[element] = decoratedType;
+    _storeNodeInformation(decoratedType, element.source, null, element, '');
+  }
+
+  @override
+  void externalDecoratedTypeParameterBound(
+      TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType) {
+    _storeNodeInformation(
+        decoratedType, typeParameter.source, null, typeParameter, 'bound of ');
   }
 
   @override
@@ -49,19 +59,25 @@
   @override
   void implicitReturnType(
       Source source, AstNode node, DecoratedTypeInfo decoratedReturnType) {
-    _sourceInfo(source).implicitReturnType[node] = decoratedReturnType;
+    _storeNodeInformation(
+        decoratedReturnType, source, node, null, 'return type of ');
   }
 
   @override
   void implicitType(
       Source source, AstNode node, DecoratedTypeInfo decoratedType) {
-    _sourceInfo(source).implicitType[node] = decoratedType;
+    _storeNodeInformation(decoratedType, source, node, null, 'type of ');
   }
 
   @override
   void implicitTypeArguments(
       Source source, AstNode node, Iterable<DecoratedTypeInfo> types) {
-    _sourceInfo(source).implicitTypeArguments[node] = types.toList();
+    int i = 0;
+    for (var type in types) {
+      _storeNodeInformation(
+          type, source, node, null, 'implicit type argument $i of ');
+      i++;
+    }
   }
 
   @override
@@ -69,8 +85,42 @@
     data.propagationSteps.add(info);
   }
 
+  String _filePathForSource(Source source) {
+    return source.fullName;
+  }
+
   /// Return the source information associated with the given [source], creating
   /// it if there has been no previous information for that source.
   SourceInformation _sourceInfo(Source source) =>
       data.sourceInformation.putIfAbsent(source, () => SourceInformation());
+
+  void _storeNodeInformation(DecoratedTypeInfo decoratedType, Source source,
+      AstNode astNode, Element element, String description) {
+    // Make sure source info exists for the given source.
+    _sourceInfo(source);
+    data.nodeInformation[decoratedType.node] = NodeInformation(
+        _filePathForSource(source), astNode, element, description);
+    var dartType = decoratedType.type;
+    if (dartType is InterfaceType) {
+      for (int i = 0; i < dartType.typeArguments.length; i++) {
+        _storeNodeInformation(decoratedType.typeArgument(i), source, astNode,
+            element, 'type argument $i of $description');
+      }
+    } else if (dartType is FunctionType) {
+      _storeNodeInformation(decoratedType.returnType, source, astNode, element,
+          'return type of $description');
+      int i = 0;
+      for (var parameter in dartType.parameters) {
+        if (parameter.isNamed) {
+          var name = parameter.name;
+          _storeNodeInformation(decoratedType.namedParameter(name), source,
+              astNode, element, 'named parameter $name of $description');
+        } else {
+          _storeNodeInformation(decoratedType.positionalParameter(i), source,
+              astNode, element, 'positional parameter $i of $description');
+          i++;
+        }
+      }
+    }
+  }
 }
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index f539107..cb4ae0c 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -185,7 +185,7 @@
   </head>
   <body>
     <h1>Non-nullable fix instrumentation report</h1>
-    <p><em>Well-written introduction to this report.</em></p>
+    <p>Migrated files:</p>
     <div class="navigation">
       {{# links }}
         {{# isLink }}<a href="{{ href }}">{{ name }}</a>{{/ isLink }}
@@ -265,34 +265,42 @@
     // Compute insertions for navigation targets.
     //
     for (NavigationTarget region in unitInfo.targets) {
-      int openOffset = mapper.map(region.offset);
-      String openInsertion = openInsertions[openOffset] ?? '';
-      openInsertion = '<a id="o${region.offset}">$openInsertion';
-      openInsertions[openOffset] = openInsertion;
+      int regionLength = region.length;
+      if (regionLength > 0) {
+        int openOffset = mapper.map(region.offset);
+        String openInsertion = openInsertions[openOffset] ?? '';
+        openInsertion = '<a id="o${region.offset}">$openInsertion';
+        openInsertions[openOffset] = openInsertion;
 
-      int closeOffset = openOffset + region.length;
-      String closeInsertion = closeInsertions[closeOffset] ?? '';
-      closeInsertion = '$closeInsertion</a>';
-      closeInsertions[closeOffset] = closeInsertion;
+        int closeOffset = openOffset + regionLength;
+        String closeInsertion = closeInsertions[closeOffset] ?? '';
+        closeInsertion = '$closeInsertion</a>';
+        closeInsertions[closeOffset] = closeInsertion;
+      }
     }
     //
     // Compute insertions for navigation sources, but skip the sources that
     // point at themselves.
     //
     for (NavigationSource region in unitInfo.sources ?? <NavigationSource>[]) {
-      int openOffset = mapper.map(region.offset);
-      NavigationTarget target = region.target;
-      if (target.filePath != unitInfo.path || region.offset != target.offset) {
-        String openInsertion = openInsertions[openOffset] ?? '';
-        String htmlPath = pathContext.relative(pathMapper.map(target.filePath),
-            from: unitDir);
-        openInsertion = '<a href="$htmlPath#o${target.offset}">$openInsertion';
-        openInsertions[openOffset] = openInsertion;
+      int regionLength = region.length;
+      if (regionLength > 0) {
+        int openOffset = mapper.map(region.offset);
+        NavigationTarget target = region.target;
+        if (target.filePath != unitInfo.path ||
+            region.offset != target.offset) {
+          String openInsertion = openInsertions[openOffset] ?? '';
+          String htmlPath = pathContext
+              .relative(pathMapper.map(target.filePath), from: unitDir);
+          openInsertion =
+              '<a href="$htmlPath#o${target.offset}">$openInsertion';
+          openInsertions[openOffset] = openInsertion;
 
-        int closeOffset = openOffset + region.length;
-        String closeInsertion = closeInsertions[closeOffset] ?? '';
-        closeInsertion = '$closeInsertion</a>';
-        closeInsertions[closeOffset] = closeInsertion;
+          int closeOffset = openOffset + regionLength;
+          String closeInsertion = closeInsertions[closeOffset] ?? '';
+          closeInsertion = '$closeInsertion</a>';
+          closeInsertions[closeOffset] = closeInsertion;
+        }
       }
     }
     //
@@ -415,13 +423,17 @@
   /// The information about the compilation units that are are migrated.
   final Set<UnitInfo> units;
 
+  /// A map from file paths to the unit infos created for those files. The units
+  /// in this map is a strict superset of the [units] that were migrated.
+  final Map<String, UnitInfo> unitMap;
+
   /// The resource provider's path context.
   final path.Context pathContext;
 
   /// The filesystem root used to create relative paths for each unit.
   final String includedRoot;
 
-  MigrationInfo(this.units, this.pathContext, this.includedRoot);
+  MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot);
 
   /// The path to the highlight.js script, relative to [unitInfo].
   String highlightJsPath(UnitInfo unitInfo) {
diff --git a/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart b/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
new file mode 100644
index 0000000..84df2c7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:meta/meta.dart';
+import 'package:path/src/context.dart';
+
+/// The page that is displayed when a preview of a valid Dart file is requested.
+class DartFilePage extends PreviewPage {
+  /// The information about the file being previewed.
+  final UnitInfo unitInfo;
+
+  /// Initialize a newly created Dart file page within the given [site]. The
+  /// [unitInfo] provides the information needed to render the page.
+  DartFilePage(PreviewSite site, this.unitInfo)
+      // TODO(brianwilkerson) The path needs to be converted to use '/' if that
+      //  isn't already done as part of building the unitInfo.
+      : super(site, unitInfo.path.substring(1));
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw UnsupportedError('generateBody');
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    InstrumentationRenderer renderer = InstrumentationRenderer(
+        unitInfo,
+        PreviewMigrationInfo(site.migrationInfo),
+        PreviewPathMapper(site.pathMapper));
+    buf.write(renderer.render());
+  }
+}
+
+/// A wrapper around a migration info that returns the expected paths to the
+/// JS and CSS files.
+class PreviewMigrationInfo implements MigrationInfo {
+  /// The wrapped migration info.
+  final MigrationInfo wrappedInfo;
+
+  /// Initialize a newly created migration info to wrap the [wrappedInfo].
+  PreviewMigrationInfo(this.wrappedInfo);
+
+  @override
+  String get includedRoot => wrappedInfo.includedRoot;
+
+  @override
+  Context get pathContext => wrappedInfo.pathContext;
+
+  @override
+  Map<String, UnitInfo> get unitMap => wrappedInfo.unitMap;
+
+  @override
+  Set<UnitInfo> get units => wrappedInfo.units;
+
+  @override
+  String highlightJsPath(UnitInfo unitInfo) {
+    return PreviewSite.highlightJSPagePath;
+  }
+
+  @override
+  String highlightStylePath(UnitInfo unitInfo) {
+    return PreviewSite.highlightCssPagePath;
+  }
+
+  @override
+  List<Map<String, Object>> unitLinks(UnitInfo thisUnit) {
+    return [
+      for (var unit in units)
+        {
+          'name': _computeName(unit),
+          'isLink': unit != thisUnit,
+          if (unit != thisUnit) 'href': _pathTo(target: unit, source: thisUnit)
+        }
+    ];
+  }
+
+  /// Return the path to [unit] from [includedRoot], to be used as a display
+  /// name for a library.
+  String _computeName(UnitInfo unit) =>
+      pathContext.relative(unit.path, from: includedRoot);
+
+  /// The path to [target], relative to [from].
+  String _pathTo({@required UnitInfo target, @required UnitInfo source}) {
+    String targetPath = target.path;
+    String sourceDir = pathContext.dirname(source.path);
+    return pathContext.relative(targetPath, from: sourceDir);
+  }
+}
+
+/// A wrapper around a path mapper that converts file paths to URIs.
+class PreviewPathMapper implements PathMapper {
+  /// The wrapped path mapper.
+  final PathMapper wrappedMapper;
+
+  /// Initialize a newly created path mapper to wrap the [wrappedMapper].
+  PreviewPathMapper(this.wrappedMapper);
+
+  @override
+  int get nextIndex => wrappedMapper.nextIndex;
+
+  @override
+  void set nextIndex(int nextIndex) {
+    wrappedMapper.nextIndex = nextIndex;
+  }
+
+  @override
+  String get outputFolder => throw UnsupportedError('outputFolder');
+
+  @override
+  String get packageRoot => wrappedMapper.packageRoot;
+
+  @override
+  Map<String, String> get pathMap => throw UnsupportedError('pathMap');
+
+  @override
+  ResourceProvider get provider => wrappedMapper.provider;
+
+  @override
+  void set provider(ResourceProvider provider) {
+    wrappedMapper.provider = provider;
+  }
+
+  @override
+  String map(String path) {
+    return Uri.file(path).path;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/exception_page.dart b/pkg/analysis_server/lib/src/edit/preview/exception_page.dart
new file mode 100644
index 0000000..ae7c30b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/exception_page.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// The page that is displayed when an exception is encountered in the process
+/// of composing the content of a different page.
+class ExceptionPage extends PreviewPage {
+  /// The message from the exception that caused this page to be displayed.
+  final String message;
+
+  /// The stack trace of the exception that caused this page to be displayed.
+  final StackTrace stackTrace;
+
+  /// Initialize a newly created exception page within the given [site]. The
+  /// [message] and [stackTrace] are used to describe the exception to the user.
+  ExceptionPage(PreviewSite site, String path, this.message, this.stackTrace)
+      : super(site, path.substring(1));
+
+  @override
+  void generateBody(Map<String, String> params) {
+    buf.write('''
+<h1>500 Exception in preview</h1>
+<p>
+We're sorry, but you've encountered a bug in the preview tool. Please visit
+<a href='https://github.com/dart-lang/sdk/issues/new'></a> to report the issue
+and include the stack trace below.
+</p>
+<h2>$message</h2>
+<p style="white-space: pre">
+${htmlEscape.convert(stackTrace.toString())}
+</p>
+''');
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart b/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart
new file mode 100644
index 0000000..a3fe02a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server/src/edit/nnbd_migration/highlight_css.dart';
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// The page that contains the CSS used to style the semantic highlighting
+/// within a Dart file.
+class HighlightCssPage extends PreviewPage {
+  /// The decoded content of the page. Use [pageContent] to access this field so
+  /// that it is initialized on first read.
+  static String _pageContent;
+
+  /// Initialize a newly created CSS page within the given [site].
+  HighlightCssPage(PreviewSite site)
+      : super(site, PreviewSite.highlightCssPagePath.substring(1));
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.write(pageContent());
+  }
+
+  /// Return the content of the page, decoding it if it hasn't been decoded
+  /// before.
+  String pageContent() {
+    return _pageContent ??= decodeHighlightCss();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart b/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart
new file mode 100644
index 0000000..c324158
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server/src/edit/nnbd_migration/highlight_js.dart';
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// The page that contains the JavaScript used to apply semantic highlighting
+/// styles to a Dart file.
+class HighlightJSPage extends PreviewPage {
+  /// The decoded content of the page. Use [pageContent] to access this field so
+  /// that it is initialized on first read.
+  static String _pageContent;
+
+  /// Initialize a newly created JS page within the given [site].
+  HighlightJSPage(PreviewSite site)
+      : super(site, PreviewSite.highlightJSPagePath.substring(1));
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.write(pageContent());
+  }
+
+  /// Return the content of the page, decoding it if it hasn't been decoded
+  /// before.
+  String pageContent() {
+    return _pageContent ??= decodeHighlightJs();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart b/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
new file mode 100644
index 0000000..1344678
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// Instances of the class [AbstractGetHandler] handle GET requests.
+abstract class AbstractGetHandler {
+  /// Handle a GET request received by the HTTP server.
+  Future<void> handleGetRequest(HttpRequest request);
+}
+
+/// Instances of the class [HttpPreviewServer] implement a simple HTTP server
+/// that serves up dartfix preview pages.
+class HttpPreviewServer {
+  /// The information about the migration that will be used to serve up pages.
+  final MigrationInfo migrationInfo;
+
+  /// The path mapper used to map paths from the unit infos to the paths being
+  /// served.
+  final PathMapper pathMapper;
+
+  /// An object that can handle GET requests.
+  AbstractGetHandler getHandler;
+
+  /// Future that is completed with the HTTP server once it is running.
+  Future<HttpServer> _serverFuture;
+
+  /// Initialize a newly created HTTP server.
+  HttpPreviewServer(this.migrationInfo, this.pathMapper);
+
+  /// Return the port this server is bound to.
+  Future<int> get boundPort async {
+    return (await _serverFuture)?.port;
+  }
+
+  void close() {
+    _serverFuture?.then((HttpServer server) {
+      server.close();
+    });
+  }
+
+  /// Begin serving HTTP requests over the given port.
+  Future<int> serveHttp([int initialPort]) async {
+    if (_serverFuture != null) {
+      return boundPort;
+    }
+
+    try {
+      _serverFuture =
+          HttpServer.bind(InternetAddress.loopbackIPv4, initialPort ?? 0);
+
+      HttpServer server = await _serverFuture;
+      _handleServer(server);
+      return server.port;
+    } catch (ignore) {
+      // If we can't bind to the specified port, don't remember the broken
+      // server.
+      _serverFuture = null;
+
+      return null;
+    }
+  }
+
+  /// Handle a GET request received by the HTTP server.
+  Future<void> _handleGetRequest(HttpRequest request) async {
+    getHandler ??= new PreviewSite(migrationInfo, pathMapper);
+    await getHandler.handleGetRequest(request);
+  }
+
+  /// Attach a listener to a newly created HTTP server.
+  void _handleServer(HttpServer httpServer) {
+    httpServer.listen((HttpRequest request) async {
+      List<String> updateValues = request.headers[HttpHeaders.upgradeHeader];
+      if (request.method == 'GET') {
+        await _handleGetRequest(request);
+      } else if (updateValues != null &&
+          updateValues.indexOf('websocket') >= 0) {
+        // We do not support serving analysis server communications over
+        // WebSocket connections.
+        HttpResponse response = request.response;
+        response.statusCode = HttpStatus.notFound;
+        response.headers.contentType = ContentType.text;
+        response.write(
+            'WebSocket connections not supported (${request.uri.path}).');
+        response.close();
+      } else {
+        _returnUnknownRequest(request);
+      }
+    });
+  }
+
+  /// Return an error in response to an unrecognized request received by the HTTP
+  /// server.
+  void _returnUnknownRequest(HttpRequest request) {
+    HttpResponse response = request.response;
+    response.statusCode = HttpStatus.notFound;
+    response.headers.contentType = ContentType.text;
+    response.write('Not found');
+    response.close();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/not_found_page.dart b/pkg/analysis_server/lib/src/edit/preview/not_found_page.dart
new file mode 100644
index 0000000..bafcbe7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/not_found_page.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// The page that is displayed when an invalid URL is requested.
+class NotFoundPage extends PreviewPage {
+  /// Initialize a newly created file-not-found page within the given [site].
+  /// The [id] is the portion of the path to the page that follows the initial
+  /// slash ('/').
+  NotFoundPage(PreviewSite site, String id) : super(site, id);
+
+  @override
+  void generateBody(Map<String, String> params) {
+    buf.write('''
+<h1>404 Not found</h1>
+<p>
+'$path' not found.
+</p>
+''');
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/preview_page.dart b/pkg/analysis_server/lib/src/edit/preview/preview_page.dart
new file mode 100644
index 0000000..f927d6a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/preview_page.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+import 'package:analysis_server/src/status/pages.dart';
+
+/// A page displayed on the preview site.
+abstract class PreviewPage extends Page {
+  /// The site containing the page.
+  final PreviewSite site;
+
+  /// Initialize a newly created page within the given [site]. The [id] is the
+  /// portion of the path to the page that follows the initial slash ('/').
+  PreviewPage(this.site, String id) : super(id, '', description: '');
+
+  /// Generate the content of the body tag.
+  void generateBody(Map<String, String> params);
+
+  /// Generate the content of the head tag.
+  void generateHead() {
+    buf.writeln('<meta charset="utf-8">');
+    buf.writeln('<meta name="viewport" content="width=device-width, '
+        'initial-scale=1.0">');
+    buf.writeln('<title>${site.title}</title>');
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.writeln('<!DOCTYPE html><html lang="en">');
+    buf.writeln('<head>');
+    buf.writeln('</head>');
+    generateHead();
+    buf.writeln('<body>');
+    generateBody(params);
+    buf.writeln('</body>');
+    buf.writeln('</html>');
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
new file mode 100644
index 0000000..2f3f778
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
@@ -0,0 +1,131 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/preview/dart_file_page.dart';
+import 'package:analysis_server/src/edit/preview/exception_page.dart';
+import 'package:analysis_server/src/edit/preview/highlight_css_page.dart';
+import 'package:analysis_server/src/edit/preview/highlight_js_page.dart';
+import 'package:analysis_server/src/edit/preview/http_preview_server.dart';
+import 'package:analysis_server/src/edit/preview/not_found_page.dart';
+import 'package:analysis_server/src/status/pages.dart';
+import 'package:analyzer/file_system/file_system.dart';
+
+/// The site used to serve pages for the preview tool.
+class PreviewSite extends Site implements AbstractGetHandler {
+  /// The path of the CSS page used to style the semantic highlighting within a
+  /// Dart file.
+  static const highlightCssPagePath = '/css/androidstudio.css';
+
+  /// The path of the JS page used to associate highlighting within a Dart file.
+  static const highlightJSPagePath = '/js/highlight.pack.js';
+
+  /// The information about the migration that will be used to serve up pages.
+  final MigrationInfo migrationInfo;
+
+  /// The path mapper used to map paths from the unit infos to the paths being
+  /// served.
+  final PathMapper pathMapper;
+
+  /// A table mapping the paths of files to the information about the
+  /// compilation units at those paths.
+  final Map<String, UnitInfo> unitInfoMap = {};
+
+  /// Initialize a newly created site to serve a preview of the results of an
+  /// NNBD migration.
+  PreviewSite(this.migrationInfo, this.pathMapper)
+      : super('NNBD Migration Preview') {
+    Set<UnitInfo> unitInfos = migrationInfo.units;
+    ResourceProvider provider = pathMapper.provider;
+    for (UnitInfo unit in unitInfos) {
+      unitInfoMap[unit.path] = unit;
+    }
+    for (UnitInfo unit in migrationInfo.unitMap.values) {
+      if (!unitInfos.contains(unit)) {
+        if (unit.content == null) {
+          try {
+            unit.content = provider.getFile(unit.path).readAsStringSync();
+          } catch (_) {
+            // If we can't read the content of the file, then skip it.
+            continue;
+          }
+        }
+        unitInfoMap[unit.path] = unit;
+      }
+    }
+  }
+
+  @override
+  Page createExceptionPage(String message, StackTrace trace) {
+    // Use createExceptionPageWithPath instead.
+    throw UnimplementedError();
+  }
+
+  /// Return a page used to display an exception that occurred while attempting
+  /// to render another page. The [path] is the path to the page that was being
+  /// rendered when the exception was thrown. The [message] and [stackTrace] are
+  /// those from the exception.
+  Page createExceptionPageWithPath(
+      String path, String message, StackTrace stackTrace) {
+    return ExceptionPage(this, path, message, stackTrace);
+  }
+
+  @override
+  Page createUnknownPage(String unknownPath) {
+    return NotFoundPage(this, unknownPath.substring(1));
+  }
+
+  @override
+  Future<void> handleGetRequest(HttpRequest request) async {
+    String path = request.uri.path;
+    try {
+      if (path == highlightCssPagePath) {
+        return respond(request, HighlightCssPage(this));
+      } else if (path == highlightJSPagePath) {
+        return respond(request, HighlightJSPage(this));
+      }
+      UnitInfo unitInfo = unitInfoMap[path];
+      if (unitInfo != null) {
+        return respond(request, DartFilePage(this, unitInfo));
+      }
+      return respond(request, createUnknownPage(path), HttpStatus.notFound);
+    } catch (exception, stackTrace) {
+      try {
+        await respond(
+            request,
+            createExceptionPageWithPath(path, '$exception', stackTrace),
+            HttpStatus.internalServerError);
+      } catch (exception, stackTrace) {
+        HttpResponse response = request.response;
+        response.statusCode = HttpStatus.internalServerError;
+        response.headers.contentType = ContentType.text;
+        response.write('$exception\n\n$stackTrace');
+        response.close();
+      }
+    }
+  }
+
+  @override
+  Future<void> respond(HttpRequest request, Page page,
+      [int code = HttpStatus.ok]) async {
+    HttpResponse response = request.response;
+    response.statusCode = code;
+    if (page is HighlightCssPage) {
+      response.headers.contentType =
+          ContentType('text', 'css', charset: 'utf-8');
+    } else if (page is HighlightJSPage) {
+      response.headers.contentType =
+          ContentType('application', 'javascript', charset: 'utf-8');
+    } else {
+      response.headers.contentType = ContentType.html;
+    }
+    response.write(await page.generate(request.uri.queryParameters));
+    response.close();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index b216613..0941eff 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -6,6 +6,8 @@
 import 'package:analysis_server/src/flutter/flutter_outline_computer.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/generated/engine.dart';
 
 void sendFlutterNotificationOutline(
     AnalysisServer server, ResolvedUnitResult resolvedUnit) {
@@ -29,8 +31,9 @@
     try {
       f();
     } catch (exception, stackTrace) {
-      server.sendServerErrorNotification(
-          'Failed to send notification', exception, stackTrace);
+      AnalysisEngine.instance.instrumentationService.logException(
+          CaughtException.withMessage(
+              'Failed to send notification', exception, stackTrace));
     }
   });
 }
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 535d6ae..f71c5b3 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -194,7 +194,7 @@
     contextManager.callbacks = contextManagerCallbacks;
     searchEngine = new SearchEngineImpl(driverMap.values);
 
-    channel.listen(handleMessage, onDone: done, onError: error);
+    channel.listen(handleMessage, onDone: done, onError: socketError);
   }
 
   /// The capabilities of the LSP client. Will be null prior to initialization.
@@ -222,14 +222,6 @@
    */
   void done() {}
 
-  /**
-   * There was an error related to the socket from which messages are being
-   * read.
-   */
-  void error(error, stack) {
-    sendServerErrorNotification('Server error', error, stack);
-  }
-
   /// Return the LineInfo for the file with the given [path]. The file is
   /// analyzed in one of the analysis drivers to which the file was added,
   /// otherwise in the first driver, otherwise `null` is returned.
@@ -328,7 +320,7 @@
           logException(errorMessage, error, stackTrace);
         }
       });
-    }, onError: error);
+    }, onError: socketError);
   }
 
   /// Logs the error on the client using window/logMessage.
@@ -455,7 +447,9 @@
     channel.sendResponse(response);
   }
 
-  void sendServerErrorNotification(String message, exception, stackTrace) {
+  @override
+  void sendServerErrorNotification(String message, exception, stackTrace,
+      {bool fatal = false}) {
     message = exception == null ? message : '$message: $exception';
 
     // Show message (without stack) to the user.
@@ -524,6 +518,15 @@
     return new Future.value();
   }
 
+  /**
+   * There was an error related to the socket from which messages are being
+   * read.
+   */
+  void socketError(error, stack) {
+    // Don't send to instrumentation service; not an internal error.
+    sendServerErrorNotification('Socket error', error, stack);
+  }
+
   void updateAnalysisRoots(List<String> addedPaths, List<String> removedPaths) {
     // TODO(dantup): This is currently case-sensitive!
     final newPaths =
@@ -625,8 +628,9 @@
       if (result.contextKey != null) {
         message += ' context: ${result.contextKey}';
       }
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.wrapInMessage(message, result.exception));
+          new SilentException.wrapInMessage(message, result.exception));
     });
     analysisServer.driverMap[folder] = analysisDriver;
     return analysisDriver;
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index f275ee9..ca211a1 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -17,6 +17,8 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 Future<void> scheduleImplementedNotification(
@@ -39,10 +41,11 @@
             file, computer.classes, computer.members);
         server.sendNotification(params.toNotification());
       } catch (exception, stackTrace) {
-        server.sendServerErrorNotification(
-            'Failed to send analysis.implemented notification.',
-            exception,
-            stackTrace);
+        AnalysisEngine.instance.instrumentationService.logException(
+            CaughtException.withMessage(
+                'Failed to send analysis.implemented notification.',
+                exception,
+                stackTrace));
       }
     }
   }
@@ -175,8 +178,9 @@
     try {
       f();
     } catch (exception, stackTrace) {
-      server.sendServerErrorNotification(
-          'Failed to send notification', exception, stackTrace);
+      AnalysisEngine.instance.instrumentationService.logException(
+          CaughtException.withMessage(
+              'Failed to send notification', exception, stackTrace));
     }
   });
 }
diff --git a/pkg/analysis_server/lib/src/server/crash_reporting.dart b/pkg/analysis_server/lib/src/server/crash_reporting.dart
new file mode 100644
index 0000000..498a45b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/crash_reporting.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/instrumentation/noop_service.dart';
+import 'package:analyzer/instrumentation/plugin_data.dart';
+import 'package:telemetry/crash_reporting.dart';
+
+class CrashReportingInstrumentation extends NoopInstrumentationService {
+  final CrashReportSender reporter;
+
+  CrashReportingInstrumentation(this.reporter);
+
+  @override
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    reporter
+        .sendReport(exception, stackTrace: stackTrace ?? StackTrace.current)
+        .catchError((error) {
+      // We silently ignore errors sending crash reports (network issues, ...).
+    });
+  }
+
+  @override
+  void logPluginException(
+      PluginData plugin, dynamic exception, StackTrace stackTrace) {
+    // TODO(mfairhurst): send plugin information too.
+    reporter.sendReport(exception, stackTrace: stackTrace).catchError((error) {
+      // We silently ignore errors sending crash reports (network issues, ...).
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index b0baf27..4714d6e 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -10,11 +10,12 @@
 import 'package:analysis_server/protocol/protocol_constants.dart'
     show PROTOCOL_VERSION;
 import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/lsp_socket_server.dart';
+import 'package:analysis_server/src/server/crash_reporting.dart';
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/dev_server.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/error_notifier.dart';
 import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/http_server.dart';
 import 'package:analysis_server/src/server/lsp_stdio_server.dart';
@@ -25,6 +26,7 @@
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analysis_server/starter.dart';
+import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/file_instrumentation.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -33,7 +35,6 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:args/args.dart';
-import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:linter/src/rules.dart' as linter;
 import 'package:path/path.dart' as path;
 import 'package:telemetry/crash_reporting.dart';
@@ -334,9 +335,9 @@
   static const String TRAIN_USING = "train-using";
 
   /**
-   * The instrumentation server that is to be used by the analysis server.
+   * The instrumentation service that is to be used by the analysis server.
    */
-  InstrumentationServer instrumentationServer;
+  InstrumentationService instrumentationService;
 
   /**
    * The file resolver provider used to override the way file URI's are
@@ -423,9 +424,13 @@
       analytics.setSessionValue('cd1', analysisServerOptions.clientVersion);
     }
 
-    // TODO(devoncarew): Replace with the real crash product ID.
-    analysisServerOptions.crashReportSender =
-        new CrashReportSender('Dart_analysis_server', analytics);
+    final shouldSendCallback = () {
+      // TODO(devoncarew): Replace with a real enablement check.
+      return false;
+    };
+
+    final crashReportSender =
+        new CrashReportSender('Dart_analysis_server', shouldSendCallback);
 
     if (telemetry.SHOW_ANALYTICS_UI) {
       if (results.wasParsed(ANALYTICS_FLAG)) {
@@ -466,17 +471,20 @@
     // Initialize the instrumentation service.
     //
     String logFilePath = results[INSTRUMENTATION_LOG_FILE];
+    List<InstrumentationService> allInstrumentationServices =
+        instrumentationService == null ? [] : [instrumentationService];
     if (logFilePath != null) {
       _rollLogFiles(logFilePath, 5);
-      FileInstrumentationServer fileBasedServer =
-          new FileInstrumentationServer(logFilePath);
-      instrumentationServer = instrumentationServer != null
-          ? new MulticastInstrumentationServer(
-              [instrumentationServer, fileBasedServer])
-          : fileBasedServer;
+      allInstrumentationServices.add(InstrumentationLogAdapter(
+          new FileInstrumentationLogger(logFilePath)));
     }
-    InstrumentationService instrumentationService =
-        new InstrumentationService(instrumentationServer);
+
+    ErrorNotifier errorNotifier = ErrorNotifier();
+    allInstrumentationServices
+        .add(CrashReportingInstrumentation(crashReportSender));
+    instrumentationService =
+        new MulticastInstrumentationService(allInstrumentationServices);
+
     instrumentationService.logVersion(
         results[TRAIN_USING] != null
             ? 'training-0'
@@ -500,22 +508,21 @@
       }
     }
 
-    CompilerContext.runWithDefaultOptions((_) async {
-      if (analysisServerOptions.useLanguageServerProtocol) {
-        startLspServer(results, analysisServerOptions, dartSdkManager,
-            instrumentationService, diagnosticServerPort);
-      } else {
-        startAnalysisServer(
-            results,
-            analysisServerOptions,
-            parser,
-            dartSdkManager,
-            instrumentationService,
-            RequestStatisticsHelper(),
-            analytics,
-            diagnosticServerPort);
-      }
-    });
+    if (analysisServerOptions.useLanguageServerProtocol) {
+      startLspServer(results, analysisServerOptions, dartSdkManager,
+          instrumentationService, diagnosticServerPort, errorNotifier);
+    } else {
+      startAnalysisServer(
+          results,
+          analysisServerOptions,
+          parser,
+          dartSdkManager,
+          instrumentationService,
+          RequestStatisticsHelper(),
+          analytics,
+          diagnosticServerPort,
+          errorNotifier);
+    }
   }
 
   void startAnalysisServer(
@@ -527,6 +534,7 @@
     RequestStatisticsHelper requestStatistics,
     telemetry.Analytics analytics,
     int diagnosticServerPort,
+    ErrorNotifier errorNotifier,
   ) {
     String trainDirectory = results[TRAIN_USING];
     if (trainDirectory != null) {
@@ -562,6 +570,8 @@
         detachableFileSystemManager);
     httpServer = new HttpAnalysisServer(socketServer);
 
+    errorNotifier.server = socketServer.analysisServer;
+
     diagnosticServer.httpServer = httpServer;
     if (serve_http) {
       diagnosticServer.startOnPort(diagnosticServerPort);
@@ -604,7 +614,7 @@
         exit(exitCode);
       }();
     } else {
-      _captureExceptions(socketServer, instrumentationService, () {
+      _captureExceptions(instrumentationService, () {
         StdioAnalysisServer stdioServer = new StdioAnalysisServer(socketServer);
         stdioServer.serveStdio().then((_) async {
           // TODO(brianwilkerson) Determine whether this await is necessary.
@@ -643,17 +653,13 @@
     // server was configured to load a language model on disk.
     CompletionRanking.instance =
         CompletionRanking(analysisServerOptions.completionModelFolder);
-    CompletionRanking.instance.start().catchError((error) {
+    CompletionRanking.instance.start().catchError((error, stackTrace) {
       // Disable smart ranking if model startup fails.
       analysisServerOptions.completionModelFolder = null;
       CompletionRanking.instance = null;
-      if (socketServer != null) {
-        socketServer.analysisServer.sendServerErrorNotification(
-            'Failed to start ranking model isolate', error, error.stackTrace);
-      } else {
-        lspSocketServer.analysisServer.sendServerErrorNotification(
-            'Failed to start ranking model isolate', error, error.stackTrace);
-      }
+      AnalysisEngine.instance.instrumentationService.logException(
+          CaughtException.withMessage(
+              'Failed to start ranking model isolate', error, stackTrace));
     });
   }
 
@@ -663,6 +669,7 @@
     DartSdkManager dartSdkManager,
     InstrumentationService instrumentationService,
     int diagnosticServerPort,
+    ErrorNotifier errorNotifier,
   ) {
     final serve_http = diagnosticServerPort != null;
 
@@ -676,6 +683,7 @@
       dartSdkManager,
       instrumentationService,
     );
+    errorNotifier.server = socketServer.analysisServer;
 
     httpServer = new HttpAnalysisServer(socketServer);
 
@@ -684,7 +692,7 @@
       diagnosticServer.startOnPort(diagnosticServerPort);
     }
 
-    _captureLspExceptions(socketServer, instrumentationService, () {
+    _captureExceptions(instrumentationService, () {
       LspStdioAnalysisServer stdioServer =
           new LspStdioAnalysisServer(socketServer);
       stdioServer.serveStdio().then((_) async {
@@ -705,14 +713,11 @@
    * instrumentation [service]. If a [print] function is provided, then also
    * capture any data printed by the callback and redirect it to the function.
    */
-  dynamic _captureExceptions(SocketServer socketServer,
-      InstrumentationService service, dynamic callback(),
+  dynamic _captureExceptions(InstrumentationService service, dynamic callback(),
       {void print(String line)}) {
     void errorFunction(Zone self, ZoneDelegate parent, Zone zone,
         dynamic exception, StackTrace stackTrace) {
-      service.logPriorityException(exception, stackTrace);
-      socketServer.analysisServer.sendServerErrorNotification(
-          'Captured exception', exception, stackTrace);
+      service.logException(exception, stackTrace);
       throw exception;
     }
 
@@ -729,33 +734,6 @@
   }
 
   /**
-   * Execute the given [callback] within a zone that will capture any unhandled
-   * exceptions and both report them to the client and send them to the given
-   * instrumentation [service]. If a [print] function is provided, then also
-   * capture any data printed by the callback and redirect it to the function.
-   */
-  dynamic _captureLspExceptions(
-      // TODO(dantup): This is a copy/paste of the above with some minor changes.
-      // We should either factor these out, or if we end up with an LspDriver, put
-      // this there.
-      LspSocketServer socketServer,
-      InstrumentationService service,
-      dynamic callback()) {
-    void errorFunction(Zone self, ZoneDelegate parent, Zone zone,
-        dynamic exception, StackTrace stackTrace) {
-      service.logPriorityException(exception, stackTrace);
-      LspAnalysisServer analysisServer = socketServer.analysisServer;
-      analysisServer.sendServerErrorNotification(
-          'Captured exception', exception, stackTrace);
-      throw exception;
-    }
-
-    ZoneSpecification zoneSpecification =
-        new ZoneSpecification(handleUncaughtError: errorFunction);
-    return runZoned(callback, zoneSpecification: zoneSpecification);
-  }
-
-  /**
    * Create and return the parser used to parse the command-line arguments.
    */
   CommandLineParser _createArgParser() {
@@ -909,14 +887,14 @@
         }
       }
     } catch (exception, stackTrace) {
-      service.logPriorityException(exception, stackTrace);
+      service.logException(exception, stackTrace);
     }
     String uuid = _generateUuidString();
     try {
       uuidFile.parent.createSync(recursive: true);
       uuidFile.writeAsStringSync(uuid);
     } catch (exception, stackTrace) {
-      service.logPriorityException(exception, stackTrace);
+      service.logException(exception, stackTrace);
       // Slightly alter the uuid to indicate it was not persisted
       uuid = 'temp-$uuid';
     }
diff --git a/pkg/analysis_server/lib/src/server/error_notifier.dart b/pkg/analysis_server/lib/src/server/error_notifier.dart
new file mode 100644
index 0000000..57bd646
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/error_notifier.dart
@@ -0,0 +1,32 @@
+import 'package:analysis_server/src/analysis_server_abstract.dart';
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
+
+/// An instrumentation service to show instrumentation errors as error
+/// notifications to the user.
+class ErrorNotifier extends NoopInstrumentationService {
+  AbstractAnalysisServer server;
+
+  @override
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    if (exception is SilentException) {
+      // Silent exceptions should not be reported to the user.
+      return;
+    }
+
+    var message = 'Internal error';
+    if (exception is CaughtException && exception.message != null) {
+      message = exception.message;
+    }
+
+    server.sendServerErrorNotification(message, exception, stackTrace,
+        fatal: exception is FatalException);
+  }
+}
+
+/// Server may throw a [FatalException] to send a fatal error response to the
+/// IDEs.
+class FatalException extends CaughtException {
+  FatalException(String message, Object exception, stackTrace)
+      : super.withMessage(message, exception, stackTrace);
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
index 8213781..7a41cc9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
@@ -14,7 +14,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 
 /// Number of lookback tokens.
-const int _LOOKBACK = 50;
+const int _LOOKBACK = 100;
 
 /// Minimum probability to prioritize model-only suggestion.
 const double _MODEL_RELEVANCE_CUTOFF = 0.5;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index da04677..1f5f28c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -2092,10 +2092,10 @@
       // should be parameter of function type
       DartType parameterType = parameterElement.type;
       if (parameterType is InterfaceType && parameterType.isDartCoreFunction) {
-        parameterType = FunctionTypeImpl.synthetic(
-          typeProvider.dynamicType,
-          [],
-          [],
+        parameterType = FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: const [],
+          returnType: typeProvider.dynamicType,
           nullabilitySuffix: NullabilitySuffix.none,
         );
       }
@@ -4376,10 +4376,10 @@
     SdkConstraintExtractor extractor = new SdkConstraintExtractor(pubspecFile);
     String text = extractor.constraintText();
     int offset = extractor.constraintOffset();
-    int length = text.length;
     if (text == null || offset < 0) {
       return;
     }
+    int length = text.length;
     String newText;
     int spaceOffset = text.indexOf(' ');
     if (spaceOffset >= 0) {
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 46ef35f..938cb49 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -829,7 +829,7 @@
     pages.add(new ContextsPage(this));
     pages.add(new EnvironmentVariablesPage(this));
     pages.add(new ExceptionsPage(this));
-    pages.add(new InstrumentationPage(this));
+    //pages.add(new InstrumentationPage(this));
     pages.add(new ProfilePage(this));
 
     // Add server-specific pages. Ordering doesn't matter as the items are
@@ -1016,41 +1016,41 @@
   }
 }
 
-class InstrumentationPage extends DiagnosticPageWithNav {
-  InstrumentationPage(DiagnosticsSite site)
-      : super(site, 'instrumentation', 'Instrumentation',
-            description:
-                'Verbose instrumentation data from the analysis server.');
-
-  @override
-  Future generateContent(Map<String, String> params) async {
-    p(
-        'Instrumentation can be enabled by starting the analysis server with the '
-        '<code>--instrumentation-log-file=path/to/file</code> flag.',
-        raw: true);
-
-    if (!AnalysisEngine.instance.instrumentationService.isActive) {
-      blankslate('Instrumentation not active.');
-      return;
-    }
-
-    h3('Instrumentation');
-
-    p('Instrumentation active.');
-
-    InstrumentationServer instrumentation =
-        AnalysisEngine.instance.instrumentationService.instrumentationServer;
-    String description = instrumentation.describe;
-    HtmlEscape htmlEscape = new HtmlEscape(HtmlEscapeMode.element);
-    description = htmlEscape.convert(description);
-    // Convert http(s): references to hyperlinks.
-    final RegExp urlRegExp = new RegExp(r'[http|https]+:\/*(\S+)');
-    description = description.replaceAllMapped(urlRegExp, (Match match) {
-      return '<a href="${match.group(0)}">${match.group(1)}</a>';
-    });
-    p(description.replaceAll('\n', '<br>'), raw: true);
-  }
-}
+// class InstrumentationPage extends DiagnosticPageWithNav {
+//   InstrumentationPage(DiagnosticsSite site)
+//       : super(site, 'instrumentation', 'Instrumentation',
+//             description:
+//                 'Verbose instrumentation data from the analysis server.');
+//
+//   @override
+//   Future generateContent(Map<String, String> params) async {
+//     p(
+//         'Instrumentation can be enabled by starting the analysis server with the '
+//         '<code>--instrumentation-log-file=path/to/file</code> flag.',
+//         raw: true);
+//
+//     if (!AnalysisEngine.instance.instrumentationService.isActive) {
+//       blankslate('Instrumentation not active.');
+//       return;
+//     }
+//
+//     h3('Instrumentation');
+//
+//     p('Instrumentation active.');
+//
+//     InstrumentationServer instrumentation =
+//         AnalysisEngine.instance.instrumentationService.instrumentationServer;
+//     String description = instrumentation.describe;
+//     HtmlEscape htmlEscape = new HtmlEscape(HtmlEscapeMode.element);
+//     description = htmlEscape.convert(description);
+//     // Convert http(s): references to hyperlinks.
+//     final RegExp urlRegExp = new RegExp(r'[http|https]+:\/*(\S+)');
+//     description = description.replaceAllMapped(urlRegExp, (Match match) {
+//       return '<a href="${match.group(0)}">${match.group(1)}</a>';
+//     });
+//     p(description.replaceAll('\n', '<br>'), raw: true);
+//   }
+// }
 
 class LspCapabilitiesPage extends DiagnosticPageWithNav {
   @override
@@ -1410,8 +1410,8 @@
     buf.writeln('<div class="column one-half">');
     h3('Status');
     buf.writeln(writeOption('Server type', server.runtimeType));
-    buf.writeln(writeOption('Instrumentation enabled',
-        AnalysisEngine.instance.instrumentationService.isActive));
+    // buf.writeln(writeOption('Instrumentation enabled',
+    //     AnalysisEngine.instance.instrumentationService.isActive));
     buf.writeln(writeOption('Server process ID', pid));
     buf.writeln('</div>');
 
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index 170c4b8..884d17b7 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -33,9 +33,9 @@
   void set fileResolverProvider(ResolverProvider provider);
 
   /**
-   * Set the instrumentation [server] that is to be used by the analysis server.
+   * Set the instrumentation [service] that is to be used by the analysis server.
    */
-  void set instrumentationServer(InstrumentationServer server);
+  void set instrumentationService(InstrumentationService service);
 
   /**
    * Set the package resolver provider used to override the way package URI's
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index ed5bec3..e8ac58f 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2511,8 +2511,8 @@
     driverMap[path] = currentDriver;
     currentDriver.exceptions.listen((ExceptionResult result) {
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.wrapInMessage(
-              'Analysis failed: ${result.path}', result.exception));
+          new CaughtException.withMessage('Analysis failed: ${result.path}',
+              result.exception.exception, result.exception.stackTrace));
     });
     return currentDriver;
   }
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
index b849d8b..e4e9f2d 100644
--- a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
@@ -26,7 +26,7 @@
     String packageRoot = resourceProvider.convertPath('/package');
     String outputDir = resourceProvider.convertPath('/output');
     MigrationInfo migrationInfo = MigrationInfo(
-        libraryInfo.units, resourceProvider.pathContext, packageRoot);
+        libraryInfo.units, {}, resourceProvider.pathContext, packageRoot);
     List<String> contents = [];
     for (UnitInfo unitInfo in libraryInfo.units) {
       contents.add(InstrumentationRenderer(unitInfo, migrationInfo,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_ranking_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_ranking_test.dart
index f975eb1..a876f51 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_ranking_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_ranking_test.dart
@@ -20,7 +20,7 @@
     final tokens =
         tokenize('if (list == null) { return; } for (final i = 0; i < list.');
     final response = await ranking.makeRequest('predict', tokens);
-    expect(response['data']['length'], greaterThan(0.85));
+    expect(response['data']['length'], greaterThan(0.9));
   });
 }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/language_model_test.dart b/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
index 3fab0ee..40cafbf 100644
--- a/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
@@ -11,7 +11,7 @@
 
 final directory = path.join(File.fromUri(Platform.script).parent.path, '..',
     '..', '..', '..', 'language_model', 'lexeme');
-const expectedLookback = 50;
+const expectedLookback = 100;
 
 void main() {
   if (sizeOf<IntPtr>() == 4) {
@@ -46,7 +46,7 @@
     final suggestions = model.predictWithScores(tokens);
     final best = suggestions.entries.first;
     expect(best.key, 'length');
-    expect(best.value, greaterThan(0.85));
+    expect(best.value, greaterThan(0.9));
   });
 
   test('predict when no previous tokens', () {
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index f284a85..56119bb 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -8,8 +8,9 @@
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/server/error_notifier.dart';
 import 'package:analysis_server/src/socket_server.dart';
-import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:test/test.dart';
 
@@ -29,10 +30,9 @@
 
 class SocketServerTest {
   static void createAnalysisServer_alreadyStarted() {
-    SocketServer server = _createSocketServer();
     MockServerChannel channel1 = new MockServerChannel();
     MockServerChannel channel2 = new MockServerChannel();
-    server.createAnalysisServer(channel1);
+    SocketServer server = _createSocketServer(channel1);
     expect(
         channel1.notificationsReceived[0].event, SERVER_NOTIFICATION_CONNECTED);
     server.createAnalysisServer(channel2);
@@ -54,9 +54,8 @@
   }
 
   static Future createAnalysisServer_successful() {
-    SocketServer server = _createSocketServer();
     MockServerChannel channel = new MockServerChannel();
-    server.createAnalysisServer(channel);
+    SocketServer server = _createSocketServer(channel);
     channel.expectMsgCount(notificationCount: 1);
     expect(
         channel.notificationsReceived[0].event, SERVER_NOTIFICATION_CONNECTED);
@@ -70,9 +69,8 @@
   }
 
   static Future requestHandler_exception() {
-    SocketServer server = _createSocketServer();
     MockServerChannel channel = new MockServerChannel();
-    server.createAnalysisServer(channel);
+    SocketServer server = _createSocketServer(channel);
     channel.expectMsgCount(notificationCount: 1);
     expect(
         channel.notificationsReceived[0].event, SERVER_NOTIFICATION_CONNECTED);
@@ -91,9 +89,8 @@
   }
 
   static Future requestHandler_futureException() async {
-    SocketServer server = _createSocketServer();
     MockServerChannel channel = new MockServerChannel();
-    server.createAnalysisServer(channel);
+    SocketServer server = _createSocketServer(channel);
     _MockRequestHandler handler = new _MockRequestHandler(true);
     server.analysisServer.handlers = [handler];
     var request = new ServerGetVersionParams().toRequest('0');
@@ -104,16 +101,23 @@
     expect(channel.notificationsReceived[1].event, SERVER_NOTIFICATION_ERROR);
   }
 
-  static SocketServer _createSocketServer() {
-    return new SocketServer(
+  static SocketServer _createSocketServer(MockServerChannel channel) {
+    final errorNotifier = new ErrorNotifier();
+    final server = new SocketServer(
         new AnalysisServerOptions(),
         new DartSdkManager('', false),
-        InstrumentationService.NULL_SERVICE,
+        errorNotifier,
         null,
         null,
         null,
         null,
         null);
+
+    server.createAnalysisServer(channel);
+    errorNotifier.server = server.analysisServer;
+    AnalysisEngine.instance.instrumentationService = errorNotifier;
+
+    return server;
   }
 }
 
diff --git a/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
index a2b0dcc..49d96a5 100644
--- a/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
+++ b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
@@ -76,58 +76,60 @@
 
   test_included_multipleRelativeDirectories() async {
     NonNullableFix fix =
-        NonNullableFix(listener, '.', included: ['lib', 'test']);
+        NonNullableFix(listener, '.', null, included: ['lib', 'test']);
     expect(fix.includedRoot, equals(convertPath('/project')));
   }
 
   test_included_multipleRelativeDirectories_nonCanonical() async {
-    NonNullableFix fix = NonNullableFix(listener, '.',
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
         included: ['../project2/lib', '../project2/lib/src']);
     expect(fix.includedRoot, equals(convertPath('/project2/lib')));
   }
 
   test_included_multipleRelativeDirectories_nonCanonical_atFilesystemRoot() async {
-    NonNullableFix fix = NonNullableFix(listener, '.',
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
         included: ['../project2/lib', '../project/lib']);
     expect(fix.includedRoot, equals(convertPath('/')));
   }
 
   test_included_multipleRelativeDirectories_subAndSuperDirectories() async {
-    NonNullableFix fix = NonNullableFix(listener, '.', included: ['lib', '.']);
+    NonNullableFix fix =
+        NonNullableFix(listener, '.', null, included: ['lib', '.']);
     expect(fix.includedRoot, equals(convertPath('/project')));
   }
 
   test_included_multipleRelativeFiles() async {
-    NonNullableFix fix = NonNullableFix(listener, '.',
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
         included: ['lib/lib1.dart', 'test/test.dart']);
     expect(fix.includedRoot, equals(convertPath('/project')));
   }
 
   test_included_multipleRelativeFiles_sameDirectory() async {
-    NonNullableFix fix = NonNullableFix(listener, '.',
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
         included: ['lib/lib1.dart', 'lib/lib2.dart']);
     expect(fix.includedRoot, equals(convertPath('/project/lib')));
   }
 
   test_included_multipleRelativeFilesAndDirectories() async {
-    NonNullableFix fix = NonNullableFix(listener, '.',
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
         included: ['lib/lib1.dart', 'lib/src', '../project/lib/src/lib3.dart']);
     expect(fix.includedRoot, equals(convertPath('/project/lib')));
   }
 
   test_included_singleAbsoluteDirectory() async {
-    NonNullableFix fix = NonNullableFix(listener, '.', included: ['/project']);
+    NonNullableFix fix =
+        NonNullableFix(listener, '.', null, included: ['/project']);
     expect(fix.includedRoot, equals(convertPath('/project')));
   }
 
   test_included_singleAbsoluteFile() async {
-    NonNullableFix fix =
-        NonNullableFix(listener, '.', included: ['/project/bin/bin.dart']);
+    NonNullableFix fix = NonNullableFix(listener, '.', null,
+        included: ['/project/bin/bin.dart']);
     expect(fix.includedRoot, equals(convertPath('/project/bin')));
   }
 
   test_included_singleRelativeDirectory() async {
-    NonNullableFix fix = NonNullableFix(listener, '.', included: ['.']);
+    NonNullableFix fix = NonNullableFix(listener, '.', null, included: ['.']);
     expect(fix.includedRoot, equals(convertPath('/project')));
   }
 
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index 3be8718..593a8fd 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -91,7 +91,8 @@
     migration.finish();
     // Build the migration info.
     InstrumentationInformation info = instrumentationListener.data;
-    InfoBuilder builder = InfoBuilder(info, listener);
+    InfoBuilder builder =
+        InfoBuilder(info, listener, explainNonNullableTypes: true);
     infos = (await builder.explainMigration()).toList();
   }
 
@@ -103,8 +104,12 @@
       {@required String migratedContent}) async {
     addTestFile(originalContent);
     await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
+    // Ignore info for dart:core
+    var filteredInfos = [
+      for (var info in infos) if (info.path.indexOf('core.dart') == -1) info
+    ];
+    expect(filteredInfos, hasLength(1));
+    UnitInfo unit = filteredInfos[0];
     expect(unit.path, testFile);
     expect(unit.content, migratedContent);
     return unit;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
index ed3eee0..f7a88ed 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
@@ -167,8 +167,8 @@
     await resolveTestUnit('''
 class A {
   B b;
-  void f(Object p) {
-    p == b.test;
+  void f(dynamic context) {
+    context == b.test;
   }
 }
 class B {
@@ -177,8 +177,8 @@
     await assertHasFix('''
 class A {
   B b;
-  void f(Object p) {
-    p == b.test;
+  void f(dynamic context) {
+    context == b.test;
   }
 }
 class B {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
index e324763..22b0b44 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
@@ -234,8 +234,8 @@
     await resolveTestUnit('''
 class A {
   B b;
-  void f(Object p) {
-    p == b.test;
+  void f(dynamic context) {
+    context == b.test;
   }
 }
 class B {
@@ -244,8 +244,8 @@
     await assertHasFix('''
 class A {
   B b;
-  void f(Object p) {
-    p == b.test;
+  void f(dynamic context) {
+    context == b.test;
   }
 }
 class B {
diff --git a/pkg/analysis_server/tool/instrumentation/log/log.dart b/pkg/analysis_server/tool/instrumentation/log/log.dart
index f575765..5e658c0 100644
--- a/pkg/analysis_server/tool/instrumentation/log/log.dart
+++ b/pkg/analysis_server/tool/instrumentation/log/log.dart
@@ -658,57 +658,48 @@
       }
       timeStamp = int.parse(component);
       String entryKind = components[1];
-      if (entryKind == InstrumentationService.TAG_ANALYSIS_TASK) {
-        return new TaskEntry(index, timeStamp, components[2], components[3]);
-      } else if (entryKind == InstrumentationService.TAG_ERROR) {
+      if (entryKind == InstrumentationLogAdapter.TAG_ERROR) {
         return new ErrorEntry(
             index, timeStamp, entryKind, components.sublist(2));
-      } else if (entryKind == InstrumentationService.TAG_EXCEPTION) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_EXCEPTION) {
         return new ExceptionEntry(
             index, timeStamp, entryKind, components.sublist(2));
-      } else if (entryKind == InstrumentationService.TAG_FILE_READ) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_LOG_ENTRY) {
         // Fall through
-      } else if (entryKind == InstrumentationService.TAG_LOG_ENTRY) {
-        // Fall through
-      } else if (entryKind == InstrumentationService.TAG_NOTIFICATION) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_NOTIFICATION) {
         Map requestData = json.decode(components[2]);
         return new NotificationEntry(index, timeStamp, requestData);
-      } else if (entryKind == InstrumentationService.TAG_PERFORMANCE) {
-        // Fall through
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_ERROR) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_PLUGIN_ERROR) {
         return new PluginErrorEntry(index, timeStamp, entryKind,
             components.sublist(2, 4), components.sublist(4));
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_EXCEPTION) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_PLUGIN_EXCEPTION) {
         return new PluginExceptionEntry(index, timeStamp, entryKind,
             components.sublist(2, 5), components.sublist(5));
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_NOTIFICATION) {
+      } else if (entryKind ==
+          InstrumentationLogAdapter.TAG_PLUGIN_NOTIFICATION) {
         Map requestData = json.decode(components[2]);
         return new PluginNotificationEntry(
             index, timeStamp, requestData, components.sublist(3));
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_REQUEST) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_PLUGIN_REQUEST) {
         Map requestData = json.decode(components[2]);
         return new PluginRequestEntry(
             index, timeStamp, requestData, components.sublist(3));
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_RESPONSE) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_PLUGIN_RESPONSE) {
         Map responseData = json.decode(components[2]);
         return new PluginResponseEntry(
             index, timeStamp, responseData, components.sublist(3));
-      } else if (entryKind == InstrumentationService.TAG_PLUGIN_TIMEOUT) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_PLUGIN_TIMEOUT) {
         return new PluginErrorEntry(index, timeStamp, entryKind,
             components.sublist(2, 3), components.sublist(3));
-      } else if (entryKind == InstrumentationService.TAG_REQUEST) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_REQUEST) {
         Map requestData = json.decode(components[2]);
         return new RequestEntry(index, timeStamp, requestData);
-      } else if (entryKind == InstrumentationService.TAG_RESPONSE) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_RESPONSE) {
         Map responseData = json.decode(components[2]);
         return new ResponseEntry(index, timeStamp, responseData);
-      } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_START) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_VERSION) {
         // Fall through
-      } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_RESULT) {
-        // Fall through
-      } else if (entryKind == InstrumentationService.TAG_VERSION) {
-        // Fall through
-      } else if (entryKind == InstrumentationService.TAG_WATCH_EVENT) {
+      } else if (entryKind == InstrumentationLogAdapter.TAG_WATCH_EVENT) {
         // Fall through
       }
       return new GenericEntry(
diff --git a/pkg/analysis_server/tool/instrumentation/page/log_page.dart b/pkg/analysis_server/tool/instrumentation/page/log_page.dart
index bb9b9c9..e3c7a5b 100644
--- a/pkg/analysis_server/tool/instrumentation/page/log_page.dart
+++ b/pkg/analysis_server/tool/instrumentation/page/log_page.dart
@@ -166,8 +166,7 @@
         var analysisStatus = entry.param('analysis');
         if (analysisStatus is Map) {
           if (analysisStatus['isAnalyzing']) {
-            description =
-                '$description <span class="gray">(analysis)</span> (<a href="${WebServer.taskPath}?analysisStart=${entry.index}">tasks</a>)';
+            description = '$description <span class="gray">(analyzing)</span>';
           } else {
             String duration = _getDuration(pairedEntry, entry);
             description =
diff --git a/pkg/analysis_server/tool/instrumentation/page/task_page.dart b/pkg/analysis_server/tool/instrumentation/page/task_page.dart
deleted file mode 100644
index e553eab..0000000
--- a/pkg/analysis_server/tool/instrumentation/page/task_page.dart
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:math' as math;
-
-import '../log/log.dart';
-import '../server.dart';
-import 'page_writer.dart';
-
-/**
- * A class used to write a human-readable version of the tasks executed within a
- * single analysis step.
- */
-class TaskPage extends PageWriter {
-  /**
-   * The instrumentation log to be written.
-   */
-  final InstrumentationLog log;
-
-  /**
-   * The index of the entry representing the start of an analysis session.
-   */
-  int analysisStart = 0;
-
-  /**
-   * The index of the first task to be written.
-   */
-  int pageStart = 0;
-
-  /**
-   * The number of tasks to be written, or `null` if all of the tasks should
-   * be written.
-   */
-  int pageLength = null;
-
-  /**
-   * The number of digits in the event stamps that are the same for every task.
-   */
-  int prefixLength;
-
-  /**
-   * Initialize a newly created page writer to write a single page worth of
-   * tasks.
-   */
-  TaskPage(this.log);
-
-  @override
-  void writeBody(StringSink sink) {
-    writeMenu(sink);
-    writeTwoColumns(
-        sink, 'leftColumn', _writeLeftColumn, 'rightColumn', _writeRightColumn);
-  }
-
-  @override
-  void writeScripts(StringSink sink) {
-    super.writeScripts(sink);
-    sink.writeln(r'''
-function setDetails(detailsContent) {
-  var element = document.getElementById("details");
-  if (element != null) {
-    element.innerHTML = detailsContent;
-  }
-}
-''');
-  }
-
-  /**
-   * Write the content of the style sheet (without the 'script' tag) for the
-   * page to the given [sink].
-   */
-  void writeStyleSheet(StringSink sink) {
-    super.writeStyleSheet(sink);
-    writeTwoColumnStyles(sink, 'leftColumn', 'rightColumn');
-  }
-
-  /**
-   * Write the given log [entry] to the given [sink].
-   */
-  void _writeEntry(StringSink sink, TaskEntry entry) {
-    String clickHandler = 'setDetails(\'${escape(entry.details())}\')';
-    String timeStamp = entry.timeStamp.toString();
-    if (prefixLength > 0) {
-      timeStamp = timeStamp.substring(prefixLength);
-    }
-
-    sink.writeln('<tr onclick="$clickHandler">');
-    sink.writeln('<td>');
-    sink.writeln(timeStamp);
-    sink.writeln('</td>');
-    sink.writeln('<td>');
-    sink.writeln(entry.taskName);
-    sink.writeln('</td>');
-    sink.writeln('<td style="white-space:nowrap;">');
-    sink.writeln(entry.target);
-    sink.writeln('</td>');
-    sink.writeln('</tr>');
-  }
-
-  /**
-   * Write the entries in the instrumentation log to the given [sink].
-   */
-  void _writeLeftColumn(StringSink sink) {
-    List<TaskEntry> entries = log.taskEntriesFor(analysisStart);
-    prefixLength = computePrefixLength(entries);
-    int length = entries.length;
-    int pageEnd =
-        pageLength == null ? length : math.min(pageStart + pageLength, length);
-    //
-    // Write the header of the column.
-    //
-    sink.writeln('<div class="columnHeader">');
-    sink.writeln('<div style="float: left">');
-    sink.writeln('Tasks $pageStart - ${pageEnd - 1} of ${length - 1}');
-    sink.writeln('</div>');
-
-    sink.writeln('<div style="float: right">');
-    if (pageStart == 0) {
-      sink.writeln('<button type="button" disabled><b>&lt;</b></button>');
-    } else {
-      sink.write('<button type="button">');
-      sink.write(
-          '<a href="${WebServer.taskPath}?analysisStart=$analysisStart&start=${pageStart - pageLength}">');
-      sink.write('<b>&lt;</b>');
-      sink.writeln('</a></button>');
-    }
-    // TODO(brianwilkerson) Add a text field for selecting the start index.
-    if (pageEnd == length) {
-      sink.writeln('<button type="button" disabled><b>&gt;</b></button>');
-    } else {
-      sink.write('<button type="button">');
-      sink.write(
-          '<a href="${WebServer.taskPath}?analysisStart=$analysisStart&start=${pageStart + pageLength}">');
-      sink.write('<b>&gt;</b>');
-      sink.writeln('</a></button>');
-    }
-    sink.writeln('</div>');
-    sink.writeln('</div>');
-    //
-    // Write the main body of the column.
-    //
-    sink.writeln('<table class="fullWidth">');
-    sink.writeln('<tr>');
-    sink.writeln('<th>Time</th>');
-    sink.writeln('<th>Task</th>');
-    sink.writeln('<th>Target</th>');
-    sink.writeln('</tr>');
-    for (int i = pageStart; i < pageEnd; i++) {
-      LogEntry entry = entries[i];
-      _writeEntry(sink, entry);
-    }
-    sink.writeln('</table>');
-  }
-
-  /**
-   * Write a placeholder to the given [sink] where the details of a selected
-   * entry can be displayed.
-   */
-  void _writeRightColumn(StringSink sink) {
-    //
-    // Write the header of the column.
-    //
-    sink.writeln('<div class="columnHeader">');
-    sink.writeln('<p><b>Task Details</b></p>');
-    sink.writeln('</div>');
-    sink.writeln('<div id="details"></div>');
-  }
-}
diff --git a/pkg/analysis_server/tool/instrumentation/server.dart b/pkg/analysis_server/tool/instrumentation/server.dart
index 4fd50e1..cbb0068 100644
--- a/pkg/analysis_server/tool/instrumentation/server.dart
+++ b/pkg/analysis_server/tool/instrumentation/server.dart
@@ -9,7 +9,6 @@
 import 'log/log.dart';
 import 'page/log_page.dart';
 import 'page/stats_page.dart';
-import 'page/task_page.dart';
 
 /**
  * An exception that is thrown when a request is received that cannot be
@@ -32,11 +31,6 @@
   static final String statsPath = '/stats';
 
   /**
-   * The path to the page containing statistics about the instrumentation log.
-   */
-  static final String taskPath = '/task';
-
-  /**
    * The content type for HTML responses.
    */
   static final ContentType _htmlContent =
@@ -118,8 +112,6 @@
         _writeLogPage(request, buffer);
       } else if (path == statsPath) {
         _writeStatsPage(request, buffer);
-      } else if (path == taskPath) {
-        _writeTaskPage(request, buffer);
       } else {
         _returnUnknownRequest(request);
         return;
@@ -219,22 +211,4 @@
   void _writeStatsPage(HttpRequest request, StringBuffer buffer) {
     new StatsPage(log).writePage(buffer);
   }
-
-  void _writeTaskPage(HttpRequest request, StringBuffer buffer) {
-    Map<String, String> parameterMap = getParameterMap(request);
-    String analysisStart = parameterMap['analysisStart'];
-    String start = parameterMap['start'];
-    TaskPage page = new TaskPage(log);
-    if (analysisStart == null) {
-      throw new UnknownRequest();
-    }
-    page.analysisStart = int.parse(analysisStart);
-    if (start != null) {
-      page.pageStart = int.parse(start);
-    } else {
-      page.pageStart = 0;
-    }
-    page.pageLength = 25;
-    page.writePage(buffer);
-  }
 }
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 435477a..41ef7cc 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/precedence.dart';
-
 /// Defines the AST model. The AST (Abstract Syntax Tree) model describes the
 /// syntactic (as opposed to semantic) structure of Dart code. The semantic
 /// structure of the code is modeled by the
@@ -35,6 +32,8 @@
 /// When an AST is resolved, the identifiers in the AST will be associated with
 /// the elements that they refer to and every expression in the AST will have a
 /// type associated with it.
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/precedence.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -286,7 +285,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class AssignmentExpression
-    implements Expression, MethodReferenceExpression {
+    implements NullShortableExpression, MethodReferenceExpression {
   /// Return the expression used to compute the left hand side.
   Expression get leftHandSide;
 
@@ -2178,11 +2177,6 @@
   /// is not a function-typed field formal parameter.
   FormalParameterList get parameters;
 
-  /// If the parameter is function-typed, and has the question mark, then its
-  /// function type is nullable. Having a nullable function type means that the
-  /// parameter can be null.
-  Token get question;
-
   /// Set the parameters of the function-typed parameter to the given
   /// [parameters].
   void set parameters(FormalParameterList parameters);
@@ -2193,6 +2187,11 @@
   /// Set the token representing the period to the given [token].
   void set period(Token token);
 
+  /// If the parameter is function-typed, and has the question mark, then its
+  /// function type is nullable. Having a nullable function type means that the
+  /// parameter can be null.
+  Token get question;
+
   /// Return the token representing the 'this' keyword.
   Token get thisKeyword;
 
@@ -3162,7 +3161,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class IndexExpression
-    implements Expression, MethodReferenceExpression {
+    implements NullShortableExpression, MethodReferenceExpression {
   /// Return the auxiliary elements associated with this identifier, or `null`
   /// if this identifier is not in both a getter and setter context.
   ///
@@ -4054,6 +4053,24 @@
   void set literal(Token token);
 }
 
+/// Abstract interface for expressions that may participate in null-shorting.
+abstract class NullShortableExpression implements Expression {
+  /// Returns the expression that terminates any null shorting that might occur
+  /// in this expression.  This may be called regardless of whether this
+  /// expression is itself null-aware.
+  ///
+  /// For example, the statement `a?.b[c] = d;` contains the following
+  /// null-shortable subexpressions:
+  /// - `a?.b`
+  /// - `a?.b[c]`
+  /// - `a?.b[c] = d`
+  ///
+  /// Calling [nullShortingTermination] on any of these subexpressions yields
+  /// the expression `a?.b[c] = d`, indicating that the null-shorting induced by
+  /// the `?.` causes the rest of the subexpression `a?.b[c] = d` to be skipped.
+  Expression get nullShortingTermination;
+}
+
 /// The "on" clause in a mixin declaration.
 ///
 ///    onClause ::=
@@ -4250,7 +4267,7 @@
 ///        [Expression] '.' [SimpleIdentifier]
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class PropertyAccess implements Expression {
+abstract class PropertyAccess implements NullShortableExpression {
   /// Return `true` if this expression is cascaded.
   ///
   /// If it is, then the target of this expression is not stored locally but is
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 951dfe4..29038c6 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -442,6 +442,9 @@
 abstract class ConstructorElement
     implements ClassMemberElement, ExecutableElement, ConstantEvaluationTarget {
   @override
+  ConstructorElement get declaration;
+
+  @override
   ClassElement get enclosingElement;
 
   /// Return `true` if this constructor is a const constructor.
@@ -501,6 +504,13 @@
   /// Return the analysis context in which this element is defined.
   AnalysisContext get context;
 
+  /// Return the declaration of this element. If the element is a view on an
+  /// element, e.g. a method from an interface type, with substituted type
+  /// parameters, return the corresponding element from the class, without any
+  /// substitutions. If this element is already a declaration (or a synthetic
+  /// element, e.g. a synthetic property accessor), return itself.
+  Element get declaration;
+
   /// Return the display name of this element, or `null` if this element does
   /// not have a name.
   ///
@@ -959,6 +969,9 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class ExecutableElement implements FunctionTypedElement {
+  @override
+  ExecutableElement get declaration;
+
   /// Return `true` if this executable element did not have an explicit return
   /// type specified for it in the original source. Note that if there was no
   /// explicit return type, and if the element model is fully populated, then
@@ -1051,6 +1064,9 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class FieldElement
     implements ClassMemberElement, PropertyInducingElement {
+  @override
+  FieldElement get declaration;
+
   /// Return `true` if this field was explicitly marked as being covariant.
   bool get isCovariant;
 
@@ -1327,7 +1343,10 @@
 /// be contained within an extension element.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class MethodElement implements ClassMemberElement, ExecutableElement {}
+abstract class MethodElement implements ClassMemberElement, ExecutableElement {
+  @override
+  MethodElement get declaration;
+}
 
 /// A pseudo-element that represents multiple elements defined within a single
 /// scope that have the same name. This situation is not allowed by the
@@ -1366,6 +1385,9 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class ParameterElement
     implements PromotableElement, ConstantEvaluationTarget {
+  @override
+  ParameterElement get declaration;
+
   /// Return the Dart code of the default value, or `null` if no default value.
   String get defaultValueCode;
 
@@ -1481,6 +1503,9 @@
   /// if there is no corresponding setter.
   PropertyAccessorElement get correspondingSetter;
 
+  @override
+  PropertyAccessorElement get declaration;
+
   /// Return `true` if this accessor represents a getter.
   bool get isGetter;
 
@@ -1568,6 +1593,9 @@
   DartType get bound;
 
   @override
+  TypeParameterElement get declaration;
+
+  @override
   @deprecated
   TypeParameterType get type;
 
@@ -1633,6 +1661,9 @@
   /// errors.
   DartObject get constantValue;
 
+  @override
+  VariableElement get declaration;
+
   /// Return `true` if this variable element did not have an explicit type
   /// specified for it.
   bool get hasImplicitType;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 75cf369..7313b18 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -128,6 +128,7 @@
   CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
   CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
   CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
+  CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
diff --git a/pkg/analyzer/lib/exception/exception.dart b/pkg/analyzer/lib/exception/exception.dart
index 5fd7348..e5f6335 100644
--- a/pkg/analyzer/lib/exception/exception.dart
+++ b/pkg/analyzer/lib/exception/exception.dart
@@ -68,12 +68,6 @@
   CaughtException.withMessage(this.message, this.exception, stackTrace)
       : this.stackTrace = stackTrace ?? StackTrace.current;
 
-  /**
-   * Create a [CaughtException] to wrap a prior one, adding a [message].
-   */
-  CaughtException.wrapInMessage(String message, CaughtException exception)
-      : this.withMessage(message, exception, null);
-
   @override
   String toString() {
     StringBuffer buffer = new StringBuffer();
@@ -108,3 +102,20 @@
     }
   }
 }
+
+/**
+ * A form of [CaughtException] that should be silent to users.
+ *
+ * This is still considered an exceptional situation and will be sent to crash
+ * reporting.
+ */
+class SilentException extends CaughtException {
+  SilentException(String message, exception, stackTrace)
+      : super.withMessage(message, exception, stackTrace);
+
+  /**
+   * Create a [SilentException] to wrap a [CaughtException], adding a [message].
+   */
+  SilentException.wrapInMessage(String message, CaughtException exception)
+      : this(message, exception, null);
+}
diff --git a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
index 2ac447f..5de75d8 100644
--- a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
@@ -7,38 +7,24 @@
 
 import 'package:analyzer/instrumentation/instrumentation.dart';
 
-/**
- * An [InstrumentationServer] that writes to a file.
- */
-class FileInstrumentationServer implements InstrumentationServer {
+/// An [InstrumentationLogger] that writes to a file (as opposed to an external
+/// source or in-memory source etc.)
+class FileInstrumentationLogger implements InstrumentationLogger {
   final String filePath;
   IOSink _sink;
 
-  FileInstrumentationServer(this.filePath) {
+  FileInstrumentationLogger(this.filePath) {
     File file = new File(filePath);
     _sink = file.openWrite();
   }
 
   @override
-  String get describe => "file: $filePath";
-
-  @override
-  String get sessionId => '';
-
-  @override
   void log(String message) {
     _sink.writeln(message);
   }
 
   @override
-  void logWithPriority(String message) {
-    log(message);
-  }
-
-  @override
   Future shutdown() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     await _sink.close();
     _sink = null;
   }
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index 449fb2c..c7742d2 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -2,512 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-import 'dart:convert';
-
-/**
- * A container with analysis performance constants.
- */
-class AnalysisPerformanceKind {
-  static const String FULL = 'analysis_full';
-  static const String INCREMENTAL = 'analysis_incremental';
-}
-
-/**
- * The interface used by client code to communicate with an instrumentation
- * server.
- */
-abstract class InstrumentationServer {
-  /**
-   * A user-friendly description of this instrumentation server.
-   */
-  String get describe;
-
-  /**
-   * Return the identifier used to identify the current session.
-   */
-  String get sessionId;
-
-  /**
-   * Pass the given [message] to the instrumentation server so that it will be
-   * logged with other messages.
-   *
-   * This method should be used for most logging.
-   */
-  void log(String message);
-
-  /**
-   * Pass the given [message] to the instrumentation server so that it will be
-   * logged with other messages.
-   *
-   * This method should only be used for logging high priority messages, such as
-   * exceptions that cause the server to shutdown.
-   */
-  void logWithPriority(String message);
-
-  /**
-   * Signal that the client is done communicating with the instrumentation
-   * server. This method should be invoked exactly one time and no other methods
-   * should be invoked on this instance after this method has been invoked.
-   */
-  Future shutdown();
-}
-
-/**
- * The interface used by client code to communicate with an instrumentation
- * server by wrapping an [InstrumentationServer].
- */
-class InstrumentationService {
-  /**
-   * An instrumentation service that will not log any instrumentation data.
-   */
-  static final InstrumentationService NULL_SERVICE =
-      new InstrumentationService(null);
-
-  static const String TAG_ANALYSIS_TASK = 'Task';
-  static const String TAG_ERROR = 'Err';
-  static const String TAG_EXCEPTION = 'Ex';
-  static const String TAG_FILE_READ = 'Read';
-  static const String TAG_INFO = 'Info';
-  static const String TAG_LOG_ENTRY = 'Log';
-  static const String TAG_NOTIFICATION = 'Noti';
-  static const String TAG_PERFORMANCE = 'Perf';
-  static const String TAG_PLUGIN_ERROR = 'PluginErr';
-  static const String TAG_PLUGIN_EXCEPTION = 'PluginEx';
-  static const String TAG_PLUGIN_NOTIFICATION = 'PluginNoti';
-  static const String TAG_PLUGIN_REQUEST = 'PluginReq';
-  static const String TAG_PLUGIN_RESPONSE = 'PluginRes';
-  static const String TAG_PLUGIN_TIMEOUT = 'PluginTo';
-  static const String TAG_REQUEST = 'Req';
-  static const String TAG_RESPONSE = 'Res';
-  static const String TAG_SUBPROCESS_START = 'SPStart';
-  static const String TAG_SUBPROCESS_RESULT = 'SPResult';
-  static const String TAG_VERSION = 'Ver';
-  static const String TAG_WATCH_EVENT = 'Watch';
-
-  /**
-   * The instrumentation server used to communicate with the server, or `null`
-   * if instrumentation data should not be logged.
-   */
-  InstrumentationServer _instrumentationServer;
-
-  /**
-   * Counter used to generate unique ID's for [logSubprocessStart].
-   */
-  int _subprocessCounter = 0;
-
-  /**
-   * Initialize a newly created instrumentation service to communicate with the
-   * given [_instrumentationServer].
-   */
-  InstrumentationService(this._instrumentationServer);
-
-  InstrumentationServer get instrumentationServer => _instrumentationServer;
-
-  /**
-   * Return `true` if this [InstrumentationService] was initialized with a
-   * non-`null` server (and hence instrumentation is active).
-   */
-  bool get isActive => _instrumentationServer != null;
-
-  /**
-   * Return the identifier used to identify the current session.
-   */
-  String get sessionId => _instrumentationServer?.sessionId ?? '';
-
-  /**
-   * The current time, expressed as a decimal encoded number of milliseconds.
-   */
-  String get _timestamp => new DateTime.now().millisecondsSinceEpoch.toString();
-
-  /**
-   * Log the fact that an error, described by the given [message], has occurred.
-   */
-  void logError(String message) {
-    _log(TAG_ERROR, message);
-  }
-
-  /**
-   * Log that the given non-priority [exception] was thrown, with the given
-   * [stackTrace].
-   */
-  void logException(dynamic exception, [StackTrace stackTrace]) {
-    if (_instrumentationServer != null) {
-      String message = _toString(exception);
-      String trace = _toString(stackTrace);
-      _instrumentationServer.log(_join([TAG_EXCEPTION, message, trace]));
-    }
-  }
-
-  /**
-   * Log that the contents of the file with the given [path] were read. The file
-   * had the given [content] and [modificationTime].
-   */
-  void logFileRead(String path, int modificationTime, String content) {
-    if (_instrumentationServer != null) {
-      String timeStamp = _toString(modificationTime);
-      _instrumentationServer
-          .log(_join([TAG_FILE_READ, path, timeStamp, content]));
-    }
-  }
-
-  /**
-   * Log unstructured text information for debugging purposes.
-   */
-  void logInfo(String message, [dynamic exception]) =>
-      _log(TAG_INFO, message + (exception == null ? "" : _toString(exception)));
-
-  /**
-   * Log that a log entry that was written to the analysis engine's log. The log
-   * entry has the given [level] and [message], and was created at the given
-   * [time].
-   */
-  void logLogEntry(String level, DateTime time, String message,
-      Object exception, StackTrace stackTrace) {
-    if (_instrumentationServer != null) {
-      String timeStamp =
-          time == null ? 'null' : time.millisecondsSinceEpoch.toString();
-      String exceptionText = exception.toString();
-      String stackTraceText = stackTrace.toString();
-      _instrumentationServer.log(_join([
-        TAG_LOG_ENTRY,
-        level,
-        timeStamp,
-        message,
-        exceptionText,
-        stackTraceText
-      ]));
-    }
-  }
-
-  /**
-   * Log that a notification has been sent to the client.
-   */
-  void logNotification(String notification) {
-    _log(TAG_NOTIFICATION, notification);
-  }
-
-  /**
-   * Log the given performance fact.
-   */
-  void logPerformance(String kind, Stopwatch sw, String message) {
-    sw.stop();
-    String elapsed = sw.elapsedMilliseconds.toString();
-    if (_instrumentationServer != null) {
-      _instrumentationServer
-          .log(_join([TAG_PERFORMANCE, kind, elapsed, message]));
-    }
-  }
-
-  /**
-   * Log the fact that an error, described by the given [message], was reported
-   * by the given [plugin].
-   */
-  void logPluginError(
-      PluginData plugin, String code, String message, String stackTrace) {
-    if (_instrumentationServer != null) {
-      List<String> fields = <String>[
-        TAG_PLUGIN_ERROR,
-        code,
-        message,
-        stackTrace
-      ];
-      plugin.addToFields(fields);
-      _instrumentationServer.log(_join(fields));
-    }
-  }
-
-  /**
-   * Log that the given non-priority [exception] was thrown, with the given
-   * [stackTrace] by the given [plugin].
-   */
-  void logPluginException(
-      PluginData plugin, dynamic exception, StackTrace stackTrace) {
-    if (_instrumentationServer != null) {
-      List<String> fields = <String>[
-        TAG_PLUGIN_EXCEPTION,
-        _toString(exception),
-        _toString(stackTrace)
-      ];
-      plugin.addToFields(fields);
-      _instrumentationServer.log(_join(fields));
-    }
-  }
-
-  void logPluginNotification(String pluginId, String notification) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer.log(
-          _join([TAG_PLUGIN_NOTIFICATION, notification, pluginId, '', '']));
-    }
-  }
-
-  void logPluginRequest(String pluginId, String request) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer
-          .log(_join([TAG_PLUGIN_REQUEST, request, pluginId, '', '']));
-    }
-  }
-
-  void logPluginResponse(String pluginId, String response) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer
-          .log(_join([TAG_PLUGIN_RESPONSE, response, pluginId, '', '']));
-    }
-  }
-
-  /**
-   * Log that the given [plugin] took too long to execute the given [request].
-   * This doesn't necessarily imply that there is a problem with the plugin,
-   * only that this particular response was not included in the data returned
-   * to the client.
-   */
-  void logPluginTimeout(PluginData plugin, String request) {
-    if (_instrumentationServer != null) {
-      List<String> fields = <String>[TAG_PLUGIN_TIMEOUT, request];
-      plugin.addToFields(fields);
-      _instrumentationServer.log(_join(fields));
-    }
-  }
-
-  /**
-   * Log that the given priority [exception] was thrown, with the given
-   * [stackTrace].
-   */
-  void logPriorityException(dynamic exception, StackTrace stackTrace) {
-    if (_instrumentationServer != null) {
-      String message = _toString(exception);
-      String trace = _toString(stackTrace);
-      _instrumentationServer
-          .logWithPriority(_join([TAG_EXCEPTION, message, trace]));
-    }
-  }
-
-  /**
-   * Log that a request has been sent to the client.
-   */
-  void logRequest(String request) {
-    _log(TAG_REQUEST, request);
-  }
-
-  /**
-   * Log that a response has been sent to the client.
-   */
-  void logResponse(String response) {
-    _log(TAG_RESPONSE, response);
-  }
-
-  /**
-   * Log the result of executing a subprocess.  [subprocessId] should be the
-   * unique ID returned by [logSubprocessStart].
-   */
-  void logSubprocessResult(
-      int subprocessId, int exitCode, String stdout, String stderr) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer.log(_join([
-        TAG_SUBPROCESS_RESULT,
-        subprocessId.toString(),
-        exitCode.toString(),
-        json.encode(stdout),
-        json.encode(stderr)
-      ]));
-    }
-  }
-
-  /**
-   * Log that the given subprocess is about to be executed.  Returns a unique
-   * identifier that can be used to identify the subprocess for later log
-   * entries.
-   */
-  int logSubprocessStart(
-      String executablePath, List<String> arguments, String workingDirectory) {
-    int subprocessId = _subprocessCounter++;
-    if (_instrumentationServer != null) {
-      _instrumentationServer.log(_join([
-        TAG_SUBPROCESS_START,
-        subprocessId.toString(),
-        executablePath,
-        workingDirectory,
-        json.encode(arguments)
-      ]));
-    }
-    return subprocessId;
-  }
-
-  /**
-   * Signal that the client has started analysis server.
-   * This method should be invoked exactly one time.
-   */
-  void logVersion(String uuid, String clientId, String clientVersion,
-      String serverVersion, String sdkVersion) {
-    String normalize(String value) =>
-        value != null && value.isNotEmpty ? value : 'unknown';
-
-    if (_instrumentationServer != null) {
-      _instrumentationServer.logWithPriority(_join([
-        TAG_VERSION,
-        uuid,
-        normalize(clientId),
-        normalize(clientVersion),
-        serverVersion,
-        sdkVersion
-      ]));
-    }
-  }
-
-  /**
-   * Log that the file system watcher sent an event. The [folderPath] is the
-   * path to the folder containing the changed file, the [filePath] is the path
-   * of the file that changed, and the [changeType] indicates what kind of
-   * change occurred.
-   */
-  void logWatchEvent(String folderPath, String filePath, String changeType) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer
-          .log(_join([TAG_WATCH_EVENT, folderPath, filePath, changeType]));
-    }
-  }
-
-  /**
-   * Signal that the client is done communicating with the instrumentation
-   * server. This method should be invoked exactly one time and no other methods
-   * should be invoked on this instance after this method has been invoked.
-   */
-  Future shutdown() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    if (_instrumentationServer != null) {
-      await _instrumentationServer.shutdown();
-      _instrumentationServer = null;
-    }
-  }
-
-  /**
-   * Write an escaped version of the given [field] to the given [buffer].
-   */
-  void _escape(StringBuffer buffer, String field) {
-    int index = field.indexOf(':');
-    if (index < 0) {
-      buffer.write(field);
-      return;
-    }
-    int start = 0;
-    while (index >= 0) {
-      buffer.write(field.substring(start, index));
-      buffer.write('::');
-      start = index + 1;
-      index = field.indexOf(':', start);
-    }
-    buffer.write(field.substring(start));
-  }
-
-  /**
-   * Return the result of joining the values of the given fields, escaping the
-   * separator character by doubling it.
-   */
-  String _join(List<String> fields) {
-    StringBuffer buffer = new StringBuffer();
-    buffer.write(_timestamp);
-    int length = fields.length;
-    for (int i = 0; i < length; i++) {
-      buffer.write(':');
-      _escape(buffer, fields[i] ?? 'null');
-    }
-    return buffer.toString();
-  }
-
-  /**
-   * Log the given message with the given tag.
-   */
-  void _log(String tag, String message) {
-    if (_instrumentationServer != null) {
-      _instrumentationServer.log(_join([tag, message]));
-    }
-  }
-
-  /**
-   * Convert the given [object] to a string.
-   */
-  String _toString(Object object) {
-    if (object == null) {
-      return 'null';
-    }
-    return object.toString();
-  }
-}
-
-/**
- * An [InstrumentationServer] that sends messages to multiple instances.
- */
-class MulticastInstrumentationServer implements InstrumentationServer {
-  final List<InstrumentationServer> _servers;
-
-  MulticastInstrumentationServer(this._servers);
-
-  @override
-  String get describe {
-    return _servers
-        .map((InstrumentationServer server) => server.describe)
-        .join("\n");
-  }
-
-  @override
-  String get sessionId => _servers[0].sessionId;
-
-  @override
-  void log(String message) {
-    for (InstrumentationServer server in _servers) {
-      server.log(message);
-    }
-  }
-
-  @override
-  void logWithPriority(String message) {
-    for (InstrumentationServer server in _servers) {
-      server.logWithPriority(message);
-    }
-  }
-
-  @override
-  Future shutdown() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    for (InstrumentationServer server in _servers) {
-      await server.shutdown();
-    }
-  }
-}
-
-/**
- * Information about a plugin.
- */
-class PluginData {
-  /**
-   * The id used to uniquely identify the plugin.
-   */
-  final String pluginId;
-
-  /**
-   * The name of the plugin.
-   */
-  final String name;
-
-  /**
-   * The version of the plugin.
-   */
-  final String version;
-
-  /**
-   * Initialize a newly created set of data about a plugin.
-   */
-  PluginData(this.pluginId, this.name, this.version);
-
-  /**
-   * Add the information about the plugin to the list of [fields] to be sent to
-   * the instrumentation server.
-   */
-  void addToFields(List<String> fields) {
-    fields.add(pluginId);
-    fields.add(name ?? '');
-    fields.add(version ?? '');
-  }
-}
+export 'package:analyzer/instrumentation/log_adapter.dart';
+export 'package:analyzer/instrumentation/logger.dart';
+export 'package:analyzer/instrumentation/multicast_service.dart';
+export 'package:analyzer/instrumentation/noop_service.dart';
+export 'package:analyzer/instrumentation/plugin_data.dart';
+export 'package:analyzer/instrumentation/service.dart';
diff --git a/pkg/analyzer/lib/instrumentation/log_adapter.dart b/pkg/analyzer/lib/instrumentation/log_adapter.dart
new file mode 100644
index 0000000..ff85100
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/log_adapter.dart
@@ -0,0 +1,217 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/instrumentation/logger.dart';
+import 'package:analyzer/instrumentation/plugin_data.dart';
+import 'package:analyzer/instrumentation/service.dart';
+
+/// A class to adapt an [InstrumentationService] into a log using an [InstrumentationLogger].
+class InstrumentationLogAdapter implements InstrumentationService {
+  static const String TAG_ERROR = 'Err';
+  static const String TAG_EXCEPTION = 'Ex';
+  static const String TAG_INFO = 'Info';
+  static const String TAG_LOG_ENTRY = 'Log';
+  static const String TAG_NOTIFICATION = 'Noti';
+  static const String TAG_PLUGIN_ERROR = 'PluginErr';
+  static const String TAG_PLUGIN_EXCEPTION = 'PluginEx';
+  static const String TAG_PLUGIN_NOTIFICATION = 'PluginNoti';
+  static const String TAG_PLUGIN_REQUEST = 'PluginReq';
+  static const String TAG_PLUGIN_RESPONSE = 'PluginRes';
+  static const String TAG_PLUGIN_TIMEOUT = 'PluginTo';
+  static const String TAG_REQUEST = 'Req';
+  static const String TAG_RESPONSE = 'Res';
+  static const String TAG_VERSION = 'Ver';
+  static const String TAG_WATCH_EVENT = 'Watch';
+
+  /// A logger used to log instrumentation in string format.
+  InstrumentationLogger _instrumentationLogger;
+
+  /// Initialize a newly created instrumentation service to communicate with the
+  /// given [_instrumentationLogger].
+  InstrumentationLogAdapter(this._instrumentationLogger);
+
+  /// The current time, expressed as a decimal encoded number of milliseconds.
+  String get _timestamp => new DateTime.now().millisecondsSinceEpoch.toString();
+
+  @override
+  void logError(String message) => _log(TAG_ERROR, message);
+
+  @override
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    if (_instrumentationLogger != null) {
+      String message = _toString(exception);
+      String trace = _toString(stackTrace);
+      _instrumentationLogger.log(_join([TAG_EXCEPTION, message, trace]));
+    }
+  }
+
+  @override
+  void logInfo(String message, [dynamic exception]) =>
+      _log(TAG_INFO, message + (exception == null ? "" : exception.toString()));
+
+  @override
+  void logLogEntry(String level, DateTime time, String message,
+      Object exception, StackTrace stackTrace) {
+    if (_instrumentationLogger != null) {
+      String timeStamp =
+          time == null ? 'null' : time.millisecondsSinceEpoch.toString();
+      String exceptionText = exception.toString();
+      String stackTraceText = stackTrace.toString();
+      _instrumentationLogger.log(_join([
+        TAG_LOG_ENTRY,
+        level,
+        timeStamp,
+        message,
+        exceptionText,
+        stackTraceText
+      ]));
+    }
+  }
+
+  @override
+  void logNotification(String notification) =>
+      _log(TAG_NOTIFICATION, notification);
+
+  @override
+  void logPluginError(
+      PluginData plugin, String code, String message, String stackTrace) {
+    if (_instrumentationLogger != null) {
+      List<String> fields = <String>[
+        TAG_PLUGIN_ERROR,
+        code,
+        message,
+        stackTrace
+      ];
+      plugin.addToFields(fields);
+      _instrumentationLogger.log(_join(fields));
+    }
+  }
+
+  @override
+  void logPluginException(
+      PluginData plugin, dynamic exception, StackTrace stackTrace) {
+    if (_instrumentationLogger != null) {
+      List<String> fields = <String>[
+        TAG_PLUGIN_EXCEPTION,
+        _toString(exception),
+        _toString(stackTrace)
+      ];
+      plugin.addToFields(fields);
+      _instrumentationLogger.log(_join(fields));
+    }
+  }
+
+  @override
+  void logPluginNotification(String pluginId, String notification) {
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger.log(
+          _join([TAG_PLUGIN_NOTIFICATION, notification, pluginId, '', '']));
+    }
+  }
+
+  @override
+  void logPluginRequest(String pluginId, String request) {
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger
+          .log(_join([TAG_PLUGIN_REQUEST, request, pluginId, '', '']));
+    }
+  }
+
+  @override
+  void logPluginResponse(String pluginId, String response) {
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger
+          .log(_join([TAG_PLUGIN_RESPONSE, response, pluginId, '', '']));
+    }
+  }
+
+  @override
+  void logPluginTimeout(PluginData plugin, String request) {
+    if (_instrumentationLogger != null) {
+      List<String> fields = <String>[TAG_PLUGIN_TIMEOUT, request];
+      plugin.addToFields(fields);
+      _instrumentationLogger.log(_join(fields));
+    }
+  }
+
+  @override
+  void logRequest(String request) => _log(TAG_REQUEST, request);
+
+  @override
+  void logResponse(String response) => _log(TAG_RESPONSE, response);
+
+  @override
+  void logVersion(String uuid, String clientId, String clientVersion,
+      String serverVersion, String sdkVersion) {
+    String normalize(String value) =>
+        value != null && value.isNotEmpty ? value : 'unknown';
+
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger.log(_join([
+        TAG_VERSION,
+        uuid,
+        normalize(clientId),
+        normalize(clientVersion),
+        serverVersion,
+        sdkVersion
+      ]));
+    }
+  }
+
+  @override
+  void logWatchEvent(String folderPath, String filePath, String changeType) {
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger
+          .log(_join([TAG_WATCH_EVENT, folderPath, filePath, changeType]));
+    }
+  }
+
+  @override
+  Future<void> shutdown() => _instrumentationLogger.shutdown();
+
+  /// Write an escaped version of the given [field] to the given [buffer].
+  void _escape(StringBuffer buffer, String field) {
+    int index = field.indexOf(':');
+    if (index < 0) {
+      buffer.write(field);
+      return;
+    }
+    int start = 0;
+    while (index >= 0) {
+      buffer.write(field.substring(start, index));
+      buffer.write('::');
+      start = index + 1;
+      index = field.indexOf(':', start);
+    }
+    buffer.write(field.substring(start));
+  }
+
+  /// Return the result of joining the values of the given fields, escaping the
+  /// separator character by doubling it.
+  String _join(List<String> fields) {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write(_timestamp);
+    int length = fields.length;
+    for (int i = 0; i < length; i++) {
+      buffer.write(':');
+      _escape(buffer, fields[i] ?? 'null');
+    }
+    return buffer.toString();
+  }
+
+  /// Log the given message with the given tag.
+  void _log(String tag, String message) {
+    if (_instrumentationLogger != null) {
+      _instrumentationLogger.log(_join([tag, message]));
+    }
+  }
+
+  /// Convert the given [object] to a string.
+  String _toString(Object object) {
+    if (object == null) {
+      return 'null';
+    }
+    return object.toString();
+  }
+}
diff --git a/pkg/analyzer/lib/instrumentation/logger.dart b/pkg/analyzer/lib/instrumentation/logger.dart
new file mode 100644
index 0000000..d1eaea4
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/logger.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// The interface used by client code to communicate with an instrumentation
+/// server.
+abstract class InstrumentationLogger {
+  /// Pass the given [message] to the instrumentation server so that it will be
+  /// logged with other messages.
+  ///
+  /// This method should be used for most logging.
+  void log(String message);
+
+  /// Shut down this logger, including file handles etc.
+  Future<void> shutdown();
+}
diff --git a/pkg/analyzer/lib/instrumentation/multicast_service.dart b/pkg/analyzer/lib/instrumentation/multicast_service.dart
new file mode 100644
index 0000000..0d4fa40
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/multicast_service.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/instrumentation/plugin_data.dart';
+import 'package:analyzer/instrumentation/service.dart';
+
+/// An [InstrumentationService] that sends messages to multiple services.
+class MulticastInstrumentationService implements InstrumentationService {
+  final List<InstrumentationService> _services;
+
+  MulticastInstrumentationService(this._services);
+
+  @override
+  void logError(String message) {
+    _services.forEach((s) => s.logError(message));
+  }
+
+  @override
+  void logException(exception, [StackTrace stackTrace]) {
+    _services.forEach((s) => s.logException(exception, stackTrace));
+  }
+
+  @override
+  void logInfo(String message, [dynamic exception]) {
+    _services.forEach((s) => s.logInfo(message, exception));
+  }
+
+  @override
+  void logLogEntry(String level, DateTime time, String message,
+      Object exception, StackTrace stackTrace) {
+    _services.forEach(
+        (s) => s.logLogEntry(level, time, message, exception, stackTrace));
+  }
+
+  @override
+  void logNotification(String notification) {
+    _services.forEach((s) => s.logNotification(notification));
+  }
+
+  @override
+  void logPluginError(
+      PluginData plugin, String code, String message, String stackTrace) {
+    _services
+        .forEach((s) => s.logPluginError(plugin, code, message, stackTrace));
+  }
+
+  @override
+  void logPluginException(PluginData plugin, exception, StackTrace stackTrace) {
+    _services
+        .forEach((s) => s.logPluginException(plugin, exception, stackTrace));
+  }
+
+  @override
+  void logPluginNotification(String pluginId, String notification) {
+    _services.forEach((s) => s.logPluginNotification(pluginId, notification));
+  }
+
+  @override
+  void logPluginRequest(String pluginId, String request) {
+    _services.forEach((s) => s.logPluginRequest(pluginId, request));
+  }
+
+  @override
+  void logPluginResponse(String pluginId, String response) {
+    _services.forEach((s) => s.logPluginResponse(pluginId, response));
+  }
+
+  @override
+  void logPluginTimeout(PluginData plugin, String request) {
+    _services.forEach((s) => s.logPluginTimeout(plugin, request));
+  }
+
+  @override
+  void logRequest(String request) {
+    _services.forEach((s) => s.logRequest(request));
+  }
+
+  @override
+  void logResponse(String response) {
+    _services.forEach((s) => s.logResponse(response));
+  }
+
+  @override
+  void logVersion(String uuid, String clientId, String clientVersion,
+      String serverVersion, String sdkVersion) {
+    _services.forEach((s) =>
+        s.logVersion(uuid, clientId, clientVersion, serverVersion, sdkVersion));
+  }
+
+  @override
+  void logWatchEvent(String folderPath, String filePath, String changeType) {
+    _services.forEach((s) => s.logWatchEvent(folderPath, filePath, changeType));
+  }
+
+  @override
+  Future<void> shutdown() {
+    return Future.wait(_services.map((s) => s.shutdown()));
+  }
+}
diff --git a/pkg/analyzer/lib/instrumentation/noop_service.dart b/pkg/analyzer/lib/instrumentation/noop_service.dart
new file mode 100644
index 0000000..c550863
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/noop_service.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/instrumentation/plugin_data.dart';
+import 'package:analyzer/instrumentation/service.dart';
+
+/// An implementation of [InstrumentationService] which noops instead of saving
+/// instrumentation logs.
+class NoopInstrumentationService implements InstrumentationService {
+  @override
+  void logError(String message) {}
+
+  @override
+  void logException(dynamic exception, [StackTrace stackTrace]) {}
+
+  @override
+  void logInfo(String message, [dynamic exception]) {}
+
+  @override
+  void logLogEntry(String level, DateTime time, String message,
+      Object exception, StackTrace stackTrace) {}
+
+  @override
+  void logNotification(String notification) {}
+
+  @override
+  void logPluginError(
+      PluginData plugin, String code, String message, String stackTrace) {}
+
+  @override
+  void logPluginException(
+      PluginData plugin, dynamic exception, StackTrace stackTrace) {}
+
+  @override
+  void logPluginNotification(String pluginId, String notification) {}
+
+  @override
+  void logPluginRequest(String pluginId, String request) {}
+
+  @override
+  void logPluginResponse(String pluginId, String response) {}
+
+  @override
+  void logPluginTimeout(PluginData plugin, String request) {}
+
+  @override
+  void logRequest(String request) {}
+
+  @override
+  void logResponse(String response) {}
+
+  @override
+  void logVersion(String uuid, String clientId, String clientVersion,
+      String serverVersion, String sdkVersion) {}
+
+  @override
+  void logWatchEvent(String folderPath, String filePath, String changeType) {}
+
+  @override
+  Future<void> shutdown() async {}
+}
diff --git a/pkg/analyzer/lib/instrumentation/plugin_data.dart b/pkg/analyzer/lib/instrumentation/plugin_data.dart
new file mode 100644
index 0000000..bc4c3e5
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/plugin_data.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Information about a plugin.
+class PluginData {
+  /// The id used to uniquely identify the plugin.
+  final String pluginId;
+
+  /// The name of the plugin.
+  final String name;
+
+  /// The version of the plugin.
+  final String version;
+
+  /// Initialize a newly created set of data about a plugin.
+  PluginData(this.pluginId, this.name, this.version);
+
+  /// Add the information about the plugin to the list of [fields] to be sent to
+  /// the instrumentation server.
+  void addToFields(List<String> fields) {
+    fields.add(pluginId);
+    fields.add(name ?? '');
+    fields.add(version ?? '');
+  }
+}
diff --git a/pkg/analyzer/lib/instrumentation/service.dart b/pkg/analyzer/lib/instrumentation/service.dart
new file mode 100644
index 0000000..59d9a2a
--- /dev/null
+++ b/pkg/analyzer/lib/instrumentation/service.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/instrumentation/noop_service.dart';
+import 'package:analyzer/instrumentation/plugin_data.dart';
+
+/// The interface used by client code to communicate with an instrumentation
+/// service of some kind.
+abstract class InstrumentationService {
+  /// A service which does not log or otherwise record instrumentation.
+  static final NULL_SERVICE = NoopInstrumentationService();
+
+  /// Log the fact that an error, described by the given [message], has occurred.
+  void logError(String message);
+
+  /// Log that the given non-priority [exception] was thrown, with the given
+  /// [stackTrace].
+  void logException(dynamic exception, [StackTrace stackTrace]);
+
+  /// Log unstructured text information for debugging purposes.
+  void logInfo(String message, [dynamic exception]);
+
+  /// Log that a log entry that was written to the analysis engine's log. The log
+  /// entry has the given [level] and [message], and was created at the given
+  /// [time].
+  void logLogEntry(String level, DateTime time, String message,
+      Object exception, StackTrace stackTrace);
+
+  /// Log that a notification has been sent to the client.
+  void logNotification(String notification);
+
+  /// Log the fact that an error, described by the given [message], was reported
+  /// by the given [plugin].
+  void logPluginError(
+      PluginData plugin, String code, String message, String stackTrace);
+
+  /// Log that the given non-priority [exception] was thrown, with the given
+  /// [stackTrace] by the given [plugin].
+  void logPluginException(
+      PluginData plugin, dynamic exception, StackTrace stackTrace);
+
+  /// Log a notification from the plugin with the given [pluginId].
+  void logPluginNotification(String pluginId, String notification);
+
+  /// Log a request to the plugin with the given [pluginId].
+  void logPluginRequest(String pluginId, String request);
+
+  /// Log a response from the plugin with the given [pluginId].
+  void logPluginResponse(String pluginId, String response);
+
+  /// Log that the given [plugin] took too long to execute the given [request].
+  /// This doesn't necessarily imply that there is a problem with the plugin,
+  /// only that this particular response was not included in the data returned
+  /// to the client.
+  void logPluginTimeout(PluginData plugin, String request);
+
+  /// Log that a request has been sent to the client.
+  void logRequest(String request);
+
+  /// Log that a response has been sent to the client.
+  void logResponse(String response);
+
+  /// Signal that the client has started analysis server.
+  /// This method should be invoked exactly one time.
+  void logVersion(String uuid, String clientId, String clientVersion,
+      String serverVersion, String sdkVersion);
+
+  /// Log that the file system watcher sent an event. The [folderPath] is the
+  /// path to the folder containing the changed file, the [filePath] is the path
+  /// of the file that changed, and the [changeType] indicates what kind of
+  /// change occurred.
+  void logWatchEvent(String folderPath, String filePath, String changeType);
+
+  /// Shut down this service.
+  Future<void> shutdown();
+}
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 05cbe28..dd56ff4b 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -110,8 +110,9 @@
         return _internalResolveUri(null, uri);
       }
     } catch (exception, stackTrace) {
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.withMessage(
+          new SilentException(
               "Could not resolve URI: $absoluteUri", exception, stackTrace));
     }
     return null;
@@ -123,8 +124,9 @@
       try {
         return _internalResolveUri(null, absoluteUri);
       } on AnalysisException catch (exception, stackTrace) {
+        // TODO(39284): should this exception be silent?
         AnalysisEngine.instance.instrumentationService.logException(
-            new CaughtException.withMessage(
+            new SilentException(
                 "Could not resolve URI: $absoluteUri", exception, stackTrace));
       }
     }
@@ -144,8 +146,9 @@
     } catch (exception, stackTrace) {
       String containingFullName =
           containingSource != null ? containingSource.fullName : '<null>';
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService
-          .logException(new CaughtException.withMessage(
+          .logException(new SilentException(
               "Could not resolve URI ($containedUri) "
               "relative to source ($containingFullName)",
               exception,
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 75e72e1a..bdbcc87 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -89,7 +89,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 88;
+  static const int DATA_VERSION = 89;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 02b4b51..e2856fc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 
@@ -338,9 +337,7 @@
    * [_ElementInfo.id] is filled by [assemble] during final sorting.
    */
   _ElementInfo _getElementInfo(Element element) {
-    if (element is Member) {
-      element = (element as Member).baseElement;
-    }
+    element = element.declaration;
     return elementMap.putIfAbsent(element, () {
       CompilationUnitElement unitElement = getUnitElement(element);
       int unitId = _getUnitId(unitElement);
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index dc4cc41..1eadd80 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/dart/analysis/index.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:collection/collection.dart';
 
@@ -384,13 +383,8 @@
 
   Future<List<SearchResult>> _searchReferences_Function(
       Element element, SearchedFiles searchedFiles) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    if (element is Member) {
-      element = (element as Member).baseElement;
-    }
     List<SearchResult> results = <SearchResult>[];
-    await _addResults(results, element, searchedFiles, const {
+    await _addResults(results, element.declaration, searchedFiles, const {
       IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
       IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
     });
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
index 5bd8db5..ec869da 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.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.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
 
@@ -59,6 +61,12 @@
     addToken(node.rightBracket);
   }
 
+  void addFeatureSet(FeatureSet featureSet) {
+    for (var feature in ExperimentStatus.knownFeatures.values) {
+      signature.addBool(featureSet.isEnabled(feature));
+    }
+  }
+
   void addFunctionBodyModifiers(FunctionBody node) {
     signature.addBool(node.isSynchronous);
     signature.addBool(node.isGenerator);
@@ -119,6 +127,8 @@
   }
 
   void compute(CompilationUnit unit) {
+    addFeatureSet(unit.featureSet);
+
     signature.addInt(unit.directives.length);
     unit.directives.forEach(addNode);
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index de7f57f..b6c1232 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -615,6 +615,7 @@
 ///    assignmentExpression ::=
 ///        [Expression] operator [Expression]
 class AssignmentExpressionImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
     implements AssignmentExpression {
   /// The expression used to compute the left hand side.
   ExpressionImpl _leftHandSide;
@@ -647,8 +648,9 @@
       } else {
         message = "The right-hand size is null";
       }
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException(new AnalysisException(message), null),
+          new SilentException(message, new AnalysisException(message), null),
           StackTrace.current);
     }
     _leftHandSide = _becomeParentOf(leftHandSide);
@@ -686,6 +688,9 @@
     _rightHandSide = _becomeParentOf(expression as ExpressionImpl);
   }
 
+  @override
+  AstNode get _nullShortingExtensionCandidate => parent;
+
   /// If the AST structure has been resolved, and the function being invoked is
   /// known based on static type information, then return the parameter element
   /// representing the parameter to which the value of the right operand will be
@@ -726,6 +731,10 @@
     _leftHandSide?.accept(visitor);
     _rightHandSide?.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression child) =>
+      identical(child, _leftHandSide);
 }
 
 /// A node in the AST structure for a Dart program.
@@ -5750,7 +5759,9 @@
 ///
 ///    indexExpression ::=
 ///        [Expression] '[' [Expression] ']'
-class IndexExpressionImpl extends ExpressionImpl implements IndexExpression {
+class IndexExpressionImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
+    implements IndexExpression {
   /// The expression used to compute the object being indexed, or `null` if this
   /// index expression is part of a cascade expression.
   ExpressionImpl _target;
@@ -5861,6 +5872,9 @@
     _target = _becomeParentOf(expression as ExpressionImpl);
   }
 
+  @override
+  AstNode get _nullShortingExtensionCandidate => parent;
+
   /// If the AST structure has been resolved, and the function being invoked is
   /// known based on static type information, then return the parameter element
   /// representing the parameter to which the value of the index expression will
@@ -5912,6 +5926,9 @@
     _target?.accept(visitor);
     _index?.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression child) => identical(child, _target);
 }
 
 /// An instance creation expression.
@@ -7718,6 +7735,33 @@
   }
 }
 
+/// Mixin that can be used to implement [NullShortableExpression].
+mixin NullShortableExpressionImpl implements NullShortableExpression {
+  @override
+  Expression get nullShortingTermination {
+    var result = this;
+    while (true) {
+      var parent = result._nullShortingExtensionCandidate;
+      if (parent is NullShortableExpressionImpl &&
+          parent._extendsNullShorting(result)) {
+        result = parent;
+      } else {
+        return result;
+      }
+    }
+  }
+
+  /// Gets the ancestor of this node to which null-shorting might be extended.
+  /// Usually this is just the node's parent, however if `this` is the base of
+  /// a cascade section, it will be the cascade expression itself, which may be
+  /// a more distant ancestor.
+  AstNode get _nullShortingExtensionCandidate;
+
+  /// Indicates whether the effect of any null-shorting within [descendant]
+  /// (which should be a descendant of `this`) should extend to include `this`.
+  bool _extendsNullShorting(Expression descendant);
+}
+
 /// The "on" clause in a mixin declaration.
 ///
 ///    onClause ::=
@@ -8184,7 +8228,9 @@
 ///
 ///    propertyAccess ::=
 ///        [Expression] '.' [SimpleIdentifier]
-class PropertyAccessImpl extends ExpressionImpl implements PropertyAccess {
+class PropertyAccessImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
+    implements PropertyAccess {
   /// The expression computing the object defining the property being accessed.
   ExpressionImpl _target;
 
@@ -8266,6 +8312,9 @@
   }
 
   @override
+  AstNode get _nullShortingExtensionCandidate => parent;
+
+  @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitPropertyAccess(this);
 
   @override
@@ -8273,6 +8322,9 @@
     _target?.accept(visitor);
     _propertyName?.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression child) => identical(child, _target);
 }
 
 /// The invocation of a constructor in the same class from within a
@@ -9969,11 +10021,17 @@
 /// A type parameter.
 ///
 ///    typeParameter ::=
-///        [SimpleIdentifier] ('extends' [TypeName])?
+///        typeParameterVariance? [SimpleIdentifier] ('extends' [TypeName])?
+///
+///    typeParameterVariance ::= 'out' | 'inout' | 'in'
 class TypeParameterImpl extends DeclarationImpl implements TypeParameter {
   /// The name of the type parameter.
   SimpleIdentifierImpl _name;
 
+  /// The token representing the variance modifier keyword, or `null` if
+  /// there is no explicit variance modifier, meaning legacy covariance.
+  Token varianceKeyword;
+
   /// The token representing the 'extends' keyword, or `null` if there is no
   /// explicit upper bound.
   Token extendsKeyword;
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 5d745b6..95d8752 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -2475,9 +2475,9 @@
       buffer.write(currentNode.runtimeType);
       currentNode = currentNode.parent;
     }
+    // TODO(39284): should this exception be silent?
     AnalysisEngine.instance.instrumentationService.logException(
-        new CaughtException.withMessage(
-            buffer.toString(), exception, stackTrace));
+        new SilentException(buffer.toString(), exception, stackTrace));
   }
 }
 
@@ -2531,8 +2531,9 @@
     try {
       node.accept(this);
     } catch (exception, stackTrace) {
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.withMessage(
+          new SilentException(
               "Unable to locate element at offset ($_startOffset - $_endOffset)",
               exception,
               stackTrace));
@@ -2571,8 +2572,9 @@
     } catch (exception, stackTrace) {
       // Ignore the exception and proceed in order to visit the rest of the
       // structure.
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.withMessage(
+          new SilentException(
               "Exception caught while traversing an AST structure.",
               exception,
               stackTrace));
@@ -2631,8 +2633,9 @@
     try {
       node.accept(this);
     } catch (exception, stackTrace) {
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.withMessage(
+          new SilentException(
               "Unable to locate element at offset ($_startOffset - $_endOffset)",
               exception,
               stackTrace));
@@ -2671,8 +2674,9 @@
     } catch (exception, stackTrace) {
       // Ignore the exception and proceed in order to visit the rest of the
       // structure.
+      // TODO(39284): should this exception be silent?
       AnalysisEngine.instance.instrumentationService.logException(
-          new CaughtException.withMessage(
+          new SilentException(
               "Exception caught while traversing an AST structure.",
               exception,
               stackTrace));
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 4fa3e1f..dda42f3 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -268,7 +268,7 @@
       ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
     ReferenceFinder referenceFinder = new ReferenceFinder(callback);
     if (constant is ConstructorElement) {
-      constant = getConstructorImpl(constant);
+      constant = (constant as ConstructorElement).declaration;
     }
     if (constant is VariableElementImpl) {
       Expression initializer = constant.constantInitializer;
@@ -281,7 +281,7 @@
             getConstRedirectedConstructor(constant);
         if (redirectedConstructor != null) {
           ConstructorElement redirectedConstructorBase =
-              getConstructorImpl(redirectedConstructor);
+              redirectedConstructor?.declaration;
           callback(redirectedConstructorBase);
           return;
         } else if (constant.isFactory) {
@@ -314,7 +314,7 @@
               (constant.returnType as InterfaceType).superclass;
           if (superclass != null && !superclass.isObject) {
             ConstructorElement unnamedConstructor =
-                getConstructorImpl(superclass.element.unnamedConstructor);
+                superclass.element.unnamedConstructor?.declaration;
             if (unnamedConstructor != null) {
               callback(unnamedConstructor);
             }
@@ -422,7 +422,7 @@
       return null;
     }
 
-    if (!getConstructorImpl(constructor).isCycleFree) {
+    if (!(constructor.declaration as ConstructorElementImpl).isCycleFree) {
       // It's not safe to evaluate this constructor, so bail out.
       // TODO(paulberry): ensure that a reasonable error message is produced
       // in this case, as well as other cases involving constant expression
@@ -519,7 +519,7 @@
       // it an unknown value will suppress further errors.
       return new DartObjectImpl.validWithUnknownValue(definingClass);
     }
-    ConstructorElementImpl constructorBase = getConstructorImpl(constructor);
+    ConstructorElementImpl constructorBase = constructor.declaration;
     validator.beforeGetConstantInitializers(constructorBase);
     List<ConstructorInitializer> initializers =
         constructorBase.constantInitializers;
@@ -581,10 +581,7 @@
 
     for (int i = 0; i < parameterCount; i++) {
       ParameterElement parameter = parameters[i];
-      ParameterElement baseParameter = parameter;
-      while (baseParameter is ParameterMember) {
-        baseParameter = (baseParameter as ParameterMember).baseElement;
-      }
+      ParameterElement baseParameter = parameter.declaration;
       DartObjectImpl argumentValue;
       AstNode errorTarget;
       if (baseParameter.isNamed) {
@@ -779,10 +776,10 @@
       if (redirectedConstructor == null) {
         break;
       } else {
-        ConstructorElement constructorBase = getConstructorImpl(constructor);
+        ConstructorElement constructorBase = constructor?.declaration;
         constructorsVisited.add(constructorBase);
         ConstructorElement redirectedConstructorBase =
-            getConstructorImpl(redirectedConstructor);
+            redirectedConstructor?.declaration;
         if (constructorsVisited.contains(redirectedConstructorBase)) {
           // Cycle in redirecting factory constructors--this is not allowed
           // and is checked elsewhere--see
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index e792f72..fc81e96 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -12,15 +12,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-
-ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
-  while (constructor is ConstructorMember) {
-    constructor = (constructor as ConstructorMember).baseElement;
-  }
-  return constructor;
-}
 
 /// Callback used by [ReferenceFinder] to report that a dependency was found.
 typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
@@ -304,7 +295,7 @@
   @override
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
     if (node.isConst) {
-      ConstructorElement constructor = getConstructorImpl(node.staticElement);
+      ConstructorElement constructor = node.staticElement?.declaration;
       if (constructor != null) {
         _callback(constructor);
       }
@@ -325,7 +316,7 @@
   void visitRedirectingConstructorInvocation(
       RedirectingConstructorInvocation node) {
     super.visitRedirectingConstructorInvocation(node);
-    ConstructorElement target = getConstructorImpl(node.staticElement);
+    ConstructorElement target = node.staticElement?.declaration;
     if (target != null) {
       _callback(target);
     }
@@ -345,7 +336,7 @@
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     super.visitSuperConstructorInvocation(node);
-    ConstructorElement constructor = getConstructorImpl(node.staticElement);
+    ConstructorElement constructor = node.staticElement?.declaration;
     if (constructor != null) {
       _callback(constructor);
     }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 7b75052..da91d96 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
@@ -1998,6 +1999,9 @@
   }
 
   @override
+  ConstructorElement get declaration => this;
+
+  @override
   String get displayName {
     if (linkedNode != null) {
       return reference.name;
@@ -2156,12 +2160,12 @@
   @override
   FunctionType get type {
     // TODO(scheglov) Remove "element" in the breaking changes branch.
-    return _type ??= FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      parameters,
-      element: this,
+    return _type ??= FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: _noneOrStarSuffix,
+      element: this,
     );
   }
 
@@ -2687,6 +2691,9 @@
   }
 
   @override
+  Element get declaration => this;
+
+  @override
   String get displayName => _name;
 
   @override
@@ -3739,12 +3746,12 @@
     if (_type != null) return _type;
 
     // TODO(scheglov) Remove "element" in the breaking changes branch.
-    return _type = FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      parameters,
-      element: this,
+    return _type = FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: _noneOrStarSuffix,
+      element: this,
     );
   }
 
@@ -4330,6 +4337,9 @@
   FieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
+  FieldElement get declaration => this;
+
+  @override
   bool get isCovariant {
     if (linkedNode != null) {
       return linkedContext.isExplicitlyCovariant(linkedNode);
@@ -4458,6 +4468,9 @@
   }
 
   @override
+  ExecutableElement get declaration => this;
+
+  @override
   String get displayName {
     if (linkedNode != null) {
       return reference.name;
@@ -4583,12 +4596,12 @@
     if (_type != null) return _type;
 
     // TODO(scheglov) Remove "element" in the breaking changes branch.
-    return _type = FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      parameters,
-      element: this,
+    return _type = FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: _noneOrStarSuffix,
+      element: this,
     );
   }
 
@@ -4900,13 +4913,13 @@
 
     var substitution = Substitution.fromPairs(typeParameters, typeArguments);
     var type = substitution.substituteType(function.type) as FunctionType;
-    return FunctionTypeImpl.synthetic(
-      type.returnType,
-      type.typeFormals,
-      type.parameters,
+    return FunctionTypeImpl(
+      typeFormals: type.typeFormals,
+      parameters: type.parameters,
+      returnType: type.returnType,
+      nullabilitySuffix: nullabilitySuffix,
       element: this,
       typeArguments: typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
     );
   }
 
@@ -5845,6 +5858,9 @@
   MethodElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
+  MethodElement get declaration => this;
+
+  @override
   String get displayName {
     String displayName = super.displayName;
     if ("unary-" == displayName) {
@@ -5871,6 +5887,23 @@
         first == 0x24);
   }
 
+  /// Return `true` if this method is `operator==`, and there is no explicit
+  /// type specified for its formal parameter, in this method or in any
+  /// overridden methods other than the one declared in `Object`.
+  bool get isOperatorEqualWithParameterTypeFromObject {
+    if (linkedNode != null) {
+      return linkedContext.hasOperatorEqualParameterTypeFromObject(linkedNode);
+    }
+    return false;
+  }
+
+  /// See [isOperatorEqualWithParameterTypeFromObject].
+  set isOperatorEqualWithParameterTypeFromObject(bool value) {
+    if (linkedNode != null) {
+      linkedContext.setOperatorEqualParameterTypeFromObject(linkedNode, value);
+    }
+  }
+
   @override
   bool get isStatic {
     if (linkedNode != null) {
@@ -6156,6 +6189,9 @@
       this.context, this.session, this.name, this.conflictingElements);
 
   @override
+  Element get declaration => null;
+
+  @override
   String get displayName => name;
 
   @override
@@ -6316,7 +6352,7 @@
 class NeverElementImpl extends ElementImpl implements TypeDefiningElement {
   /// Return the unique instance of this class.
   static NeverElementImpl get instance =>
-      BottomTypeImpl.instance.element as NeverElementImpl;
+      NeverTypeImpl.instance.element as NeverElementImpl;
 
   /// Initialize a newly created instance of this class. Instances of this class
   /// should <b>not</b> be created except as part of creating the type
@@ -6342,11 +6378,11 @@
   }) {
     switch (nullabilitySuffix) {
       case NullabilitySuffix.question:
-        return BottomTypeImpl.instanceNullable;
+        return NeverTypeImpl.instanceNullable;
       case NullabilitySuffix.star:
-        return BottomTypeImpl.instanceLegacy;
+        return NeverTypeImpl.instanceLegacy;
       case NullabilitySuffix.none:
-        return BottomTypeImpl.instance;
+        return NeverTypeImpl.instance;
     }
     throw StateError('Unsupported nullability: $nullabilitySuffix');
   }
@@ -6413,8 +6449,12 @@
         if (linkedContext.hasInitializer(linkedNode)) {
           _initializer = new FunctionElementImpl('', -1)
             ..isSynthetic = true
-            .._type = FunctionTypeImpl.synthetic(type, [], [],
-                nullabilitySuffix: NullabilitySuffix.star)
+            .._type = FunctionTypeImpl(
+              typeFormals: const [],
+              parameters: const [],
+              returnType: type,
+              nullabilitySuffix: NullabilitySuffix.star,
+            )
             ..enclosingElement = this;
         }
       }
@@ -6534,6 +6574,9 @@
   }
 
   @override
+  ParameterElement get declaration => this;
+
+  @override
   String get defaultValueCode {
     if (linkedNode != null) {
       return linkedContext.getDefaultValueCode(linkedNode);
@@ -7042,6 +7085,9 @@
     return variable.setter;
   }
 
+  @override
+  PropertyAccessorElement get declaration => this;
+
   /// Set whether this accessor is a getter.
   void set getter(bool isGetter) {
     setModifier(Modifier.GETTER, isGetter);
@@ -7158,12 +7204,12 @@
     if (_type != null) return _type;
 
     // TODO(scheglov) Remove "element" in the breaking changes branch.
-    var type = FunctionTypeImpl.synthetic(
-      returnType,
-      const <TypeParameterElement>[],
-      const <ParameterElement>[],
-      element: this,
+    var type = FunctionTypeImpl(
+      typeFormals: const <TypeParameterElement>[],
+      parameters: const <ParameterElement>[],
+      returnType: returnType,
       nullabilitySuffix: _noneOrStarSuffix,
+      element: this,
     );
 
     // Don't cache, because types change during top-level inference.
@@ -7217,12 +7263,12 @@
     if (_type != null) return _type;
 
     // TODO(scheglov) Remove "element" in the breaking changes branch.
-    var type = FunctionTypeImpl.synthetic(
-      returnType,
-      const <TypeParameterElement>[],
-      parameters,
-      element: this,
+    var type = FunctionTypeImpl(
+      typeFormals: const <TypeParameterElement>[],
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: _noneOrStarSuffix,
+      element: this,
     );
 
     // Don't cache, because types change during top-level inference.
@@ -7445,6 +7491,10 @@
   /// if this parameter does not have an explicit bound.
   DartType _bound;
 
+  /// The value representing the variance modifier keyword, or `null` if
+  /// there is no explicit variance modifier, meaning legacy covariance.
+  Variance _variance;
+
   /// Initialize a newly created method element to have the given [name] and
   /// [offset].
   TypeParameterElementImpl(String name, int offset) : super(name, offset);
@@ -7494,6 +7544,9 @@
     return super.codeOffset;
   }
 
+  @override
+  TypeParameterElement get declaration => this;
+
   /// The default value of the type parameter. It is used to provide the
   /// corresponding missing type argument in type annotations and as the
   /// fall-back type value in type inference.
@@ -7548,12 +7601,24 @@
     _type = type;
   }
 
+  Variance get variance => _variance ?? Variance.covariant;
+
+  void set variance(Variance newVariance) => _variance = newVariance;
+
+  bool get isLegacyCovariant => _variance == null;
+
   @override
-  bool operator ==(Object object) {
-    if (identical(this, object)) {
+  bool operator ==(Object other) {
+    if (identical(other, this)) {
       return true;
     }
-    return object is TypeParameterElementImpl && object.location == location;
+    if (other is TypeParameterElement) {
+      if (other.enclosingElement == null || enclosingElement == null) {
+        return identical(other, this);
+      }
+      return other.location == location;
+    }
+    return false;
   }
 
   @override
@@ -7703,6 +7768,9 @@
   DartObject get constantValue => evaluationResult?.value;
 
   @override
+  VariableElement get declaration => this;
+
+  @override
   String get displayName => name;
 
   /// Return the result of evaluating this variable's initializer as a
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 550b729..e349274 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -23,41 +23,65 @@
 class ConstructorMember extends ExecutableMember implements ConstructorElement {
   /**
    * Initialize a newly created element to represent a constructor, based on
-   * the [baseElement], and applied [substitution].
+   * the [declaration], and applied [substitution].
    */
   ConstructorMember(
-    ConstructorElement baseElement,
+    ConstructorElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
+
+  @deprecated
+  @override
+  ConstructorElement get baseElement => declaration;
 
   @override
-  ConstructorElement get baseElement => super.baseElement as ConstructorElement;
+  ConstructorElement get declaration => super.declaration as ConstructorElement;
 
   @override
-  ClassElement get enclosingElement => baseElement.enclosingElement;
+  ClassElement get enclosingElement => declaration.enclosingElement;
 
   @override
-  bool get isConst => baseElement.isConst;
+  bool get isConst => declaration.isConst;
 
   @override
-  bool get isConstantEvaluated => baseElement.isConstantEvaluated;
+  bool get isConstantEvaluated => declaration.isConstantEvaluated;
 
   @override
-  bool get isDefaultConstructor => baseElement.isDefaultConstructor;
+  bool get isDefaultConstructor => declaration.isDefaultConstructor;
 
   @override
-  bool get isFactory => baseElement.isFactory;
+  bool get isFactory => declaration.isFactory;
 
   @override
-  int get nameEnd => baseElement.nameEnd;
+  int get nameEnd => declaration.nameEnd;
 
   @override
-  int get periodOffset => baseElement.periodOffset;
+  int get periodOffset => declaration.periodOffset;
 
   @override
   ConstructorElement get redirectedConstructor {
-    var definingType = _substitution.substituteType(enclosingElement.thisType);
-    return from(baseElement.redirectedConstructor, definingType);
+    var element = this.declaration.redirectedConstructor;
+    if (element == null) {
+      return null;
+    }
+
+    ConstructorElement declaration;
+    MapSubstitution substitution;
+    if (element is ConstructorMember) {
+      declaration = element._declaration;
+      var map = <TypeParameterElement, DartType>{};
+      var elementMap = element._substitution.map;
+      for (var typeParameter in elementMap.keys) {
+        var type = elementMap[typeParameter];
+        map[typeParameter] = _substitution.substituteType(type);
+      }
+      substitution = Substitution.fromMap(map);
+    } else {
+      declaration = element;
+      substitution = _substitution;
+    }
+
+    return ConstructorMember(declaration, substitution);
   }
 
   @override
@@ -66,7 +90,7 @@
 
   @override
   String toString() {
-    ConstructorElement baseElement = this.baseElement;
+    ConstructorElement declaration = this.declaration;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
 
@@ -75,7 +99,7 @@
       buffer.write(type.returnType);
       buffer.write(' ');
     }
-    buffer.write(baseElement.enclosingElement.displayName);
+    buffer.write(declaration.enclosingElement.displayName);
     String name = displayName;
     if (name != null && name.isNotEmpty) {
       buffer.write('.');
@@ -126,47 +150,51 @@
 
   /**
    * Initialize a newly created element to represent a callable element (like a
-   * method or function or property), based on the [baseElement], and applied
+   * method or function or property), based on the [declaration], and applied
    * [substitution].
    */
   ExecutableMember(
-    ExecutableElement baseElement,
+    ExecutableElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
+
+  @deprecated
+  @override
+  ExecutableElement get baseElement => declaration;
 
   @override
-  ExecutableElement get baseElement => super.baseElement as ExecutableElement;
+  ExecutableElement get declaration => super.declaration as ExecutableElement;
 
   @override
-  bool get hasImplicitReturnType => baseElement.hasImplicitReturnType;
+  bool get hasImplicitReturnType => declaration.hasImplicitReturnType;
 
   @override
-  bool get isAbstract => baseElement.isAbstract;
+  bool get isAbstract => declaration.isAbstract;
 
   @override
-  bool get isAsynchronous => baseElement.isAsynchronous;
+  bool get isAsynchronous => declaration.isAsynchronous;
 
   @override
-  bool get isExternal => baseElement.isExternal;
+  bool get isExternal => declaration.isExternal;
 
   @override
-  bool get isGenerator => baseElement.isGenerator;
+  bool get isGenerator => declaration.isGenerator;
 
   @override
-  bool get isOperator => baseElement.isOperator;
+  bool get isOperator => declaration.isOperator;
 
   @override
-  bool get isSimplyBounded => baseElement.isSimplyBounded;
+  bool get isSimplyBounded => declaration.isSimplyBounded;
 
   @override
-  bool get isStatic => baseElement.isStatic;
+  bool get isStatic => declaration.isStatic;
 
   @override
-  bool get isSynchronous => baseElement.isSynchronous;
+  bool get isSynchronous => declaration.isSynchronous;
 
   @override
   List<ParameterElement> get parameters {
-    return baseElement.parameters.map((p) {
+    return declaration.parameters.map((p) {
       if (p is FieldFormalParameterElement) {
         return FieldFormalParameterMember(p, _substitution);
       }
@@ -181,13 +209,13 @@
   FunctionType get type {
     if (_type != null) return _type;
 
-    return _type = _substitution.substituteType(baseElement.type);
+    return _type = _substitution.substituteType(declaration.type);
   }
 
   @override
   List<TypeParameterElement> get typeParameters {
     return TypeParameterMember.from(
-      baseElement.typeParameters,
+      declaration.typeParameters,
       _substitution,
     );
   }
@@ -207,7 +235,7 @@
     var combined = substitution;
     if (element is ExecutableMember) {
       ExecutableMember member = element;
-      element = member.baseElement;
+      element = member.declaration;
       var map = <TypeParameterElement, DartType>{};
       map.addAll(member._substitution.map);
       map.addAll(substitution.map);
@@ -238,16 +266,16 @@
     implements FieldFormalParameterElement {
   /**
    * Initialize a newly created element to represent a field formal parameter,
-   * based on the [baseElement], with applied [substitution].
+   * based on the [declaration], with applied [substitution].
    */
   FieldFormalParameterMember(
-    FieldFormalParameterElement baseElement,
+    FieldFormalParameterElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
 
   @override
   FieldElement get field {
-    var field = (baseElement as FieldFormalParameterElement).field;
+    var field = (declaration as FieldFormalParameterElement).field;
     if (field == null) {
       return null;
     }
@@ -256,7 +284,7 @@
   }
 
   @override
-  bool get isCovariant => baseElement.isCovariant;
+  bool get isCovariant => declaration.isCovariant;
 
   @override
   T accept<T>(ElementVisitor<T> visitor) =>
@@ -270,22 +298,26 @@
 class FieldMember extends VariableMember implements FieldElement {
   /**
    * Initialize a newly created element to represent a field, based on the
-   * [baseElement], with applied [substitution].
+   * [declaration], with applied [substitution].
    */
   FieldMember(
-    FieldElement baseElement,
+    FieldElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
+
+  @deprecated
+  @override
+  FieldElement get baseElement => declaration;
 
   @override
-  FieldElement get baseElement => super.baseElement as FieldElement;
+  FieldElement get declaration => super.declaration as FieldElement;
 
   @override
-  Element get enclosingElement => baseElement.enclosingElement;
+  Element get enclosingElement => declaration.enclosingElement;
 
   @override
   PropertyAccessorElement get getter {
-    var baseGetter = baseElement.getter;
+    var baseGetter = declaration.getter;
     if (baseGetter == null) {
       return null;
     }
@@ -293,14 +325,14 @@
   }
 
   @override
-  bool get isCovariant => baseElement.isCovariant;
+  bool get isCovariant => declaration.isCovariant;
 
   @override
-  bool get isEnumConstant => baseElement.isEnumConstant;
+  bool get isEnumConstant => declaration.isEnumConstant;
 
   @override
   PropertyAccessorElement get setter {
-    var baseSetter = baseElement.setter;
+    var baseSetter = declaration.setter;
     if (baseSetter == null) {
       return null;
     }
@@ -349,7 +381,7 @@
   /**
    * The element on which the parameterized element was created.
    */
-  final Element _baseElement;
+  final Element _declaration;
 
   /**
    * The substitution for type parameters referenced in the base element.
@@ -358,113 +390,121 @@
 
   /**
    * Initialize a newly created element to represent a member, based on the
-   * [baseElement], and applied [_substitution].
+   * [declaration], and applied [_substitution].
    */
-  Member(this._baseElement, this._substitution);
+  Member(this._declaration, this._substitution) {
+    if (_declaration is Member) {
+      throw StateError('Members must be created from a declarations.');
+    }
+  }
 
   /**
    * Return the element on which the parameterized element was created.
    */
-  Element get baseElement => _baseElement;
+  @Deprecated('Use Element.declaration instead')
+  Element get baseElement => _declaration;
 
   @override
-  AnalysisContext get context => _baseElement.context;
+  AnalysisContext get context => _declaration.context;
 
   @override
-  String get displayName => _baseElement.displayName;
+  Element get declaration => _declaration;
 
   @override
-  String get documentationComment => _baseElement.documentationComment;
+  String get displayName => _declaration.displayName;
 
   @override
-  bool get hasAlwaysThrows => _baseElement.hasAlwaysThrows;
+  String get documentationComment => _declaration.documentationComment;
 
   @override
-  bool get hasDeprecated => _baseElement.hasDeprecated;
+  bool get hasAlwaysThrows => _declaration.hasAlwaysThrows;
 
   @override
-  bool get hasFactory => _baseElement.hasFactory;
+  bool get hasDeprecated => _declaration.hasDeprecated;
 
   @override
-  bool get hasIsTest => _baseElement.hasIsTest;
+  bool get hasFactory => _declaration.hasFactory;
 
   @override
-  bool get hasIsTestGroup => _baseElement.hasIsTestGroup;
+  bool get hasIsTest => _declaration.hasIsTest;
 
   @override
-  bool get hasJS => _baseElement.hasJS;
+  bool get hasIsTestGroup => _declaration.hasIsTestGroup;
 
   @override
-  bool get hasLiteral => _baseElement.hasLiteral;
+  bool get hasJS => _declaration.hasJS;
 
   @override
-  bool get hasMustCallSuper => _baseElement.hasMustCallSuper;
+  bool get hasLiteral => _declaration.hasLiteral;
 
   @override
-  bool get hasNonVirtual => _baseElement.hasNonVirtual;
+  bool get hasMustCallSuper => _declaration.hasMustCallSuper;
 
   @override
-  bool get hasOptionalTypeArgs => _baseElement.hasOptionalTypeArgs;
+  bool get hasNonVirtual => _declaration.hasNonVirtual;
 
   @override
-  bool get hasOverride => _baseElement.hasOverride;
+  bool get hasOptionalTypeArgs => _declaration.hasOptionalTypeArgs;
 
   @override
-  bool get hasProtected => _baseElement.hasProtected;
+  bool get hasOverride => _declaration.hasOverride;
 
   @override
-  bool get hasRequired => _baseElement.hasRequired;
+  bool get hasProtected => _declaration.hasProtected;
 
   @override
-  bool get hasSealed => _baseElement.hasSealed;
+  bool get hasRequired => _declaration.hasRequired;
 
   @override
-  bool get hasVisibleForTemplate => _baseElement.hasVisibleForTemplate;
+  bool get hasSealed => _declaration.hasSealed;
 
   @override
-  bool get hasVisibleForTesting => _baseElement.hasVisibleForTesting;
+  bool get hasVisibleForTemplate => _declaration.hasVisibleForTemplate;
 
   @override
-  int get id => _baseElement.id;
+  bool get hasVisibleForTesting => _declaration.hasVisibleForTesting;
 
   @override
-  bool get isPrivate => _baseElement.isPrivate;
+  int get id => _declaration.id;
 
   @override
-  bool get isPublic => _baseElement.isPublic;
+  bool get isPrivate => _declaration.isPrivate;
 
   @override
-  bool get isSynthetic => _baseElement.isSynthetic;
+  bool get isPublic => _declaration.isPublic;
 
   @override
-  ElementKind get kind => _baseElement.kind;
+  bool get isSynthetic => _declaration.isSynthetic;
 
   @override
-  LibraryElement get library => _baseElement.library;
+  ElementKind get kind => _declaration.kind;
 
   @override
-  Source get librarySource => _baseElement.librarySource;
+  LibraryElement get library => _declaration.library;
 
   @override
-  ElementLocation get location => _baseElement.location;
+  Source get librarySource => _declaration.librarySource;
 
   @override
-  List<ElementAnnotation> get metadata => _baseElement.metadata;
+  ElementLocation get location => _declaration.location;
 
   @override
-  String get name => _baseElement.name;
+  List<ElementAnnotation> get metadata => _declaration.metadata;
 
   @override
-  int get nameLength => _baseElement.nameLength;
+  String get name => _declaration.name;
 
   @override
-  int get nameOffset => _baseElement.nameOffset;
+  int get nameLength => _declaration.nameLength;
 
   @override
-  AnalysisSession get session => _baseElement.session;
+  int get nameOffset => _declaration.nameOffset;
 
   @override
-  Source get source => _baseElement.source;
+  AnalysisSession get session => _declaration.session;
+
+  @override
+  Source get source => _declaration.source;
 
   /**
    * The substitution for type parameters referenced in the base element.
@@ -473,15 +513,15 @@
 
   @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) =>
-      baseElement.getAncestor(predicate);
+      declaration.getAncestor(predicate);
 
   @override
   String getExtendedDisplayName(String shortName) =>
-      _baseElement.getExtendedDisplayName(shortName);
+      _declaration.getExtendedDisplayName(shortName);
 
   @override
   bool isAccessibleIn(LibraryElement library) =>
-      _baseElement.isAccessibleIn(library);
+      _declaration.isAccessibleIn(library);
 
   /**
    * Use the given [visitor] to visit all of the [children].
@@ -508,25 +548,29 @@
 class MethodMember extends ExecutableMember implements MethodElement {
   /**
    * Initialize a newly created element to represent a method, based on the
-   * [baseElement], with applied [substitution].
+   * [declaration], with applied [substitution].
    */
   MethodMember(
-    MethodElement baseElement,
+    MethodElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
+
+  @deprecated
+  @override
+  MethodElement get baseElement => declaration;
 
   @override
-  MethodElement get baseElement => super.baseElement as MethodElement;
+  MethodElement get declaration => super.declaration as MethodElement;
 
   @override
-  Element get enclosingElement => baseElement.enclosingElement;
+  Element get enclosingElement => declaration.enclosingElement;
 
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
   @override
   String toString() {
-    MethodElement baseElement = this.baseElement;
+    MethodElement declaration = this.declaration;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
 
@@ -535,9 +579,9 @@
       buffer.write(type.returnType);
       buffer.write(' ');
     }
-    buffer.write(baseElement.enclosingElement.displayName);
+    buffer.write(declaration.enclosingElement.displayName);
     buffer.write('.');
-    buffer.write(baseElement.displayName);
+    buffer.write(declaration.displayName);
     int typeParameterCount = typeParameters.length;
     if (typeParameterCount > 0) {
       buffer.write('<');
@@ -627,36 +671,38 @@
     implements ParameterElement {
   /**
    * Initialize a newly created element to represent a parameter, based on the
-   * [baseElement], with applied [substitution]. If [type] is passed it will
-   * represent the already substituted type.
+   * [declaration], with applied [substitution].
    */
   ParameterMember(
-    ParameterElement baseElement,
-    MapSubstitution substitution, [
-    DartType type,
-  ]) : super._(baseElement, substitution, type);
-
-  @override
-  ParameterElement get baseElement => super.baseElement as ParameterElement;
-
-  @override
-  String get defaultValueCode => baseElement.defaultValueCode;
-
-  @override
-  Element get enclosingElement => baseElement.enclosingElement;
-
-  @override
-  int get hashCode => baseElement.hashCode;
-
-  @override
-  bool get isCovariant => baseElement.isCovariant;
-
-  @override
-  bool get isInitializingFormal => baseElement.isInitializingFormal;
+    ParameterElement declaration,
+    MapSubstitution substitution,
+  ) : super(declaration, substitution);
 
   @deprecated
   @override
-  ParameterKind get parameterKind => baseElement.parameterKind;
+  ParameterElement get baseElement => declaration;
+
+  @override
+  ParameterElement get declaration => super.declaration as ParameterElement;
+
+  @override
+  String get defaultValueCode => declaration.defaultValueCode;
+
+  @override
+  Element get enclosingElement => declaration.enclosingElement;
+
+  @override
+  int get hashCode => declaration.hashCode;
+
+  @override
+  bool get isCovariant => declaration.isCovariant;
+
+  @override
+  bool get isInitializingFormal => declaration.isInitializingFormal;
+
+  @deprecated
+  @override
+  ParameterKind get parameterKind => declaration.parameterKind;
 
   @override
   List<ParameterElement> get parameters {
@@ -670,7 +716,7 @@
   @override
   List<TypeParameterElement> get typeParameters {
     return TypeParameterMember.from(
-      baseElement.typeParameters,
+      declaration.typeParameters,
       _substitution,
     );
   }
@@ -680,7 +726,7 @@
 
   @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) {
-    Element element = baseElement.getAncestor(predicate);
+    Element element = declaration.getAncestor(predicate);
     if (element is ExecutableElement) {
       return ExecutableMember.from2(element, _substitution) as E;
     }
@@ -689,20 +735,20 @@
 
   @override
   String toString() {
-    ParameterElement baseElement = this.baseElement;
+    ParameterElement declaration = this.declaration;
     String left = "";
     String right = "";
     while (true) {
-      if (baseElement.isNamed) {
+      if (declaration.isNamed) {
         left = "{";
         right = "}";
-      } else if (baseElement.isOptionalPositional) {
+      } else if (declaration.isOptionalPositional) {
         left = "[";
         right = "]";
       }
       break;
     }
-    return '$left$type ${baseElement.displayName}$right';
+    return '$left$type ${declaration.displayName}$right';
   }
 
   @override
@@ -720,21 +766,21 @@
     implements PropertyAccessorElement {
   /**
    * Initialize a newly created element to represent a property, based on the
-   * [baseElement], with applied [substitution].
+   * [declaration], with applied [substitution].
    */
   PropertyAccessorMember(
-    PropertyAccessorElement baseElement,
+    PropertyAccessorElement declaration,
     MapSubstitution substitution,
-  ) : super(baseElement, substitution);
+  ) : super(declaration, substitution);
 
+  @deprecated
   @override
-  PropertyAccessorElement get baseElement =>
-      super.baseElement as PropertyAccessorElement;
+  PropertyAccessorElement get baseElement => declaration;
 
   @override
   PropertyAccessorElement get correspondingGetter {
     return PropertyAccessorMember(
-      baseElement.correspondingGetter,
+      declaration.correspondingGetter,
       _substitution,
     );
   }
@@ -742,23 +788,27 @@
   @override
   PropertyAccessorElement get correspondingSetter {
     return PropertyAccessorMember(
-      baseElement.correspondingSetter,
+      declaration.correspondingSetter,
       _substitution,
     );
   }
 
   @override
-  Element get enclosingElement => baseElement.enclosingElement;
+  PropertyAccessorElement get declaration =>
+      super.declaration as PropertyAccessorElement;
 
   @override
-  bool get isGetter => baseElement.isGetter;
+  Element get enclosingElement => declaration.enclosingElement;
 
   @override
-  bool get isSetter => baseElement.isSetter;
+  bool get isGetter => declaration.isGetter;
+
+  @override
+  bool get isSetter => declaration.isSetter;
 
   @override
   PropertyInducingElement get variable {
-    PropertyInducingElement variable = baseElement.variable;
+    PropertyInducingElement variable = declaration.variable;
     if (variable is FieldElement) {
       return FieldMember(variable, _substitution);
     }
@@ -771,7 +821,7 @@
 
   @override
   String toString() {
-    PropertyAccessorElement baseElement = this.baseElement;
+    PropertyAccessorElement declaration = this.declaration;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
 
@@ -785,9 +835,9 @@
     } else {
       builder.write('set ');
     }
-    builder.write(baseElement.enclosingElement.displayName);
+    builder.write(declaration.enclosingElement.displayName);
     builder.write('.');
-    builder.write(baseElement.displayName);
+    builder.write(declaration.displayName);
     builder.write('(');
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
@@ -839,33 +889,36 @@
   DartType _bound;
   DartType _type;
 
-  TypeParameterMember(TypeParameterElement baseElement,
+  TypeParameterMember(TypeParameterElement declaration,
       MapSubstitution substitution, this._bound)
-      : super(baseElement, substitution) {
+      : super(declaration, substitution) {
     _type = TypeParameterTypeImpl(this);
   }
 
+  @deprecated
   @override
-  TypeParameterElement get baseElement =>
-      super.baseElement as TypeParameterElement;
+  TypeParameterElement get baseElement => declaration;
 
   @override
   DartType get bound => _bound;
 
   @override
-  Element get enclosingElement => baseElement.enclosingElement;
+  TypeParameterElement get declaration =>
+      super.declaration as TypeParameterElement;
 
   @override
-  int get hashCode => baseElement.hashCode;
+  Element get enclosingElement => declaration.enclosingElement;
+
+  @override
+  int get hashCode => declaration.hashCode;
 
   @override
   TypeParameterType get type => _type;
 
   @override
-  bool operator ==(Object other) =>
-      other is TypeParameterMember &&
-      other.baseElement == baseElement &&
-      other._bound == _bound;
+  bool operator ==(Object other) {
+    return declaration == other;
+  }
 
   @override
   T accept<T>(ElementVisitor<T> visitor) =>
@@ -938,29 +991,23 @@
 
   /**
    * Initialize a newly created element to represent a variable, based on the
-   * [baseElement], with applied [substitution].
+   * [declaration], with applied [substitution].
    */
-  VariableMember(
-    VariableElement baseElement,
-    MapSubstitution substitution, [
-    DartType type,
-  ])  : _type = type,
-        super(baseElement, substitution);
+  VariableMember(VariableElement declaration, MapSubstitution substitution)
+      : super(declaration, substitution);
 
-  // TODO(jmesserly): this is temporary to allow the ParameterMember subclass.
-  // Apparently mixins don't work with optional params.
-  VariableMember._(VariableElement baseElement, MapSubstitution substitution,
-      [DartType type])
-      : this(baseElement, substitution, type);
+  @deprecated
+  @override
+  VariableElement get baseElement => declaration;
 
   @override
-  VariableElement get baseElement => super.baseElement as VariableElement;
+  DartObject get constantValue => declaration.constantValue;
 
   @override
-  DartObject get constantValue => baseElement.constantValue;
+  VariableElement get declaration => super.declaration as VariableElement;
 
   @override
-  bool get hasImplicitType => baseElement.hasImplicitType;
+  bool get hasImplicitType => declaration.hasImplicitType;
 
   @override
   FunctionElement get initializer {
@@ -973,35 +1020,35 @@
   }
 
   @override
-  bool get isConst => baseElement.isConst;
+  bool get isConst => declaration.isConst;
 
   @override
-  bool get isConstantEvaluated => baseElement.isConstantEvaluated;
+  bool get isConstantEvaluated => declaration.isConstantEvaluated;
 
   @override
-  bool get isFinal => baseElement.isFinal;
+  bool get isFinal => declaration.isFinal;
 
   @override
-  bool get isLate => baseElement.isLate;
+  bool get isLate => declaration.isLate;
 
   @override
-  bool get isStatic => baseElement.isStatic;
+  bool get isStatic => declaration.isStatic;
 
   @override
   DartType get type {
     if (_type != null) return _type;
 
-    return _type = _substitution.substituteType(baseElement.type);
+    return _type = _substitution.substituteType(declaration.type);
   }
 
   @override
-  DartObject computeConstantValue() => baseElement.computeConstantValue();
+  DartObject computeConstantValue() => declaration.computeConstantValue();
 
   @override
   void visitChildren(ElementVisitor visitor) {
     // TODO(brianwilkerson) We need to finish implementing the accessors used
     // below so that we can safely invoke them.
     super.visitChildren(visitor);
-    baseElement.initializer?.accept(visitor);
+    declaration.initializer?.accept(visitor);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart b/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
new file mode 100644
index 0000000..c1485e2
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
@@ -0,0 +1,171 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_visitor.dart';
+
+class NullabilityEliminator extends DartTypeVisitor<DartType> {
+  int _counter = 0;
+
+  @override
+  DartType defaultDartType(DartType type) {
+    throw UnimplementedError('(${type.runtimeType}) $type');
+  }
+
+  DartType visit(DartType type) {
+    return DartTypeVisitor.visit(type, this);
+  }
+
+  @override
+  DartType visitDynamicType(DynamicTypeImpl type) {
+    return type;
+  }
+
+  @override
+  DartType visitFunctionType(FunctionType type) {
+    var before = _counter;
+    _incrementCounterIfNotLegacy(type);
+
+    type = _freshTypeParameters(type);
+
+    var parameters = type.parameters.map((parameter) {
+      var type = visit(parameter.type);
+      return _parameterElement(parameter, type);
+    }).toList();
+
+    var returnType = visit(type.returnType);
+    var typeArguments = type.typeArguments.map(visit).toList();
+
+    if (_counter == before) {
+      return type;
+    }
+
+    return FunctionTypeImpl(
+      typeFormals: type.typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.star,
+      element: type.element,
+      typeArguments: typeArguments,
+    );
+  }
+
+  @override
+  DartType visitInterfaceType(InterfaceType type) {
+    var before = _counter;
+    _incrementCounterIfNotLegacy(type);
+
+    var typeArguments = type.typeArguments;
+    if (typeArguments.isNotEmpty) {
+      typeArguments = type.typeArguments.map(visit).toList();
+    }
+
+    if (_counter == before) {
+      return type;
+    }
+
+    return type.element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  @override
+  DartType visitNeverType(NeverTypeImpl type) {
+    return type.withNullability(NullabilitySuffix.star);
+  }
+
+  @override
+  DartType visitTypeParameterType(TypeParameterType type) {
+    var before = _counter;
+    _incrementCounterIfNotLegacy(type);
+
+    if (_counter == before) {
+      return type;
+    }
+
+    return type.element.instantiate(
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  @override
+  DartType visitVoidType(VoidType type) {
+    return type;
+  }
+
+  /// If the [type] has type parameters, and any of them has bounds with
+  /// nullability to eliminate, return a new [FunctionType] instance, with
+  /// new type parameters with legacy types as their bounds, incrementing
+  /// [_counter] as necessary. Otherwise return the original [type] instance.
+  FunctionType _freshTypeParameters(FunctionType type) {
+    var elements = type.typeFormals;
+    if (elements.isEmpty) {
+      return type;
+    }
+
+    var before = _counter;
+
+    var freshBounds = List<DartType>(elements.length);
+    for (var i = 0; i < elements.length; i++) {
+      var bound = elements[i].bound;
+      if (bound != null) {
+        freshBounds[i] = visit(bound);
+      }
+    }
+
+    if (_counter == before) {
+      return type;
+    }
+
+    var freshElements = List<TypeParameterElement>(elements.length);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      var freshElement = TypeParameterElementImpl(element.name, -1);
+      freshElement.bound = freshBounds[i];
+      freshElements[i] = freshElement;
+    }
+
+    FunctionType newType = replaceTypeParameters(type, freshElements);
+    return FunctionTypeImpl(
+      typeFormals: freshElements,
+      parameters: newType.parameters,
+      returnType: newType.returnType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  void _incrementCounterIfNotLegacy(DartType type) {
+    var typeImpl = type as TypeImpl;
+    if (typeImpl.nullabilitySuffix != NullabilitySuffix.star) {
+      _counter++;
+    }
+  }
+
+  /// If the [type] itself, or any of its components, has any nullability,
+  /// return a new type with legacy nullability suffixes. Otherwise return the
+  /// original instance.
+  static T perform<T extends DartType>(T type) {
+    return NullabilityEliminator().visit(type);
+  }
+
+  static ParameterElementImpl _parameterElement(
+    ParameterElement parameter,
+    DartType type,
+  ) {
+    var result = ParameterElementImpl.synthetic(
+      parameter.name,
+      type,
+      // ignore: deprecated_member_use_from_same_package
+      parameter.parameterKind,
+    );
+    result.isExplicitlyCovariant = parameter.isCovariant;
+    return result;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index d518283..920a511 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -40,102 +40,6 @@
 }
 
 /**
- * A [Type] that represents the type 'bottom'.
- */
-class BottomTypeImpl extends TypeImpl {
-  /**
-   * The unique instance of this class, nullable.
-   *
-   * This behaves equivalently to the `Null` type, but we distinguish it for two
-   * reasons: (1) there are circumstances where we need access to this type, but
-   * we don't have access to the type provider, so using `Never?` is a
-   * convenient solution.  (2) we may decide that the distinction is convenient
-   * in diagnostic messages (this is TBD).
-   */
-  static final BottomTypeImpl instanceNullable =
-      new BottomTypeImpl._(NullabilitySuffix.question);
-
-  /**
-   * The unique instance of this class, starred.
-   *
-   * This behaves like a version of the Null* type that could be conceivably
-   * migrated to be of type Never. Therefore, it's the bottom of all legacy
-   * types, and also assignable to the true bottom. Note that Never? and Never*
-   * are not the same type, as Never* is a subtype of Never, while Never? is
-   * not.
-   */
-  static final BottomTypeImpl instanceLegacy =
-      new BottomTypeImpl._(NullabilitySuffix.star);
-
-  /**
-   * The unique instance of this class, non-nullable.
-   */
-  static final BottomTypeImpl instance =
-      new BottomTypeImpl._(NullabilitySuffix.none);
-
-  @override
-  final NullabilitySuffix nullabilitySuffix;
-
-  /**
-   * Prevent the creation of instances of this class.
-   */
-  BottomTypeImpl._(this.nullabilitySuffix)
-      : super(new NeverElementImpl(), "Never");
-
-  @override
-  int get hashCode => 0;
-
-  @override
-  bool get isBottom => true;
-
-  @override
-  bool get isDartCoreNull {
-    // `Never?` is equivalent to `Null`, so make sure it behaves the same.
-    return nullabilitySuffix == NullabilitySuffix.question;
-  }
-
-  @override
-  bool operator ==(Object object) => identical(object, this);
-
-  @override
-  DartType replaceTopAndBottom(TypeProvider typeProvider,
-      {bool isCovariant = true}) {
-    if (isCovariant) {
-      return this;
-    } else {
-      // In theory this should never happen, since we only need to do this
-      // replacement when checking super-boundedness of explicitly-specified
-      // types, or types produced by mixin inference or instantiate-to-bounds,
-      // and bottom can't occur in any of those cases.
-      assert(false,
-          'Attempted to check super-boundedness of a type including "bottom"');
-      // But just in case it does, return `dynamic` since that's similar to what
-      // we do with Null.
-      return typeProvider.objectType;
-    }
-  }
-
-  @override
-  @deprecated
-  BottomTypeImpl substitute2(
-          List<DartType> argumentTypes, List<DartType> parameterTypes) =>
-      this;
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
-    switch (nullabilitySuffix) {
-      case NullabilitySuffix.question:
-        return instanceNullable;
-      case NullabilitySuffix.star:
-        return instanceLegacy;
-      case NullabilitySuffix.none:
-        return instance;
-    }
-    throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
-  }
-}
-
-/**
  * The [Type] representing the type `dynamic`.
  */
 class DynamicTypeImpl extends TypeImpl {
@@ -210,13 +114,28 @@
   @override
   final NullabilitySuffix nullabilitySuffix;
 
-  /// Creates a function type that's not associated with any element in the
-  /// element tree.
-  FunctionTypeImpl.synthetic(this.returnType, this.typeFormals, this.parameters,
+  FunctionTypeImpl({
+    @required List<TypeParameterElement> typeFormals,
+    @required List<ParameterElement> parameters,
+    @required DartType returnType,
+    @required NullabilitySuffix nullabilitySuffix,
+    Element element,
+    List<DartType> typeArguments,
+  })  : typeFormals = typeFormals,
+        parameters = _sortNamedParameters(parameters),
+        returnType = returnType,
+        nullabilitySuffix = nullabilitySuffix,
+        typeArguments = typeArguments ?? const <DartType>[],
+        super(element, null);
+
+  @deprecated
+  FunctionTypeImpl.synthetic(
+      this.returnType, this.typeFormals, List<ParameterElement> parameters,
       {Element element,
       List<DartType> typeArguments,
       @required NullabilitySuffix nullabilitySuffix})
-      : typeArguments = typeArguments ?? const <DartType>[],
+      : parameters = _sortNamedParameters(parameters),
+        typeArguments = typeArguments ?? const <DartType>[],
         nullabilitySuffix = nullabilitySuffix,
         super(element, null);
 
@@ -369,11 +288,7 @@
       }
 
       return returnType == object.returnType &&
-          TypeImpl.equalArrays(
-              normalParameterTypes, object.normalParameterTypes) &&
-          TypeImpl.equalArrays(
-              optionalParameterTypes, object.optionalParameterTypes) &&
-          _equals(namedParameterTypes, object.namedParameterTypes) &&
+          _equalParameters(parameters, object.parameters) &&
           nullabilitySuffix == object.nullabilitySuffix;
     }
     return false;
@@ -389,14 +304,12 @@
         StringBuffer typeParametersBuffer = StringBuffer();
         // To print a type with type variables, first make sure we have unique
         // variable names to print.
-        Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>();
+        var freeVariables = <TypeParameterElement>{};
         _freeVariablesInFunctionType(this, freeVariables);
 
-        Set<String> namesToAvoid = new HashSet<String>();
-        for (DartType arg in freeVariables) {
-          if (arg is TypeParameterType) {
-            namesToAvoid.add(arg.displayName);
-          }
+        var namesToAvoid = <String>{};
+        for (TypeParameterElement arg in freeVariables) {
+          namesToAvoid.add(arg.displayName);
         }
 
         List<DartType> instantiateTypeArgs = <DartType>[];
@@ -404,7 +317,7 @@
         typeParametersBuffer.write('<');
         for (TypeParameterElement e in typeFormals) {
           if (e != typeFormals[0]) {
-            typeParametersBuffer.write(',');
+            typeParametersBuffer.write(', ');
           }
           String name = e.name;
           int counter = 0;
@@ -475,9 +388,12 @@
         ..isExplicitlyCovariant = p.isCovariant;
     }
 
-    return FunctionTypeImpl.synthetic(substitution.substituteType(returnType),
-        const [], _transformOrShare(parameters, transformParameter),
-        nullabilitySuffix: nullabilitySuffix);
+    return FunctionTypeImpl(
+      returnType: substitution.substituteType(returnType),
+      typeFormals: const [],
+      parameters: _transformOrShare(parameters, transformParameter),
+      nullabilitySuffix: nullabilitySuffix,
+    );
   }
 
   @override
@@ -502,8 +418,12 @@
         identical(parameters, this.parameters)) {
       return this;
     }
-    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters,
-        nullabilitySuffix: nullabilitySuffix);
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: nullabilitySuffix,
+    );
   }
 
   @override
@@ -531,17 +451,20 @@
   @override
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
-    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters,
-        element: element,
-        typeArguments: typeArguments,
-        nullabilitySuffix: nullabilitySuffix);
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: nullabilitySuffix,
+      element: element,
+      typeArguments: typeArguments,
+    );
   }
 
   void _appendToWithTypeParameters(StringBuffer buffer,
       Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
     List<DartType> normalParameterTypes = this.normalParameterTypes;
     List<DartType> optionalParameterTypes = this.optionalParameterTypes;
-    Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
     DartType returnType = this.returnType;
 
     if (returnType == null) {
@@ -588,19 +511,25 @@
       buffer.write(']');
       needsComma = true;
     }
-    if (namedParameterTypes.isNotEmpty) {
+
+    var namedParameters = parameters.where((e) => e.isNamed).toList();
+    if (namedParameters.isNotEmpty) {
       startOptionalParameters();
       buffer.write('{');
-      namedParameterTypes.forEach((String name, DartType type) {
+      for (var parameter in namedParameters) {
         writeSeparator();
-        buffer.write(name);
+        if (withNullability && parameter.isRequiredNamed) {
+          buffer.write('required ');
+        }
+        buffer.write(parameter.name);
         buffer.write(': ');
-        (type as TypeImpl)
+        (parameter.type as TypeImpl)
             .appendTo(buffer, visitedTypes, withNullability: withNullability);
-      });
+      }
       buffer.write('}');
       needsComma = true;
     }
+
     buffer.write(')');
     if (withNullability) {
       _appendNullability(buffer);
@@ -618,35 +547,24 @@
   }
 
   void _freeVariablesInFunctionType(
-      FunctionType type, Set<TypeParameterType> free) {
-    // Make some fresh variables to avoid capture.
-    List<DartType> typeArgs = const <DartType>[];
-    if (type.typeFormals.isNotEmpty) {
-      typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
-          new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
-
-      type = type.instantiate(typeArgs);
-    }
-
-    for (ParameterElement p in type.parameters) {
-      _freeVariablesInType(p.type, free);
+      FunctionType type, Set<TypeParameterElement> free) {
+    for (var parameter in type.parameters) {
+      _freeVariablesInType(parameter.type, free);
     }
     _freeVariablesInType(type.returnType, free);
-
-    // Remove all of our bound variables.
-    free.removeAll(typeArgs);
+    free.removeAll(type.typeFormals);
   }
 
   void _freeVariablesInInterfaceType(
-      InterfaceType type, Set<TypeParameterType> free) {
+      InterfaceType type, Set<TypeParameterElement> free) {
     for (DartType typeArg in type.typeArguments) {
       _freeVariablesInType(typeArg, free);
     }
   }
 
-  void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
+  void _freeVariablesInType(DartType type, Set<TypeParameterElement> free) {
     if (type is TypeParameterType) {
-      free.add(type);
+      free.add(type.element);
     } else if (type is FunctionType) {
       _freeVariablesInFunctionType(type, free);
     } else if (type is InterfaceType) {
@@ -884,30 +802,72 @@
     return variablesFresh;
   }
 
-  /**
-   * Return `true` if all of the name/type pairs in the first map ([firstTypes])
-   * are equal to the corresponding name/type pairs in the second map
-   * ([secondTypes]). The maps are expected to iterate over their entries in the
-   * same order in which those entries were added to the map.
-   */
-  static bool _equals(
-      Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) {
-    if (secondTypes.length != firstTypes.length) {
+  /// Return `true` if given lists of parameters are semantically - have the
+  /// same kinds (required, optional position, named, required named), and
+  /// the same types. Named parameters must also have same names. Named
+  /// parameters must be sorted in the given lists.
+  static bool _equalParameters(
+    List<ParameterElement> firstParameters,
+    List<ParameterElement> secondParameters,
+  ) {
+    if (firstParameters.length != secondParameters.length) {
       return false;
     }
-    Iterator<String> firstKeys = firstTypes.keys.iterator;
-    Iterator<String> secondKeys = secondTypes.keys.iterator;
-    while (firstKeys.moveNext() && secondKeys.moveNext()) {
-      String firstKey = firstKeys.current;
-      String secondKey = secondKeys.current;
-      TypeImpl firstType = firstTypes[firstKey];
-      TypeImpl secondType = secondTypes[secondKey];
-      if (firstKey != secondKey || firstType != secondType) {
+    for (var i = 0; i < firstParameters.length; ++i) {
+      var firstParameter = firstParameters[i];
+      var secondParameter = secondParameters[i];
+      // ignore: deprecated_member_use_from_same_package
+      if (firstParameter.parameterKind != secondParameter.parameterKind) {
+        return false;
+      }
+      if (firstParameter.type != secondParameter.type) {
+        return false;
+      }
+      if (firstParameter.isNamed &&
+          firstParameter.name != secondParameter.name) {
         return false;
       }
     }
     return true;
   }
+
+  /// If named parameters are already sorted in [parameters], return it.
+  /// Otherwise, return a new list, in which named parameters are sorted.
+  static List<ParameterElement> _sortNamedParameters(
+    List<ParameterElement> parameters,
+  ) {
+    int firstNamedParameterIndex;
+
+    // Check if already sorted.
+    var namedParametersAlreadySorted = true;
+    var lastNamedParameterName = '';
+    for (var i = 0; i < parameters.length; ++i) {
+      var parameter = parameters[i];
+      if (parameter.isNamed) {
+        firstNamedParameterIndex ??= i;
+        var name = parameter.name;
+        if (lastNamedParameterName.compareTo(name) > 0) {
+          namedParametersAlreadySorted = false;
+          break;
+        }
+        lastNamedParameterName = name;
+      }
+    }
+    if (namedParametersAlreadySorted) {
+      return parameters;
+    }
+
+    // Sort named parameters.
+    var namedParameters =
+        parameters.sublist(firstNamedParameterIndex, parameters.length);
+    namedParameters.sort((a, b) => a.name.compareTo(b.name));
+
+    // Combine into a new list, with sorted named parameters.
+    var newParameters = parameters.toList();
+    newParameters.replaceRange(
+        firstNamedParameterIndex, parameters.length, namedParameters);
+    return newParameters;
+  }
 }
 
 /**
@@ -1895,6 +1855,102 @@
 }
 
 /**
+ * The type `Never` represents the uninhabited bottom type.
+ */
+class NeverTypeImpl extends TypeImpl {
+  /**
+   * The unique instance of this class, nullable.
+   *
+   * This behaves equivalently to the `Null` type, but we distinguish it for two
+   * reasons: (1) there are circumstances where we need access to this type, but
+   * we don't have access to the type provider, so using `Never?` is a
+   * convenient solution.  (2) we may decide that the distinction is convenient
+   * in diagnostic messages (this is TBD).
+   */
+  static final NeverTypeImpl instanceNullable =
+      new NeverTypeImpl._(NullabilitySuffix.question);
+
+  /**
+   * The unique instance of this class, starred.
+   *
+   * This behaves like a version of the Null* type that could be conceivably
+   * migrated to be of type Never. Therefore, it's the bottom of all legacy
+   * types, and also assignable to the true bottom. Note that Never? and Never*
+   * are not the same type, as Never* is a subtype of Never, while Never? is
+   * not.
+   */
+  static final NeverTypeImpl instanceLegacy =
+      new NeverTypeImpl._(NullabilitySuffix.star);
+
+  /**
+   * The unique instance of this class, non-nullable.
+   */
+  static final NeverTypeImpl instance =
+      new NeverTypeImpl._(NullabilitySuffix.none);
+
+  @override
+  final NullabilitySuffix nullabilitySuffix;
+
+  /**
+   * Prevent the creation of instances of this class.
+   */
+  NeverTypeImpl._(this.nullabilitySuffix)
+      : super(new NeverElementImpl(), 'Never');
+
+  @override
+  int get hashCode => 0;
+
+  @override
+  bool get isBottom => true;
+
+  @override
+  bool get isDartCoreNull {
+    // `Never?` is equivalent to `Null`, so make sure it behaves the same.
+    return nullabilitySuffix == NullabilitySuffix.question;
+  }
+
+  @override
+  bool operator ==(Object object) => identical(object, this);
+
+  @override
+  DartType replaceTopAndBottom(TypeProvider typeProvider,
+      {bool isCovariant = true}) {
+    if (isCovariant) {
+      return this;
+    } else {
+      // In theory this should never happen, since we only need to do this
+      // replacement when checking super-boundedness of explicitly-specified
+      // types, or types produced by mixin inference or instantiate-to-bounds,
+      // and bottom can't occur in any of those cases.
+      assert(false,
+          'Attempted to check super-boundedness of a type including "bottom"');
+      // But just in case it does, return `dynamic` since that's similar to what
+      // we do with Null.
+      return typeProvider.objectType;
+    }
+  }
+
+  @override
+  @deprecated
+  NeverTypeImpl substitute2(
+          List<DartType> argumentTypes, List<DartType> parameterTypes) =>
+      this;
+
+  @override
+  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
+    switch (nullabilitySuffix) {
+      case NullabilitySuffix.question:
+        return instanceNullable;
+      case NullabilitySuffix.star:
+        return instanceLegacy;
+      case NullabilitySuffix.none:
+        return instance;
+    }
+    throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
+  }
+}
+
+/**
  * The abstract class `TypeImpl` implements the behavior common to objects
  * representing the declared type of elements in the element model.
  */
@@ -2140,6 +2196,7 @@
     }
     return other is TypeParameterTypeImpl &&
         other.element == element &&
+        other.bound == bound &&
         other.nullabilitySuffix == nullabilitySuffix;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index adeeb1e..c74ce935 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -75,10 +75,10 @@
     )..isExplicitlyCovariant = p.isCovariant;
   }
 
-  return FunctionTypeImpl.synthetic(
-    substitution.substituteType(type.returnType),
-    newTypeParameters,
-    type.parameters.map(transformParameter).toList(),
+  return FunctionTypeImpl(
+    typeFormals: newTypeParameters,
+    parameters: type.parameters.map(transformParameter).toList(),
+    returnType: substitution.substituteType(type.returnType),
     nullabilitySuffix: type.nullabilitySuffix,
   );
 }
@@ -109,10 +109,9 @@
   FreshTypeParameters(this.freshTypeParameters, this.substitution);
 
   FunctionType applyToFunctionType(FunctionType type) {
-    return new FunctionTypeImpl.synthetic(
-      substitute(type.returnType),
-      freshTypeParameters,
-      type.parameters.map((parameter) {
+    return new FunctionTypeImpl(
+      typeFormals: freshTypeParameters,
+      parameters: type.parameters.map((parameter) {
         return ParameterElementImpl.synthetic(
           parameter.name,
           substitute(parameter.type),
@@ -120,6 +119,7 @@
           parameter.parameterKind,
         );
       }).toList(),
+      returnType: substitute(type.returnType),
       nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
     );
   }
@@ -376,9 +376,6 @@
   }
 
   @override
-  DartType visitBottomType(BottomTypeImpl type) => type;
-
-  @override
   DartType visitDynamicType(DynamicTypeImpl type) => type;
 
   @override
@@ -418,13 +415,13 @@
 
     if (this.useCounter == before) return type;
 
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeFormals,
-      parameters,
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
       element: type.element,
       typeArguments: typeArguments,
-      nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
     );
   }
 
@@ -509,6 +506,9 @@
   }
 
   @override
+  DartType visitNeverType(NeverTypeImpl type) => type;
+
+  @override
   DartType visitTypeParameterType(TypeParameterType type) {
     var argument = getSubstitute(type.element);
     if (argument == null) {
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index 952e495..07a7fe8 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.dart
@@ -45,13 +45,20 @@
   final LibraryElement _coreLibrary;
   final LibraryElement _asyncLibrary;
 
+  ClassElement _boolElement;
+  ClassElement _doubleElement;
   ClassElement _futureElement;
   ClassElement _futureOrElement;
+  ClassElement _intElement;
   ClassElement _iterableElement;
   ClassElement _listElement;
   ClassElement _mapElement;
+  ClassElement _nullElement;
+  ClassElement _numElement;
+  ClassElement _objectElement;
   ClassElement _setElement;
   ClassElement _streamElement;
+  ClassElement _stringElement;
   ClassElement _symbolElement;
 
   InterfaceType _boolType;
@@ -82,6 +89,11 @@
   InterfaceType _symbolType;
   InterfaceType _typeType;
 
+  InterfaceType _iterableForSetMapDisambiguation;
+  InterfaceType _mapForSetMapDisambiguation;
+
+  Set<ClassElement> _nonSubtypableClasses;
+
   /// Initialize a newly created type provider to provide the types defined in
   /// the given [coreLibrary] and [asyncLibrary].
   TypeProviderImpl(
@@ -93,6 +105,11 @@
         _asyncLibrary = asyncLibrary;
 
   @override
+  ClassElement get boolElement {
+    return _boolElement ??= _getClassElement(_coreLibrary, 'bool');
+  }
+
+  @override
   InterfaceType get boolType {
     _boolType ??= _getType(_coreLibrary, "bool");
     return _boolType;
@@ -101,9 +118,9 @@
   @override
   DartType get bottomType {
     if (_nullabilitySuffix == NullabilitySuffix.none) {
-      return BottomTypeImpl.instance;
+      return NeverTypeImpl.instance;
     }
-    return BottomTypeImpl.instanceLegacy;
+    return NeverTypeImpl.instanceLegacy;
   }
 
   @override
@@ -113,6 +130,11 @@
   }
 
   @override
+  ClassElement get doubleElement {
+    return _doubleElement ??= _getClassElement(_coreLibrary, "double");
+  }
+
+  @override
   InterfaceType get doubleType {
     _doubleType ??= _getType(_coreLibrary, "double");
     return _doubleType;
@@ -178,6 +200,11 @@
   }
 
   @override
+  ClassElement get intElement {
+    return _intElement ??= _getClassElement(_coreLibrary, "int");
+  }
+
+  @override
   InterfaceType get intType {
     _intType ??= _getType(_coreLibrary, "int");
     return _intType;
@@ -198,6 +225,25 @@
     return _iterableElement ??= _getClassElement(_coreLibrary, 'Iterable');
   }
 
+  /// Return the type that should be used during disambiguation between `Set`
+  /// and `Map` literals. If NNBD enabled, use `Iterable<Object?, Object?>`,
+  /// otherwise use `Iterable<Object*, Object*>*`.
+  InterfaceType get iterableForSetMapDisambiguation {
+    if (_iterableForSetMapDisambiguation == null) {
+      var objectType = objectElement.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: _questionOrStarSuffix,
+      );
+      _iterableForSetMapDisambiguation = iterableElement.instantiate(
+        typeArguments: [
+          objectType,
+        ],
+        nullabilitySuffix: _questionOrStarSuffix,
+      );
+    }
+    return _iterableForSetMapDisambiguation;
+  }
+
   @override
   InterfaceType get iterableObjectType {
     _iterableObjectType ??= InterfaceTypeImpl.explicit(
@@ -230,6 +276,26 @@
     return _mapElement ??= _getClassElement(_coreLibrary, 'Map');
   }
 
+  /// Return the type that should be used during disambiguation between `Set`
+  /// and `Map` literals. If NNBD enabled, use `Map<Object?, Object?>`,
+  /// otherwise use `Map<Object*, Object*>*`.
+  InterfaceType get mapForSetMapDisambiguation {
+    if (_mapForSetMapDisambiguation == null) {
+      var objectType = objectElement.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: _questionOrStarSuffix,
+      );
+      _mapForSetMapDisambiguation = mapElement.instantiate(
+        typeArguments: [
+          objectType,
+          objectType,
+        ],
+        nullabilitySuffix: _questionOrStarSuffix,
+      );
+    }
+    return _mapForSetMapDisambiguation;
+  }
+
   @override
   InterfaceType get mapObjectObjectType {
     _mapObjectObjectType ??= InterfaceTypeImpl.explicit(
@@ -247,7 +313,23 @@
   }
 
   @override
-  DartType get neverType => BottomTypeImpl.instance;
+  DartType get neverType => NeverTypeImpl.instance;
+
+  @override
+  Set<ClassElement> get nonSubtypableClasses => _nonSubtypableClasses ??= {
+        boolElement,
+        doubleElement,
+        futureOrElement,
+        intElement,
+        nullElement,
+        numElement,
+        stringElement,
+      };
+
+  @override
+  ClassElement get nullElement {
+    return _nullElement ??= _getClassElement(_coreLibrary, 'Null');
+  }
 
   @override
   DartObjectImpl get nullObject {
@@ -264,11 +346,20 @@
   }
 
   @override
+  ClassElement get numElement {
+    return _numElement ??= _getClassElement(_coreLibrary, 'num');
+  }
+
+  @override
   InterfaceType get numType {
     _numType ??= _getType(_coreLibrary, "num");
     return _numType;
   }
 
+  ClassElement get objectElement {
+    return _objectElement ??= _getClassElement(_coreLibrary, 'Object');
+  }
+
   @override
   InterfaceType get objectType {
     _objectType ??= _getType(_coreLibrary, "Object");
@@ -313,6 +404,11 @@
   }
 
   @override
+  ClassElement get stringElement {
+    return _stringElement ??= _getClassElement(_coreLibrary, 'String');
+  }
+
+  @override
   InterfaceType get stringType {
     _stringType ??= _getType(_coreLibrary, "String");
     return _stringType;
@@ -338,6 +434,12 @@
   @override
   VoidType get voidType => VoidTypeImpl.instance;
 
+  NullabilitySuffix get _questionOrStarSuffix {
+    return _nullabilitySuffix == NullabilitySuffix.none
+        ? NullabilitySuffix.question
+        : NullabilitySuffix.star;
+  }
+
   @override
   InterfaceType futureOrType2(DartType valueType) {
     return futureOrElement.instantiate(
diff --git a/pkg/analyzer/lib/src/dart/element/type_visitor.dart b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
index fe8a706..60ce66d 100644
--- a/pkg/analyzer/lib/src/dart/element/type_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
@@ -13,8 +13,6 @@
 
   R defaultDartType(DartType type) => null;
 
-  R visitBottomType(BottomTypeImpl type) => defaultDartType(type);
-
   R visitDynamicType(DynamicTypeImpl type) => defaultDartType(type);
 
   R visitFunctionType(FunctionType type) => defaultDartType(type);
@@ -25,6 +23,8 @@
 
   R visitNamedTypeBuilder(NamedTypeBuilder type) => defaultDartType(type);
 
+  R visitNeverType(NeverTypeImpl type) => defaultDartType(type);
+
   R visitTypeParameterType(TypeParameterType type) => defaultDartType(type);
 
   R visitUnknownInferredType(UnknownInferredType type) => defaultDartType(type);
@@ -32,8 +32,8 @@
   R visitVoidType(VoidType type) => defaultDartType(type);
 
   static R visit<R>(DartType type, DartTypeVisitor<R> visitor) {
-    if (type is BottomTypeImpl) {
-      return visitor.visitBottomType(type);
+    if (type is NeverTypeImpl) {
+      return visitor.visitNeverType(type);
     }
     if (type is DynamicTypeImpl) {
       return visitor.visitDynamicType(type);
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index 27e447b..c109df6 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:collection';
-
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -24,14 +22,7 @@
 /// nodes, have legacy types, and asserts that the legacy types are deep legacy
 /// types.
 class LegacyTypeAsserter extends GeneralizingAstVisitor {
-  // TODO(mfairhurst): remove custom equality/hashCode once both use nullability
-  Set<DartType> visitedTypes = LinkedHashSet<DartType>(
-      equals: (a, b) =>
-          a == b &&
-          (a as TypeImpl).nullabilitySuffix ==
-              (b as TypeImpl).nullabilitySuffix,
-      hashCode: (a) =>
-          a.hashCode * 11 + (a as TypeImpl).nullabilitySuffix.hashCode);
+  Set<DartType> _visitedTypes = {};
 
   LegacyTypeAsserter({bool requireIsDebug = true}) {
     if (requireIsDebug) {
@@ -72,9 +63,10 @@
   }
 
   @override
-  visitExpression(Expression e) {
-    _assertLegacyType(e.staticType);
-    super.visitExpression(e);
+  visitExpression(Expression node) {
+    _assertLegacyType(node.staticType);
+    _assertLegacyType(node.staticParameterElement?.type);
+    super.visitExpression(node);
   }
 
   @override
@@ -90,6 +82,13 @@
   }
 
   @override
+  visitInvocationExpression(InvocationExpression node) {
+    _assertLegacyType(node.staticInvokeType);
+    node.typeArgumentTypes?.forEach(_assertLegacyType);
+    return super.visitInvocationExpression(node);
+  }
+
+  @override
   visitTypeAnnotation(TypeAnnotation node) {
     _assertLegacyType(node.type);
     super.visitTypeAnnotation(node);
@@ -125,12 +124,10 @@
       return;
     }
 
-    if (visitedTypes.contains(type)) {
+    if (!_visitedTypes.add(type)) {
       return;
     }
 
-    visitedTypes.add(type);
-
     if (type is TypeParameterType) {
       _assertLegacyType(type.bound);
     } else if (type is InterfaceType) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index e119faf..dfff9aa 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -159,7 +159,7 @@
       return;
     }
 
-    if (receiverType == BottomTypeImpl.instance) {
+    if (receiverType == NeverTypeImpl.instance) {
       _reportUseOfNeverType(node, receiver);
       return;
     }
@@ -885,7 +885,7 @@
       return _reportUseOfVoidType(node, node.methodName);
     }
 
-    if (type == BottomTypeImpl.instance) {
+    if (type == NeverTypeImpl.instance) {
       return _reportUseOfNeverType(node, node.methodName);
     }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index c3489dd..8df0142 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/declaration_resolver.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -635,10 +636,10 @@
 
             node.returnType?.accept(this);
             if (_elementWalker == null) {
-              element.type = FunctionTypeImpl.synthetic(
-                node.returnType?.type ?? _dynamicType,
-                element.typeParameters,
-                element.parameters,
+              element.type = FunctionTypeImpl(
+                typeFormals: element.typeParameters,
+                parameters: element.parameters,
+                returnType: node.returnType?.type ?? _dynamicType,
                 nullabilitySuffix: _getNullability(node.question != null),
               );
             }
@@ -673,10 +674,10 @@
       });
     });
 
-    var type = FunctionTypeImpl.synthetic(
-      element.returnType,
-      element.typeParameters,
-      element.parameters,
+    var type = FunctionTypeImpl(
+      typeFormals: element.typeParameters,
+      parameters: element.parameters,
+      returnType: element.returnType,
       nullabilitySuffix: _getNullability(node.question != null),
     );
     element.type = type;
@@ -892,6 +893,13 @@
   void visitTypeParameter(TypeParameter node) {
     TypeParameterElementImpl element = node.declaredElement;
 
+    // TODO (kallentu) : Clean up TypeParameterImpl checks and casting once
+    //  variance is added to the interface.
+    if (node is TypeParameterImpl && node.varianceKeyword != null) {
+      element.variance =
+          Variance.fromKeywordString(node.varianceKeyword.lexeme);
+    }
+
     node.metadata?.accept(this);
     _setElementAnnotations(node.metadata, element.metadata);
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 40ca63b..d59b9ba 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -410,11 +410,9 @@
       List<ImportElement> imports = _definingLibrary.imports;
       int count = imports.length;
       for (int i = 0; i < count; i++) {
-        if (imports[i].prefix == null) {
-          for (var element in imports[i].namespace.definedNames.values) {
-            if (element is ExtensionElement && !_extensions.contains(element)) {
-              _extensions.add(element);
-            }
+        for (var element in imports[i].namespace.definedNames.values) {
+          if (element is ExtensionElement && !_extensions.contains(element)) {
+            _extensions.add(element);
           }
         }
       }
@@ -786,7 +784,7 @@
     // which is not possible for `dynamic`.
     if (library.isDartCore) {
       definedNames['dynamic'] = DynamicElementImpl.instance;
-      definedNames['Never'] = BottomTypeImpl.instance.element;
+      definedNames['Never'] = NeverTypeImpl.instance.element;
     }
 
     return new Namespace(definedNames);
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
index 69bc580..3f69514 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variance.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -5,108 +5,157 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 
-/// Computes the variance of the [typeParameter] in the [type].
-int computeVariance(TypeParameterElement typeParameter, DartType type) {
-  if (type is TypeParameterType) {
-    if (type.element == typeParameter) {
-      return Variance.covariant;
-    } else {
-      return Variance.unrelated;
-    }
-  } else if (type is InterfaceType) {
-    var result = Variance.unrelated;
-    for (var argument in type.typeArguments) {
-      result = Variance.meet(
-        result,
-        computeVariance(typeParameter, argument),
-      );
-    }
-    return result;
-  } else if (type is FunctionType) {
-    var result = computeVariance(typeParameter, type.returnType);
-
-    for (var parameter in type.typeFormals) {
-      // If [parameter] is referenced in the bound at all, it makes the
-      // variance of [parameter] in the entire type invariant.  The invocation
-      // of [computeVariance] below is made to simply figure out if [variable]
-      // occurs in the bound.
-      var bound = parameter.bound;
-      if (bound != null &&
-          computeVariance(typeParameter, bound) != Variance.unrelated) {
-        result = Variance.invariant;
-      }
-    }
-
-    for (var parameter in type.parameters) {
-      result = Variance.meet(
-        result,
-        Variance.combine(
-          Variance.contravariant,
-          computeVariance(typeParameter, parameter.type),
-        ),
-      );
-    }
-    return result;
-  }
-  return Variance.unrelated;
-}
-
-/// Value set for variance of a type parameter `X` in a type `T`.
+/// The variance of a type parameter `X` in a type `T`.
 class Variance {
   /// Used when `X` does not occur free in `T`.
-  static const int unrelated = 0;
+  static const Variance unrelated = Variance._(0);
 
   /// Used when `X` occurs free in `T`, and `U <: V` implies `[U/X]T <: [V/X]T`.
-  static const int covariant = 1;
+  static const Variance covariant = Variance._(1);
 
   /// Used when `X` occurs free in `T`, and `U <: V` implies `[V/X]T <: [U/X]T`.
-  static const int contravariant = 2;
+  static const Variance contravariant = Variance._(2);
 
   /// Used when there exists a pair `U` and `V` such that `U <: V`, but
   /// `[U/X]T` and `[V/X]T` are incomparable.
-  static const int invariant = 3;
+  static const Variance invariant = Variance._(3);
+
+  /// The encoding associated with the variance.
+  final int _encoding;
+
+  /// Computes the variance of the [typeParameter] in the [type].
+  factory Variance(TypeParameterElement typeParameter, DartType type) {
+    if (type is TypeParameterType) {
+      if (type.element == typeParameter) {
+        return covariant;
+      } else {
+        return unrelated;
+      }
+    } else if (type is InterfaceType) {
+      var result = unrelated;
+      for (var argument in type.typeArguments) {
+        result = result.meet(
+          Variance(typeParameter, argument),
+        );
+      }
+      return result;
+    } else if (type is FunctionType) {
+      var result = Variance(typeParameter, type.returnType);
+
+      for (var parameter in type.typeFormals) {
+        // If [parameter] is referenced in the bound at all, it makes the
+        // variance of [parameter] in the entire type invariant.  The invocation
+        // of [computeVariance] below is made to simply figure out if [variable]
+        // occurs in the bound.
+        var bound = parameter.bound;
+        if (bound != null && !Variance(typeParameter, bound).isUnrelated) {
+          result = invariant;
+        }
+      }
+
+      for (var parameter in type.parameters) {
+        result = result.meet(
+          contravariant.combine(
+            Variance(typeParameter, parameter.type),
+          ),
+        );
+      }
+      return result;
+    }
+    return unrelated;
+  }
+
+  /// Initialize a newly created variance to have the given [encoding].
+  const Variance._(this._encoding);
+
+  /// Return the variance with the given [encoding].
+  factory Variance._fromEncoding(int encoding) {
+    switch (encoding) {
+      case 0:
+        return unrelated;
+      case 1:
+        return covariant;
+      case 2:
+        return contravariant;
+      case 3:
+        return invariant;
+    }
+    throw new ArgumentError('Invalid encoding for variance: $encoding');
+  }
+
+  /// Return the variance associated with the string representation of variance.
+  factory Variance.fromKeywordString(String varianceString) {
+    if (varianceString == "in") {
+      return contravariant;
+    } else if (varianceString == "inout") {
+      return invariant;
+    } else if (varianceString == "out") {
+      return covariant;
+    } else if (varianceString == "unrelated") {
+      return unrelated;
+    }
+    throw new ArgumentError(
+        'Invalid keyword string for variance: $varianceString');
+  }
+
+  /// Return `true` if this represents the case when `X` occurs free in `T`, and
+  /// `U <: V` implies `[V/X]T <: [U/X]T`.
+  bool get isContravariant => this == contravariant;
+
+  /// Return `true` if this represents the case when `X` occurs free in `T`, and
+  /// `U <: V` implies `[U/X]T <: [V/X]T`.
+  bool get isCovariant => this == covariant;
+
+  /// Return `true` if this represents the case when there exists a pair `U` and
+  /// `V` such that `U <: V`, but `[U/X]T` and `[V/X]T` are incomparable.
+  bool get isInvariant => this == invariant;
+
+  /// Return `true` if this represents the case when `X` does not occur free in
+  /// `T`.
+  bool get isUnrelated => this == unrelated;
 
   /// Combines variances of `X` in `T` and `Y` in `S` into variance of `X` in
   /// `[Y/T]S`.
   ///
   /// Consider the following examples:
   ///
-  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y`
-  /// in `List<Y>` is [covariant], so variance of `X` in `List<Function(X)>` is
-  /// [contravariant];
+  /// * variance of `X` in `Function(X)` is contravariant, variance of `Y`
+  /// in `List<Y>` is covariant, so variance of `X` in `List<Function(X)>` is
+  /// contravariant;
   ///
-  /// * variance of `X` in `List<X>` is [covariant], variance of `Y` in
-  /// `Function(Y)` is [contravariant], so variance of `X` in
-  /// `Function(List<X>)` is [contravariant];
+  /// * variance of `X` in `List<X>` is covariant, variance of `Y` in
+  /// `Function(Y)` is contravariant, so variance of `X` in
+  /// `Function(List<X>)` is contravariant;
   ///
-  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y` in
-  /// `Function(Y)` is [contravariant], so variance of `X` in
-  /// `Function(Function(X))` is [covariant];
+  /// * variance of `X` in `Function(X)` is contravariant, variance of `Y` in
+  /// `Function(Y)` is contravariant, so variance of `X` in
+  /// `Function(Function(X))` is covariant;
   ///
   /// * let the following be declared:
   ///
   ///     typedef F<Z> = Function();
   ///
-  /// then variance of `X` in `F<X>` is [unrelated], variance of `Y` in
-  /// `List<Y>` is [covariant], so variance of `X` in `List<F<X>>` is
-  /// [unrelated];
+  /// then variance of `X` in `F<X>` is unrelated, variance of `Y` in
+  /// `List<Y>` is covariant, so variance of `X` in `List<F<X>>` is
+  /// unrelated;
   ///
   /// * let the following be declared:
   ///
   ///     typedef G<Z> = Z Function(Z);
   ///
-  /// then variance of `X` in `List<X>` is [covariant], variance of `Y` in
-  /// `G<Y>` is [invariant], so variance of `X` in `G<List<X>>` is [invariant].
-  static int combine(int a, int b) {
-    if (a == unrelated || b == unrelated) return unrelated;
-    if (a == invariant || b == invariant) return invariant;
-    return a == b ? covariant : contravariant;
+  /// then variance of `X` in `List<X>` is covariant, variance of `Y` in
+  /// `G<Y>` is invariant, so variance of `X` in `G<List<X>>` is invariant.
+  Variance combine(Variance other) {
+    if (isUnrelated || other.isUnrelated) return unrelated;
+    if (isInvariant || other.isInvariant) return invariant;
+    return this == other ? covariant : contravariant;
   }
 
-  /// Variance values form a lattice where [unrelated] is the top, [invariant]
-  /// is the bottom, and [covariant] and [contravariant] are incomparable.
+  /// Variance values form a lattice where unrelated is the top, invariant
+  /// is the bottom, and covariant and contravariant are incomparable.
   /// [meet] calculates the meet of two elements of such lattice.  It can be
   /// used, for example, to calculate the variance of a typedef type parameter
   /// if it's encountered on the RHS of the typedef multiple times.
-  static int meet(int a, int b) => a | b;
+  Variance meet(Variance other) =>
+      Variance._fromEncoding(_encoding | other._encoding);
 }
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 7657ed0..10e559f 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -635,9 +635,9 @@
     if (resourceProvider is MemoryResourceProvider) {
       (resourceProvider as MemoryResourceProvider).writeOn(buffer);
     }
+    // TODO(39284): should this exception be silent?
     AnalysisEngine.instance.instrumentationService.logException(
-        new CaughtException.withMessage(
-            buffer.toString(), lastException, lastStackTrace));
+        new SilentException(buffer.toString(), lastException, lastStackTrace));
     return new LibraryMap();
   }
 
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 159c539..240ec8c 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1229,6 +1229,17 @@
               "modifier.");
 
   /**
+   * No parameters.
+   */
+  static const CompileTimeErrorCode DEFERRED_IMPORT_OF_EXTENSION =
+      const CompileTimeErrorCode('DEFERRED_IMPORT_OF_EXTENSION',
+          "Imports of deferred libraries must hide all extensions",
+          correction:
+              "Try adding either a show combinator listing the names you need "
+              "to reference or a hide combinator listing all of the "
+              "extensions.");
+
+  /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity
    * with the same name declared in the same scope.
    */
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 6640df9..16ae004 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -331,7 +330,8 @@
     }
 
     DartType type = typeName.type;
-    if (typeProvider.nonSubtypableTypes.contains(type)) {
+    if (type is InterfaceType &&
+        typeProvider.nonSubtypableClasses.contains(type.element)) {
       reporter.reportErrorForNode(errorCode, typeName, [type.displayName]);
       return true;
     }
@@ -450,10 +450,7 @@
     for (var i = 0; i < baseParameterElements.length; ++i) {
       var baseParameter = baseParameterElements[i];
       if (baseParameter.isOptional) {
-        if (baseParameter is ParameterMember) {
-          baseParameter = (baseParameter as ParameterMember).baseElement;
-        }
-        baseOptionalElements.add(baseParameter);
+        baseOptionalElements.add(baseParameter.declaration);
       }
     }
 
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 66fa754..8aeb435 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -145,13 +144,8 @@
     }
 
     InterfaceType iterableType;
-    var iterableDynamicType = (typeProvider.iterableDynamicType as TypeImpl)
-        .withNullability(NullabilitySuffix.question);
-    if (expressionType is InterfaceTypeImpl &&
-        typeSystem.isSubtypeOf(expressionType, iterableDynamicType)) {
-      iterableType = expressionType.asInstanceOf(
-        iterableDynamicType.element,
-      );
+    if (expressionType is InterfaceTypeImpl) {
+      iterableType = expressionType.asInstanceOf(typeProvider.iterableElement);
     }
 
     if (iterableType == null) {
@@ -192,10 +186,8 @@
     }
 
     InterfaceType mapType;
-    var mapObjectObjectType = typeProvider.mapObjectObjectType;
-    if (expressionType is InterfaceTypeImpl &&
-        typeSystem.isSubtypeOf(expressionType, mapObjectObjectType)) {
-      mapType = expressionType.asInstanceOf(mapObjectObjectType.element);
+    if (expressionType is InterfaceTypeImpl) {
+      mapType = expressionType.asInstanceOf(typeProvider.mapElement);
     }
 
     if (mapType == null) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 94fcd92..c40153a2 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -25,6 +25,7 @@
         templateExpectedButGot,
         templateExpectedIdentifier,
         templateExperimentNotEnabled,
+        templateInternalProblemUnhandled,
         templateUnexpectedToken;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show
@@ -36,6 +37,9 @@
         MemberKind,
         optional,
         Parser;
+import 'package:_fe_analyzer_shared/src/parser/quote.dart';
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
+    show NullValue, StackListener;
 import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
     show translateErrorToken;
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' hide StringToken;
@@ -54,14 +58,10 @@
         ClassDeclarationImpl,
         CompilationUnitImpl,
         ExtensionDeclarationImpl,
-        MixinDeclarationImpl;
+        MixinDeclarationImpl,
+        TypeParameterImpl;
 import 'package:analyzer/src/fasta/error_converter.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:front_end/src/fasta/problems.dart' show unhandled;
-import 'package:front_end/src/fasta/quote.dart';
-import 'package:front_end/src/fasta/source/stack_listener.dart'
-    show NullValue, StackListener;
-import 'package:kernel/ast.dart' show AsyncMarker;
 
 const _invalidCollectionElement = const _InvalidCollectionElement._();
 
@@ -78,6 +78,11 @@
   @override
   final Uri uri;
 
+  @override
+  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+    throw UnsupportedError(message.message);
+  }
+
   /// The parser that uses this listener, used to parse optional parts, e.g.
   /// `native` support.
   Parser parser;
@@ -672,8 +677,11 @@
       redirectedConstructor = bodyObject.constructorName;
       body = ast.emptyFunctionBody(endToken);
     } else {
-      unhandled("${bodyObject.runtimeType}", "bodyObject",
-          beginToken.charOffset, uri);
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments(
+              "${bodyObject.runtimeType}", "bodyObject"),
+          beginToken.charOffset,
+          uri);
     }
 
     SimpleIdentifier prefixOrName;
@@ -753,8 +761,11 @@
       redirectedConstructor = bodyObject.constructorName;
       body = ast.emptyFunctionBody(endToken);
     } else {
-      unhandled("${bodyObject.runtimeType}", "bodyObject",
-          beginToken.charOffset, uri);
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments(
+              "${bodyObject.runtimeType}", "bodyObject"),
+          beginToken.charOffset,
+          uri);
     }
 
     FormalParameterList parameters = pop();
@@ -856,8 +867,11 @@
     } else if (bodyObject is _RedirectingFactoryBody) {
       body = ast.emptyFunctionBody(endToken);
     } else {
-      unhandled("${bodyObject.runtimeType}", "bodyObject",
-          beginToken.charOffset, uri);
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments(
+              "${bodyObject.runtimeType}", "bodyObject"),
+          beginToken.charOffset,
+          uri);
     }
 
     Token operatorKeyword;
@@ -1576,7 +1590,11 @@
     } else if (node is SimpleIdentifier) {
       variable = _makeVariableDeclaration(node, null, null);
     } else {
-      unhandled("${node.runtimeType}", "identifier", nameToken.charOffset, uri);
+      internalProblem(
+          templateInternalProblemUnhandled.withArguments(
+              "${node.runtimeType}", "identifier"),
+          nameToken.charOffset,
+          uri);
     }
     push(variable);
   }
@@ -1659,8 +1677,11 @@
         } else if (part is InterpolationExpression) {
           elements.add(part);
         } else {
-          unhandled("${part.runtimeType}", "string interpolation",
-              first.charOffset, uri);
+          internalProblem(
+              templateInternalProblemUnhandled.withArguments(
+                  "${part.runtimeType}", "string interpolation"),
+              first.charOffset,
+              uri);
         }
       }
       elements.add(ast.interpolationString(
@@ -2121,9 +2142,14 @@
 
     // Peek to leave type parameters on top of stack.
     List<TypeParameter> typeParameters = peek();
-    typeParameters[index]
+    TypeParameter typeParameter = typeParameters[index];
+    typeParameter
       ..extendsKeyword = extendsOrSuper
       ..bound = bound;
+
+    if (typeParameter is TypeParameterImpl) {
+      typeParameter.varianceKeyword = variance;
+    }
   }
 
   @override
@@ -2197,41 +2223,6 @@
     push(ast.yieldStatement(yieldToken, starToken, expression, semicolon));
   }
 
-  @override
-  void exitLocalScope() {}
-
-  @override
-  AstNode finishFields() {
-    debugEvent("finishFields");
-
-    if (classDeclaration != null) {
-      return classDeclaration.members
-          .removeAt(classDeclaration.members.length - 1);
-    } else if (mixinDeclaration != null) {
-      return mixinDeclaration.members
-          .removeAt(mixinDeclaration.members.length - 1);
-    } else {
-      return declarations.removeLast();
-    }
-  }
-
-  void finishFunction(formals, AsyncMarker asyncModifier, FunctionBody body) {
-    debugEvent("finishFunction");
-
-    Statement bodyStatement;
-    if (body is EmptyFunctionBody) {
-      bodyStatement = ast.emptyStatement(body.semicolon);
-    } else if (body is NativeFunctionBody) {
-      // TODO(danrubel): what do we need to do with NativeFunctionBody?
-    } else if (body is ExpressionFunctionBody) {
-      bodyStatement = ast.returnStatement(null, body.expression, null);
-    } else {
-      bodyStatement = (body as BlockFunctionBody).block;
-    }
-    // TODO(paulberry): what do we need to do with bodyStatement at this point?
-    bodyStatement; // Suppress "unused local variable" hint
-  }
-
   void handleAsOperator(Token asOperator) {
     assert(optional('as', asOperator));
     debugEvent("AsOperator");
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 1132017..b7ce355 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -274,12 +273,6 @@
    */
   HiddenElements _hiddenElements;
 
-  /**
-   * A list of types used by the [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]
-   * and [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS] error codes.
-   */
-  List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT;
-
   final _UninstantiatedBoundChecker _uninstantiatedBoundChecker;
 
   /// Setting this flag to `true` disables the check for conflicting generics.
@@ -318,7 +311,6 @@
     _isInStaticMethod = false;
     _boolType = _typeProvider.boolType;
     _intType = _typeProvider.intType;
-    _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes;
     _typeSystem = _currentLibrary.context.typeSystem;
     _options = _currentLibrary.context.analysisOptions;
     _typeArgumentsVerifier =
@@ -953,6 +945,9 @@
     if (importElement != null) {
       _checkForImportDuplicateLibraryName(node, importElement);
       _checkForImportInternalLibrary(node, importElement);
+      if (importElement.isDeferred) {
+        _checkForDeferredImportOfExtensions(node, importElement);
+      }
     }
     super.visitImportDirective(node);
   }
@@ -2624,6 +2619,39 @@
   }
 
   /**
+   * Report a diagnostic if there are any extensions in the imported library
+   * that are not hidden.
+   */
+  void _checkForDeferredImportOfExtensions(
+      ImportDirective directive, ImportElement importElement) {
+    List<String> shownNames = [];
+    List<String> hiddenNames = [];
+
+    Iterable<String> namesOf(List<SimpleIdentifier> identifiers) =>
+        identifiers.map((identifier) => identifier.name);
+    for (Combinator combinator in directive.combinators) {
+      if (combinator is HideCombinator) {
+        hiddenNames.addAll(namesOf(combinator.hiddenNames));
+      } else if (combinator is ShowCombinator) {
+        shownNames.addAll(namesOf(combinator.shownNames));
+      }
+    }
+    for (Element element in importElement.importedLibrary.topLevelElements) {
+      if (element is ExtensionElement) {
+        String name = element.name;
+        if (name != null &&
+            name.isNotEmpty &&
+            (shownNames.contains(name) ||
+                (shownNames.isEmpty && !hiddenNames.contains(name)))) {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION, directive.uri);
+          return;
+        }
+      }
+    }
+  }
+
+  /**
    * Verify that any deferred imports in the given compilation [unit] have a
    * unique prefix.
    *
@@ -2876,7 +2904,8 @@
     if (_currentLibrary.source.isInSystemLibrary) {
       return false;
     }
-    return _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT.contains(typeName.type);
+    return typeName.type is InterfaceType &&
+        _typeProvider.nonSubtypableClasses.contains(typeName.type.element);
   }
 
   void _checkForExtensionDeclaresMemberOfObject(MethodDeclaration node) {
@@ -3130,7 +3159,7 @@
     // Similar logic applies for sync* and async*.
     //
     var lowerBound = expectedElement.instantiate(
-      typeArguments: [BottomTypeImpl.instance],
+      typeArguments: [NeverTypeImpl.instance],
       nullabilitySuffix: NullabilitySuffix.star,
     );
     if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
@@ -5092,7 +5121,7 @@
    */
   bool _checkForUseOfNever(Expression expression) {
     if (expression == null ||
-        !identical(expression.staticType, BottomTypeImpl.instance)) {
+        !identical(expression.staticType, NeverTypeImpl.instance)) {
       return false;
     }
 
@@ -5274,9 +5303,8 @@
     void checkOne(DartType superInterface) {
       if (superInterface != null) {
         for (var typeParameter in _enclosingClass.typeParameters) {
-          var variance = computeVariance(typeParameter, superInterface);
-          if (variance == Variance.contravariant ||
-              variance == Variance.invariant) {
+          var variance = Variance(typeParameter, superInterface);
+          if (variance.isContravariant || variance.isInvariant) {
             _errorReporter.reportErrorForElement(
               CompileTimeErrorCode
                   .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
@@ -5744,12 +5772,6 @@
    * indirectly.
    */
   bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) {
-    ConstructorElement nonMember(ConstructorElement constructor) {
-      return constructor is ConstructorMember
-          ? constructor.baseElement
-          : constructor;
-    }
-
     Set<ConstructorElement> constructors = new HashSet<ConstructorElement>();
     ConstructorElement current = constructor;
     while (current != null) {
@@ -5757,7 +5779,7 @@
         return identical(current, constructor);
       }
       constructors.add(current);
-      current = nonMember(current.redirectedConstructor);
+      current = current.redirectedConstructor?.declaration;
     }
     return false;
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d0e1e5f..8a3ddfc 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
@@ -364,7 +365,7 @@
           node.returnType, node.functionExpression.body, element, node);
 
       // Return types are inferred only on non-recursive local functions.
-      if (node.parent is CompilationUnit) {
+      if (node.parent is CompilationUnit && !node.isSetter) {
         _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
       }
       _checkStrictInferenceInParameters(node.functionExpression.parameters);
@@ -498,7 +499,7 @@
       _checkForMissingReturn(node.returnType, node.body, element, node);
       _checkForUnnecessaryNoSuchMethod(node);
 
-      if (_strictInference && !node.isSetter && !elementIsOverride()) {
+      if (!node.isSetter && !elementIsOverride()) {
         _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
       }
       _checkStrictInferenceInParameters(node.parameters);
@@ -1359,6 +1360,10 @@
   /// `null` if the element doesn't have a deprecated annotation or if the
   /// annotation does not have a message.
   static String _deprecatedMessage(Element element) {
+    // Implicit getters/setters.
+    if (element.isSynthetic && element is PropertyAccessorElement) {
+      element = (element as PropertyAccessorElement).variable;
+    }
     ElementAnnotationImpl annotation = element.metadata.firstWhere(
       (e) => e.isDeprecated,
       orElse: () => null,
@@ -2697,8 +2702,12 @@
   /// or `null` if not in a [SwitchStatement].
   DartType _enclosingSwitchStatementExpressionType;
 
-  InterfaceType _iterableForSetMapDisambiguationCached;
-  InterfaceType _mapForSetMapDisambiguationCached;
+  /// Stack of expressions which we have not yet finished visiting, that should
+  /// terminate a null-shorting expression.
+  ///
+  /// The stack contains a `null` sentinel as its first entry so that it is
+  /// always safe to use `.last` to examine the top of the stack.
+  final List<Expression> unfinishedNullShorts = [null];
 
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
@@ -2792,31 +2801,6 @@
         : NullabilitySuffix.star;
   }
 
-  InterfaceType get _iterableForSetMapDisambiguation {
-    return _iterableForSetMapDisambiguationCached ??=
-        typeProvider.iterableElement.instantiate(
-      typeArguments: [
-        typeProvider.dynamicType,
-      ],
-      nullabilitySuffix: _nonNullableEnabled
-          ? NullabilitySuffix.question
-          : NullabilitySuffix.star,
-    );
-  }
-
-  InterfaceType get _mapForSetMapDisambiguation {
-    return _mapForSetMapDisambiguationCached ??=
-        typeProvider.mapElement.instantiate(
-      typeArguments: [
-        typeProvider.dynamicType,
-        typeProvider.dynamicType,
-      ],
-      nullabilitySuffix: _nonNullableEnabled
-          ? NullabilitySuffix.question
-          : NullabilitySuffix.star,
-    );
-  }
-
   /**
    * Return `true` if NNBD is enabled for this compilation unit.
    */
@@ -3840,8 +3824,9 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     node.target?.accept(this);
-    if (node.isNullAware) {
-      _flowAnalysis?.flow?.nullAwareAccess_rightBegin(node.target);
+    if (node.isNullAware && _nonNullableEnabled) {
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      unfinishedNullShorts.add(node.nullShortingTermination);
     }
     node.accept(elementResolver);
     var method = node.staticElement;
@@ -4037,8 +4022,9 @@
     // to be visited in the context of the property access node.
     //
     node.target?.accept(this);
-    if (node.isNullAware) {
-      _flowAnalysis?.flow?.nullAwareAccess_rightBegin(node.target);
+    if (node.isNullAware && _nonNullableEnabled) {
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      unfinishedNullShorts.add(node.nullShortingTermination);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -4509,9 +4495,9 @@
       // TODO(brianwilkerson) Find out what the "greatest closure" is and use that
       // where [unwrappedContextType] is used below.
       bool isIterable = typeSystem.isSubtypeOf(
-          unwrappedContextType, _iterableForSetMapDisambiguation);
+          unwrappedContextType, typeProvider.iterableForSetMapDisambiguation);
       bool isMap = typeSystem.isSubtypeOf(
-          unwrappedContextType, _mapForSetMapDisambiguation);
+          unwrappedContextType, typeProvider.mapForSetMapDisambiguation);
       if (isIterable && !isMap) {
         return _LiteralResolution(
             _LiteralResolutionKind.set, unwrappedContextType);
@@ -4604,7 +4590,7 @@
       // Get back to the uninstantiated generic constructor.
       // TODO(jmesserly): should we store this earlier in resolution?
       // Or look it up, instead of jumping backwards through the Member?
-      var rawElement = originalElement.baseElement;
+      var rawElement = originalElement.declaration;
 
       FunctionType constructorType =
           StaticTypeAnalyzer.constructorToGenericFunctionType(rawElement);
@@ -4834,7 +4820,7 @@
   final Source source;
 
   /// The object used to access the types from the core library.
-  final TypeProvider typeProvider;
+  final TypeProviderImpl typeProvider;
 
   /// The error reporter that will be informed of any errors that are found
   /// during resolution.
@@ -6292,6 +6278,9 @@
 /// The interface `TypeProvider` defines the behavior of objects that provide
 /// access to types defined by the language.
 abstract class TypeProvider {
+  /// Return the element representing the built-in class 'bool'.
+  ClassElement get boolElement;
+
   /// Return the type representing the built-in type 'bool'.
   InterfaceType get boolType;
 
@@ -6301,6 +6290,9 @@
   /// Return the type representing the built-in type 'Deprecated'.
   InterfaceType get deprecatedType;
 
+  /// Return the element representing the built-in class 'double'.
+  ClassElement get doubleElement;
+
   /// Return the type representing the built-in type 'double'.
   InterfaceType get doubleType;
 
@@ -6333,6 +6325,9 @@
   @Deprecated('Use futureType2() instead.')
   InterfaceType get futureType;
 
+  /// Return the element representing the built-in class 'int'.
+  ClassElement get intElement;
+
   /// Return the type representing the built-in type 'int'.
   InterfaceType get intType;
 
@@ -6371,14 +6366,25 @@
 
   /// Return a list containing all of the types that cannot be either extended
   /// or implemented.
+  Set<ClassElement> get nonSubtypableClasses;
+
+  /// Return a list containing all of the types that cannot be either extended
+  /// or implemented.
+  @Deprecated('Use nonSubtypableClasses instead.')
   List<InterfaceType> get nonSubtypableTypes;
 
+  /// Return the element representing the built-in class 'null'.
+  ClassElement get nullElement;
+
   /// Return a [DartObjectImpl] representing the `null` object.
   DartObjectImpl get nullObject;
 
   /// Return the type representing the built-in type 'Null'.
   InterfaceType get nullType;
 
+  /// Return the element representing the built-in class 'num'.
+  ClassElement get numElement;
+
   /// Return the type representing the built-in type 'num'.
   InterfaceType get numType;
 
@@ -6405,6 +6411,9 @@
   @Deprecated('Use streamType2() instead.')
   InterfaceType get streamType;
 
+  /// Return the element representing the built-in class 'String'.
+  ClassElement get stringElement;
+
   /// Return the type representing the built-in type 'String'.
   InterfaceType get stringType;
 
@@ -6882,7 +6891,16 @@
       return;
     }
 
-    Element element = identifier.staticElement;
+    // This is the same logic used in [checkForDeprecatedMemberUseAtIdentifier]
+    // to avoid reporting an error twice for named constructors.
+    AstNode parent = identifier.parent;
+    if (parent is ConstructorName && identical(identifier, parent.name)) {
+      return;
+    }
+    AstNode grandparent = parent?.parent;
+    Element element = grandparent is ConstructorName
+        ? grandparent.staticElement
+        : identifier.staticElement;
     if (element == null || _inCurrentLibrary(element)) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 33f39c3..6ed57e1 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -339,13 +339,15 @@
       pkgDir = pkgDir.getCanonicalFile();
     } catch (exception, stackTrace) {
       if (!exception.toString().contains("Required key not available")) {
+        // TODO(39284): should this exception be silent?
         AnalysisEngine.instance.instrumentationService.logException(
-            new CaughtException.withMessage(
+            new SilentException(
                 "Canonical failed: $pkgDir", exception, stackTrace));
       } else if (_CanLogRequiredKeyIoException) {
         _CanLogRequiredKeyIoException = false;
+        // TODO(39284): should this exception be silent?
         AnalysisEngine.instance.instrumentationService.logException(
-            new CaughtException.withMessage(
+            new SilentException(
                 "Canonical failed: $pkgDir", exception, stackTrace));
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index e4ba3a4..ff85dcb 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -47,7 +48,7 @@
   /**
    * The object providing access to the types defined by the language.
    */
-  TypeProvider _typeProvider;
+  TypeProviderImpl _typeProvider;
 
   /**
    * The type system in use for static type analysis.
@@ -70,9 +71,6 @@
    */
   DartType thisType;
 
-  InterfaceType _iterableForSetMapDisambiguationCached;
-  InterfaceType _mapForSetMapDisambiguationCached;
-
   /**
    * The object providing promoted or declared types of variables.
    */
@@ -96,31 +94,6 @@
     _strictInference = analysisOptions.strictInference;
   }
 
-  InterfaceType get _iterableForSetMapDisambiguation {
-    return _iterableForSetMapDisambiguationCached ??=
-        _typeProvider.iterableElement.instantiate(
-      typeArguments: [
-        _typeProvider.dynamicType,
-      ],
-      nullabilitySuffix: _nonNullableEnabled
-          ? NullabilitySuffix.question
-          : NullabilitySuffix.star,
-    );
-  }
-
-  InterfaceType get _mapForSetMapDisambiguation {
-    return _mapForSetMapDisambiguationCached ??=
-        _typeProvider.mapElement.instantiate(
-      typeArguments: [
-        _typeProvider.dynamicType,
-        _typeProvider.dynamicType,
-      ],
-      nullabilitySuffix: _nonNullableEnabled
-          ? NullabilitySuffix.question
-          : NullabilitySuffix.star,
-    );
-  }
-
   NullabilitySuffix get _noneOrStarSuffix {
     return _nonNullableEnabled
         ? NullabilitySuffix.none
@@ -1449,35 +1422,6 @@
     return returnType.type;
   }
 
-  /// If [node] is a null-shorting expression, updates flow analysis as
-  /// appropriate to finish the null shorting, and returns `true`.  Otherwise
-  /// returns `false`.
-  bool _finishNullShorting(Expression node) {
-    bool nullShortingFound = false;
-    while (true) {
-      Expression next;
-      if (node is AssignmentExpression) {
-        next = node.leftHandSide;
-      } else if (node is IndexExpression) {
-        if (node.isNullAware) {
-          nullShortingFound = true;
-          _flowAnalysis?.flow?.nullAwareAccess_end();
-        }
-        next = node.target;
-      } else if (node is PropertyAccess) {
-        if (node.isNullAware) {
-          nullShortingFound = true;
-          _flowAnalysis?.flow?.nullAwareAccess_end();
-        }
-        next = node.target;
-      } else {
-        break;
-      }
-      node = next;
-    }
-    return nullShortingFound;
-  }
-
   /**
    * If the given element name can be mapped to the name of a class defined within the given
    * library, return the type specified by the argument.
@@ -1636,7 +1580,7 @@
       bool isNull = expressionType.isDartCoreNull;
       if (!isNull && expressionType is InterfaceType) {
         if (_typeSystem.isSubtypeOf(
-            expressionType, _typeProvider.iterableObjectType)) {
+            expressionType, _typeProvider.iterableForSetMapDisambiguation)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.iterableElement);
           return _InferredCollectionElementTypeInformation(
@@ -1644,7 +1588,7 @@
               keyType: null,
               valueType: null);
         } else if (_typeSystem.isSubtypeOf(
-            expressionType, _typeProvider.mapObjectObjectType)) {
+            expressionType, _typeProvider.mapForSetMapDisambiguation)) {
           InterfaceType mapType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.mapElement);
           List<DartType> typeArguments = mapType.typeArguments;
@@ -1786,7 +1730,7 @@
     // Get back to the uninstantiated generic constructor.
     // TODO(jmesserly): should we store this earlier in resolution?
     // Or look it up, instead of jumping backwards through the Member?
-    var rawElement = (originalElement as ConstructorMember).baseElement;
+    var rawElement = originalElement.declaration;
 
     FunctionType constructorType = constructorToGenericFunctionType(rawElement);
 
@@ -1899,14 +1843,19 @@
   // node's argumentList. (This likely affects only explicit calls to
   // `Object.noSuchMethod`.)
   bool _inferMethodInvocationObject(MethodInvocation node) {
-    // If we have a call like `toString()` or `libraryPrefix.toString()` don't
+    // If we have a call like `toString()` or `libraryPrefix.toString()`, don't
     // infer it.
     Expression target = node.realTarget;
     if (target == null ||
         target is SimpleIdentifier && target.staticElement is PrefixElement) {
       return false;
     }
-
+    DartType nodeType = node.staticInvokeType;
+    if (nodeType == null ||
+        !nodeType.isDynamic ||
+        node.argumentList.arguments.isNotEmpty) {
+      return false;
+    }
     // Object methods called on dynamic targets can have their types improved.
     String name = node.methodName.name;
     MethodElement inferredElement =
@@ -1915,16 +1864,15 @@
       return false;
     }
     DartType inferredType = inferredElement.type;
-    DartType nodeType = node.staticInvokeType;
-    if (nodeType != null &&
-        nodeType.isDynamic &&
-        inferredType is FunctionType &&
-        inferredType.parameters.isEmpty &&
-        node.argumentList.arguments.isEmpty &&
-        _typeProvider.nonSubtypableTypes.contains(inferredType.returnType)) {
-      node.staticInvokeType = inferredType;
-      _recordStaticType(node, inferredType.returnType);
-      return true;
+    if (inferredType is FunctionType) {
+      DartType returnType = inferredType.returnType;
+      if (inferredType.parameters.isEmpty &&
+          returnType is InterfaceType &&
+          _typeProvider.nonSubtypableClasses.contains(returnType.element)) {
+        node.staticInvokeType = inferredType;
+        _recordStaticType(node, inferredType.returnType);
+        return true;
+      }
     }
     return false;
   }
@@ -1953,8 +1901,8 @@
     DartType inferredType = inferredElement.type.returnType;
     if (nodeType != null &&
         nodeType.isDynamic &&
-        inferredType != null &&
-        _typeProvider.nonSubtypableTypes.contains(inferredType)) {
+        inferredType is InterfaceType &&
+        _typeProvider.nonSubtypableClasses.contains(inferredType.element)) {
       _recordStaticType(id, inferredType);
       _recordStaticType(node, inferredType);
       return true;
@@ -1995,9 +1943,11 @@
     bool contextProvidesAmbiguityResolutionClues =
         contextType != null && contextType is! UnknownInferredType;
     bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(contextType, _iterableForSetMapDisambiguation);
+        _typeSystem.isSubtypeOf(
+            contextType, _typeProvider.iterableForSetMapDisambiguation);
     bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(contextType, _mapForSetMapDisambiguation);
+        _typeSystem.isSubtypeOf(
+            contextType, _typeProvider.mapForSetMapDisambiguation);
     if (contextIsIterable && !contextIsMap) {
       return _toSetType(literal, contextType, inferredTypes);
     } else if ((contextIsMap && !contextIsIterable) || elements.isEmpty) {
@@ -2084,20 +2034,12 @@
   void _nullShortingTermination(Expression node) {
     if (!_nonNullableEnabled) return;
 
-    var parent = node.parent;
-    if (parent is AssignmentExpression && parent.leftHandSide == node) {
-      return;
-    }
-    if (parent is PropertyAccess) {
-      return;
-    }
-    if (parent is IndexExpression && parent.target == node) {
-      return;
-    }
-
-    if (_finishNullShorting(node)) {
-      var type = node.staticType;
-      node.staticType = _typeSystem.makeNullable(type);
+    if (identical(_resolver.unfinishedNullShorts.last, node)) {
+      do {
+        _resolver.unfinishedNullShorts.removeLast();
+        _flowAnalysis.flow.nullAwareAccess_end();
+      } while (identical(_resolver.unfinishedNullShorts.last, node));
+      node.staticType = _typeSystem.makeNullable(node.staticType);
     }
   }
 
@@ -2112,7 +2054,7 @@
       expression.staticType = _dynamicType;
     } else {
       expression.staticType = type;
-      if (identical(type, BottomTypeImpl.instance)) {
+      if (identical(type, NeverTypeImpl.instance)) {
         _flowAnalysis?.flow?.handleExit();
       }
     }
@@ -2236,10 +2178,10 @@
       return constructor.type;
     }
 
-    return FunctionTypeImpl.synthetic(
-      constructor.returnType,
-      typeParameters,
-      constructor.parameters,
+    return FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: constructor.parameters,
+      returnType: constructor.returnType,
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 9538549..411503d 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -15,12 +15,10 @@
  * for the core library.
  */
 class TestTypeProvider extends TypeProviderImpl {
-  factory TestTypeProvider([
-    AnalysisContext context,
-    Object analysisDriver,
+  factory TestTypeProvider({
     NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
-  ]) {
-    context ??= _MockAnalysisContext();
+  }) {
+    var context = _MockAnalysisContext();
     var sdkElements = MockSdkElements(context, nullabilitySuffix);
     return TestTypeProvider._(
       nullabilitySuffix,
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index cfebd50..1b841ec 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/error/codes.dart' show HintCode, StrongModeCode;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
@@ -217,7 +218,7 @@
 
     // No subtype relation, so no known GLB.
     // TODO(mfairhurst): implement fully NNBD GLB, and return Never (non-legacy)
-    return BottomTypeImpl.instanceLegacy;
+    return NeverTypeImpl.instanceLegacy;
   }
 
   /**
@@ -634,7 +635,7 @@
     }
 
     // Left Bottom: if `T0` is `Never`, then `T0 <: T1`.
-    if (identical(T0, BottomTypeImpl.instance)) {
+    if (identical(T0, NeverTypeImpl.instance)) {
       return true;
     }
 
@@ -1073,11 +1074,21 @@
 
   /// Check that [f1] is a subtype of [f2].
   bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2) {
-    return FunctionTypeImpl.relate(f1, f2, isSubtypeOf,
-        parameterRelation: (p1, p2) => isSubtypeOf(p2.type, p1.type),
+    return FunctionTypeImpl.relate(
+      f1,
+      f2,
+      isSubtypeOf,
+      parameterRelation: (p1, p2) {
+        if (p1.isRequiredNamed && !p2.isRequiredNamed) {
+          return false;
+        }
+        return isSubtypeOf(p2.type, p1.type);
+      },
+      boundsRelation: (t1, t2, p1, p2) {
         // Type parameter bounds are invariant.
-        boundsRelation: (t1, t2, p1, p2) =>
-            isSubtypeOf(t1, t2) && isSubtypeOf(t2, t1));
+        return isSubtypeOf(t1, t2) && isSubtypeOf(t2, t1);
+      },
+    );
   }
 
   bool _isInterfaceSubtypeOf(
@@ -1097,14 +1108,35 @@
     if (i1Element == i2.element) {
       List<DartType> tArgs1 = i1.typeArguments;
       List<DartType> tArgs2 = i2.typeArguments;
+      List<TypeParameterElement> tParams = i1Element.typeParameters;
 
       assert(tArgs1.length == tArgs2.length);
+      assert(tParams.length == tArgs1.length);
 
       for (int i = 0; i < tArgs1.length; i++) {
         DartType t1 = tArgs1[i];
         DartType t2 = tArgs2[i];
-        if (!isSubtypeOf(t1, t2)) {
-          return false;
+
+        // TODO (kallentu) : Clean up TypeParameterElementImpl checks and
+        // casting once variance is added to the interface.
+        TypeParameterElement parameterElement = tParams[i];
+        Variance variance = Variance.covariant;
+        if (parameterElement is TypeParameterElementImpl) {
+          variance = parameterElement.variance;
+        }
+
+        if (variance.isContravariant) {
+          if (!isSubtypeOf(t2, t1)) {
+            return false;
+          }
+        } else if (variance.isInvariant) {
+          if (!isSubtypeOf(t1, t2) || !isSubtypeOf(t2, t1)) {
+            return false;
+          }
+        } else {
+          if (!isSubtypeOf(t1, t2)) {
+            return false;
+          }
         }
       }
       return true;
@@ -1212,10 +1244,10 @@
         return type;
       }
 
-      return new FunctionTypeImpl.synthetic(
-        newReturnType,
-        type.typeFormals,
-        newParameters,
+      return new FunctionTypeImpl(
+        typeFormals: type.typeFormals,
+        parameters: newParameters,
+        returnType: newReturnType,
         nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
       );
     }
@@ -1355,10 +1387,10 @@
 
     // Since we're trying to infer the instantiation, we want to ignore type
     // formals as we check the parameters and return type.
-    var inferFnType = FunctionTypeImpl.synthetic(
-      fnType.returnType,
-      const [],
-      fnType.parameters,
+    var inferFnType = FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: fnType.parameters,
+      returnType: fnType.returnType,
       nullabilitySuffix: (fnType as TypeImpl).nullabilitySuffix,
     );
     tryMatchSubtypeOf(inferFnType, contextType, origin, covariant: true);
@@ -2099,13 +2131,17 @@
   /// causing pain in real code.  The current algorithm is:
   /// 1. If either of the types is a supertype of the other, return it.
   ///    This is in fact the best result in this case.
-  /// 2. If the two types have the same class element, then take the
-  ///    pointwise least upper bound of the type arguments.  This is again
-  ///    the best result, except that the recursive calls may not return
-  ///    the true least upper bounds.  The result is guaranteed to be a
-  ///    well-formed type under the assumption that the input types were
-  ///    well-formed (and assuming that the recursive calls return
-  ///    well-formed types).
+  /// 2. If the two types have the same class element and are implicitly or
+  ///    explicitly covariant, then take the pointwise least upper bound of
+  ///    the type arguments. This is again the best result, except that the
+  ///    recursive calls may not return the true least upper bounds. The
+  ///    result is guaranteed to be a well-formed type under the assumption
+  ///    that the input types were well-formed (and assuming that the
+  ///    recursive calls return well-formed types).
+  ///    If the variance of the type parameter is contravariant, we take the
+  ///    greatest lower bound of the type arguments. If the variance of the
+  ///    type parameter is invariant, we verify if the type arguments satisfy
+  ///    subtyping in both directions, then choose a bound.
   /// 3. Otherwise return the spec-defined least upper bound.  This will
   ///    be an upper bound, might (or might not) be least, and might
   ///    (or might not) be a well-formed type.
@@ -2131,11 +2167,42 @@
     if (type1.element == type2.element) {
       var args1 = type1.typeArguments;
       var args2 = type2.typeArguments;
-
+      var params = type1.element.typeParameters;
       assert(args1.length == args2.length);
+      assert(args1.length == params.length);
+
       var args = List<DartType>(args1.length);
       for (int i = 0; i < args1.length; i++) {
-        args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+        // TODO (kallentu) : Clean up TypeParameterElementImpl checks and
+        // casting once variance is added to the interface.
+        TypeParameterElement parameter = params[i];
+        Variance parameterVariance = Variance.covariant;
+        if (parameter is TypeParameterElementImpl) {
+          parameterVariance = parameter.variance;
+        }
+
+        if (parameterVariance.isContravariant) {
+          if (typeSystem is Dart2TypeSystem) {
+            args[i] = (typeSystem as Dart2TypeSystem)
+                .getGreatestLowerBound(args1[i], args2[i]);
+          } else {
+            args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+          }
+        } else if (parameterVariance.isInvariant) {
+          if (!typeSystem.isSubtypeOf(args1[i], args2[i]) ||
+              !typeSystem.isSubtypeOf(args2[i], args1[i])) {
+            // No bound will be valid, find bound at the interface level.
+            return _computeLeastUpperBound(
+              InstantiatedClass.of(type1),
+              InstantiatedClass.of(type2),
+            ).withNullability(nullability);
+          }
+          // TODO (kallentu) : Fix asymmetric bounds behavior for invariant type
+          //  parameters.
+          args[i] = args1[i];
+        } else {
+          args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+        }
       }
 
       return new InterfaceTypeImpl.explicit(
@@ -2671,7 +2738,7 @@
   /// Returns a non-nullable version of [type].  This is equivalent to the
   /// operation `NonNull` defined in the spec.
   DartType promoteToNonNull(covariant TypeImpl type) {
-    if (type.isDartCoreNull) return BottomTypeImpl.instance;
+    if (type.isDartCoreNull) return NeverTypeImpl.instance;
 
     if (type is TypeParameterTypeImpl) {
       var element = type.element;
@@ -2902,10 +2969,10 @@
     // Calculate the LUB of the return type.
     DartType returnType = getLeastUpperBound(f.returnType, g.returnType);
 
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeFormals,
-      parameters,
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: (f as TypeImpl).nullabilitySuffix,
     );
   }
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 6268493..35114ca 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -253,9 +253,7 @@
 
 /// Prints logging information comments to the [outSink] and error messages to
 /// [errorSink].
-class StdInstrumentation extends InstrumentationService {
-  StdInstrumentation() : super(null);
-
+class StdInstrumentation extends NoopInstrumentationService {
   @override
   void logError(String message, [exception]) {
     errorSink.writeln(message);
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 0c48fea..6e51f55 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -17,7 +17,6 @@
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions;
@@ -290,11 +289,8 @@
     }
 
     // Ensure that dependencies (e.g. default parameter values) are computed.
-    var implElement = element;
-    if (element is ConstructorMember) {
-      implElement = element.baseElement;
-    }
-    (implElement as ConstructorElementImpl).computeConstantDependencies();
+    ConstructorElementImpl implElement = element.declaration;
+    implElement.computeConstantDependencies();
 
     //
     // Verify that the evaluation of the constructor would not produce an
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index d907895..f702e50 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -3783,9 +3783,9 @@
   String _variantField_30;
   LinkedNodeBuilder _variantField_14;
   idl.LinkedNodeKind _kind;
+  bool _variantField_31;
   List<String> _variantField_34;
   String _name;
-  bool _variantField_31;
   idl.UnlinkedTokenType _variantField_35;
   TopLevelInferenceErrorBuilder _variantField_32;
   LinkedNodeTypeBuilder _variantField_23;
@@ -6695,6 +6695,37 @@
   }
 
   @override
+  bool get methodDeclaration_hasOperatorEqualWithParameterTypeFromObject {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_31 ??= false;
+  }
+
+  @override
+  bool get simplyBoundable_isSimplyBounded {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    return _variantField_31 ??= false;
+  }
+
+  set methodDeclaration_hasOperatorEqualWithParameterTypeFromObject(
+      bool value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_31 = value;
+  }
+
+  set simplyBoundable_isSimplyBounded(bool value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_31 = value;
+  }
+
+  @override
   List<String> get mixinDeclaration_superInvokedNames {
     assert(kind == idl.LinkedNodeKind.mixinDeclaration);
     return _variantField_34 ??= <String>[];
@@ -6728,25 +6759,6 @@
   }
 
   @override
-  bool get simplyBoundable_isSimplyBounded {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_31 ??= false;
-  }
-
-  set simplyBoundable_isSimplyBounded(bool value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_31 = value;
-  }
-
-  @override
   idl.UnlinkedTokenType get spreadElement_spreadOperator {
     assert(kind == idl.LinkedNodeKind.spreadElement);
     return _variantField_35 ??= idl.UnlinkedTokenType.NOTHING;
@@ -7545,6 +7557,7 @@
     LinkedNodeBuilder methodDeclaration_returnType,
     LinkedNodeBuilder methodDeclaration_typeParameters,
     int informativeId,
+    bool methodDeclaration_hasOperatorEqualWithParameterTypeFromObject,
   })  : _kind = idl.LinkedNodeKind.methodDeclaration,
         _variantField_24 = actualReturnType,
         _variantField_4 = annotatedNode_metadata,
@@ -7552,7 +7565,9 @@
         _variantField_7 = methodDeclaration_formalParameters,
         _variantField_8 = methodDeclaration_returnType,
         _variantField_9 = methodDeclaration_typeParameters,
-        _variantField_36 = informativeId;
+        _variantField_36 = informativeId,
+        _variantField_31 =
+            methodDeclaration_hasOperatorEqualWithParameterTypeFromObject;
 
   LinkedNodeBuilder.methodInvocation({
     LinkedNodeTypeBuilder invocationExpression_invokeType,
@@ -7576,8 +7591,8 @@
     List<LinkedNodeBuilder> classOrMixinDeclaration_members,
     LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
     int informativeId,
-    List<String> mixinDeclaration_superInvokedNames,
     bool simplyBoundable_isSimplyBounded,
+    List<String> mixinDeclaration_superInvokedNames,
   })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = mixinDeclaration_onClause,
@@ -7585,8 +7600,8 @@
         _variantField_5 = classOrMixinDeclaration_members,
         _variantField_13 = classOrMixinDeclaration_typeParameters,
         _variantField_36 = informativeId,
-        _variantField_34 = mixinDeclaration_superInvokedNames,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
+        _variantField_31 = simplyBoundable_isSimplyBounded,
+        _variantField_34 = mixinDeclaration_superInvokedNames;
 
   LinkedNodeBuilder.namedExpression({
     LinkedNodeBuilder namedExpression_expression,
@@ -9412,6 +9427,9 @@
       signature.addInt(this.flags ?? 0);
       signature.addBool(this.actualReturnType != null);
       this.actualReturnType?.collectApiSignature(signature);
+      signature.addBool(
+          this.methodDeclaration_hasOperatorEqualWithParameterTypeFromObject ==
+              true);
       signature.addString(this.name ?? '');
     } else if (kind == idl.LinkedNodeKind.methodInvocation) {
       signature.addInt(this.kind == null ? 0 : this.kind.index);
@@ -10200,15 +10218,15 @@
     if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
       fbBuilder.addUint8(0, _kind.index);
     }
+    if (_variantField_31 == true) {
+      fbBuilder.addBool(31, true);
+    }
     if (offset_variantField_34 != null) {
       fbBuilder.addOffset(34, offset_variantField_34);
     }
     if (offset_name != null) {
       fbBuilder.addOffset(37, offset_name);
     }
-    if (_variantField_31 == true) {
-      fbBuilder.addBool(31, true);
-    }
     if (_variantField_35 != null &&
         _variantField_35 != idl.UnlinkedTokenType.NOTHING) {
       fbBuilder.addUint8(35, _variantField_35.index);
@@ -10279,9 +10297,9 @@
   String _variantField_30;
   idl.LinkedNode _variantField_14;
   idl.LinkedNodeKind _kind;
+  bool _variantField_31;
   List<String> _variantField_34;
   String _name;
-  bool _variantField_31;
   idl.UnlinkedTokenType _variantField_35;
   idl.TopLevelInferenceError _variantField_32;
   idl.LinkedNodeType _variantField_23;
@@ -12378,6 +12396,26 @@
   }
 
   @override
+  bool get methodDeclaration_hasOperatorEqualWithParameterTypeFromObject {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_31 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 31, false);
+    return _variantField_31;
+  }
+
+  @override
+  bool get simplyBoundable_isSimplyBounded {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_31 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 31, false);
+    return _variantField_31;
+  }
+
+  @override
   List<String> get mixinDeclaration_superInvokedNames {
     assert(kind == idl.LinkedNodeKind.mixinDeclaration);
     _variantField_34 ??= const fb.ListReader<String>(const fb.StringReader())
@@ -12402,18 +12440,6 @@
   }
 
   @override
-  bool get simplyBoundable_isSimplyBounded {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_31 ??=
-        const fb.BoolReader().vTableGet(_bc, _bcOffset, 31, false);
-    return _variantField_31;
-  }
-
-  @override
   idl.UnlinkedTokenType get spreadElement_spreadOperator {
     assert(kind == idl.LinkedNodeKind.spreadElement);
     _variantField_35 ??= const _UnlinkedTokenTypeReader()
@@ -13271,6 +13297,10 @@
         _result["methodDeclaration_typeParameters"] =
             methodDeclaration_typeParameters.toJson();
       if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (methodDeclaration_hasOperatorEqualWithParameterTypeFromObject !=
+          false)
+        _result["methodDeclaration_hasOperatorEqualWithParameterTypeFromObject"] =
+            methodDeclaration_hasOperatorEqualWithParameterTypeFromObject;
     }
     if (kind == idl.LinkedNodeKind.methodInvocation) {
       if (invocationExpression_invokeType != null)
@@ -13309,12 +13339,12 @@
         _result["classOrMixinDeclaration_typeParameters"] =
             classOrMixinDeclaration_typeParameters.toJson();
       if (informativeId != 0) _result["informativeId"] = informativeId;
-      if (mixinDeclaration_superInvokedNames.isNotEmpty)
-        _result["mixinDeclaration_superInvokedNames"] =
-            mixinDeclaration_superInvokedNames;
       if (simplyBoundable_isSimplyBounded != false)
         _result["simplyBoundable_isSimplyBounded"] =
             simplyBoundable_isSimplyBounded;
+      if (mixinDeclaration_superInvokedNames.isNotEmpty)
+        _result["mixinDeclaration_superInvokedNames"] =
+            mixinDeclaration_superInvokedNames;
     }
     if (kind == idl.LinkedNodeKind.namedExpression) {
       if (namedExpression_expression != null)
@@ -13834,8 +13864,8 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+        "name": name,
         "unused11": unused11,
       };
     }
@@ -13849,8 +13879,8 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.comment) {
@@ -14253,8 +14283,8 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
@@ -14298,8 +14328,8 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.hideCombinator) {
@@ -14482,6 +14512,8 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
+        "methodDeclaration_hasOperatorEqualWithParameterTypeFromObject":
+            methodDeclaration_hasOperatorEqualWithParameterTypeFromObject,
         "name": name,
       };
     }
@@ -14511,10 +14543,10 @@
         "flags": flags,
         "informativeId": informativeId,
         "kind": kind,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
         "mixinDeclaration_superInvokedNames":
             mixinDeclaration_superInvokedNames,
         "name": name,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
     if (kind == idl.LinkedNodeKind.namedExpression) {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 9f3bf60..f65b42b 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1103,12 +1103,12 @@
 
   kind:LinkedNodeKind (id: 0);
 
+  variantField_31:bool (id: 31);
+
   variantField_34:[string] (id: 34);
 
   name:string (id: 37);
 
-  variantField_31:bool (id: 31);
-
   variantField_35:UnlinkedTokenType (id: 35);
 
   variantField_32:TopLevelInferenceError (id: 32);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index be60016..d6a9a31 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1202,6 +1202,9 @@
   @VariantId(7, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_formalParameters;
 
+  @VariantId(31, variant: LinkedNodeKind.methodDeclaration)
+  bool get methodDeclaration_hasOperatorEqualWithParameterTypeFromObject;
+
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
index 42ffe5c..b866a53 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
@@ -407,7 +407,7 @@
   }
 
   static bool hasQuestion(int flags) {
-    return (flags & _isStringInterpolationIdentifier) != 0;
+    return (flags & _hasQuestion) != 0;
   }
 
   static bool hasSeparatorColon(int flags) {
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 232ab13..5677f4b9 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -1168,6 +1168,10 @@
       body,
     );
     LazyMethodDeclaration.setData(node, data);
+    LazyAst.setOperatorEqualParameterTypeFromObject(
+      node,
+      data.methodDeclaration_hasOperatorEqualWithParameterTypeFromObject,
+    );
     return node;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 6bca136..a1cb51c 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -945,6 +945,8 @@
       methodDeclaration_returnType: node.returnType?.accept(this),
       methodDeclaration_typeParameters: node.typeParameters?.accept(this),
       methodDeclaration_formalParameters: node.parameters?.accept(this),
+      methodDeclaration_hasOperatorEqualWithParameterTypeFromObject:
+          LazyAst.hasOperatorEqualParameterTypeFromObject(node),
     );
     builder.name = node.name.name;
     builder.flags = AstBinaryFlags.encode(
@@ -1463,12 +1465,12 @@
   }
 
   _ElementComponents _componentsOfElement(Element element) {
-    while (element is ParameterMember) {
-      element = (element as ParameterMember).baseElement;
+    if (element is ParameterMember) {
+      element = element.declaration;
     }
 
     if (element is Member) {
-      var elementIndex = _indexOfElement(element.baseElement);
+      var elementIndex = _indexOfElement(element.declaration);
       var substitution = element.substitution.map;
       var substitutionBuilder = LinkedNodeTypeSubstitutionBuilder(
         typeParameters: substitution.keys.map(_indexOfElement).toList(),
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index d170f4a..b1119fa 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -73,10 +73,10 @@
     }
 
     var builtReturnType = _buildType(returnType);
-    _type = FunctionTypeImpl.synthetic(
-      builtReturnType,
-      typeFormals,
-      parameters,
+    _type = FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: builtReturnType,
       nullabilitySuffix: nullabilitySuffix,
     );
 
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 179133d..2ab0887 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -19,6 +19,8 @@
   static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
   static const _inheritsCovariantKey = 'lazyAst_isCovariant';
   static const _isSimplyBoundedKey = 'lazyAst_simplyBounded';
+  static const _isOperatorEqualParameterTypeFromObjectKey =
+      'lazyAst_isOperatorEqualParameterTypeFromObject';
   static const _rawFunctionTypeKey = 'lazyAst_rawFunctionType';
   static const _returnTypeKey = 'lazyAst_returnType';
   static const _typeInferenceErrorKey = 'lazyAst_typeInferenceError';
@@ -56,6 +58,11 @@
     return node.getProperty(_typeInferenceErrorKey);
   }
 
+  static bool hasOperatorEqualParameterTypeFromObject(AstNode node) {
+    return node.getProperty(_isOperatorEqualParameterTypeFromObjectKey) ??
+        false;
+  }
+
   static bool hasOverrideInferenceDone(AstNode node) {
     return node.getProperty(_hasOverrideInferenceKey) ?? false;
   }
@@ -76,6 +83,10 @@
     node.setProperty(_inheritsCovariantKey, value);
   }
 
+  static void setOperatorEqualParameterTypeFromObject(AstNode node, bool b) {
+    node.setProperty(_isOperatorEqualParameterTypeFromObjectKey, b);
+  }
+
   static void setOverrideInferenceDone(AstNode node) {
     node.setProperty(_hasOverrideInferenceKey, true);
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 47b48b1..8a60db6 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -731,6 +731,10 @@
     return LazyVariableDeclaration.hasInitializer(node);
   }
 
+  bool hasOperatorEqualParameterTypeFromObject(MethodDeclaration node) {
+    return LazyAst.hasOperatorEqualParameterTypeFromObject(node);
+  }
+
   bool hasOverrideInferenceDone(AstNode node) {
     // Only nodes in the libraries being linked might be not inferred yet.
     if (_astReader.isLazy) return true;
@@ -743,6 +747,8 @@
       return node.abstractKeyword != null;
     } else if (node is ClassTypeAlias) {
       return node.abstractKeyword != null;
+    } else if (node is ConstructorDeclaration) {
+      return false;
     } else if (node is FunctionDeclaration) {
       return false;
     } else if (node is MethodDeclaration) {
@@ -902,7 +908,7 @@
     var kind = linkedType.kind;
     if (kind == LinkedNodeTypeKind.bottom) {
       var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
-      return BottomTypeImpl.instance.withNullability(nullabilitySuffix);
+      return NeverTypeImpl.instance.withNullability(nullabilitySuffix);
     } else if (kind == LinkedNodeTypeKind.dynamic_) {
       return DynamicTypeImpl.instance;
     } else if (kind == LinkedNodeTypeKind.function) {
@@ -947,13 +953,13 @@
 
       var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
 
-      return FunctionTypeImpl.synthetic(
-        returnType,
-        typeParameters,
-        formalParameters,
+      return FunctionTypeImpl(
+        typeFormals: typeParameters,
+        parameters: formalParameters,
+        returnType: returnType,
+        nullabilitySuffix: nullabilitySuffix,
         element: typedefElement,
         typeArguments: typedefTypeArguments,
-        nullabilitySuffix: nullabilitySuffix,
       );
     } else if (kind == LinkedNodeTypeKind.interface) {
       var element = bundleContext.elementOfIndex(linkedType.interfaceClass);
@@ -997,6 +1003,10 @@
     }
   }
 
+  void setOperatorEqualParameterTypeFromObject(AstNode node, bool value) {
+    LazyAst.setOperatorEqualParameterTypeFromObject(node, value);
+  }
+
   void setOverrideInferenceDone(AstNode node) {
     // TODO(scheglov) This assert fails, check how to avoid this.
 //    assert(!_astReader.isLazy);
diff --git a/pkg/analyzer/lib/src/summary2/named_type_builder.dart b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
index b44a12a..39b6ef7 100644
--- a/pkg/analyzer/lib/src/summary2/named_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
@@ -78,19 +78,19 @@
         var arguments = _buildArguments(parameters);
         var substitution = Substitution.fromPairs(parameters, arguments);
         var instantiated = substitution.substituteType(rawType) as FunctionType;
-        _type = FunctionTypeImpl.synthetic(
-          instantiated.returnType,
-          instantiated.typeFormals,
-          instantiated.parameters,
+        _type = FunctionTypeImpl(
+          typeFormals: instantiated.typeFormals,
+          parameters: instantiated.parameters,
+          returnType: instantiated.returnType,
+          nullabilitySuffix: nullabilitySuffix,
           element: element,
           typeArguments: arguments,
-          nullabilitySuffix: nullabilitySuffix,
         );
       } else {
         _type = _dynamicType;
       }
     } else if (element is NeverElementImpl) {
-      _type = BottomTypeImpl.instance.withNullability(nullabilitySuffix);
+      _type = NeverTypeImpl.instance.withNullability(nullabilitySuffix);
     } else if (element is TypeParameterElement) {
       _type = TypeParameterTypeImpl(
         element,
@@ -188,10 +188,10 @@
       );
     }).toList();
 
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      formalParameters,
+    return FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: formalParameters,
+      returnType: returnType,
       nullabilitySuffix: _getNullabilitySuffix(hasQuestion),
     );
   }
@@ -200,10 +200,10 @@
     if (node != null) {
       return _buildType(node?.type);
     } else {
-      return FunctionTypeImpl.synthetic(
-        _dynamicType,
-        const <TypeParameterElement>[],
-        const <ParameterElement>[],
+      return FunctionTypeImpl(
+        typeFormals: const <TypeParameterElement>[],
+        parameters: const <ParameterElement>[],
+        returnType: _dynamicType,
         nullabilitySuffix: NullabilitySuffix.none,
       );
     }
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index d4b7b0c..4914569 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -227,13 +226,9 @@
 
   @override
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    var element = node.staticElement;
+    var element = node.staticElement?.declaration;
     if (element == null) return;
 
-    if (element is ConstructorMember) {
-      element = (element as ConstructorMember).baseElement;
-    }
-
     _set.add(element);
 
     if (element.enclosingElement.typeParameters.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/summary2/type_alias.dart b/pkg/analyzer/lib/src/summary2/type_alias.dart
index 617c152..0ee7be4 100644
--- a/pkg/analyzer/lib/src/summary2/type_alias.dart
+++ b/pkg/analyzer/lib/src/summary2/type_alias.dart
@@ -55,11 +55,10 @@
     }
     node.functionType.returnType = null;
     node.functionType.parameters.parameters.clear();
-    (node.functionType as GenericFunctionTypeImpl).type =
-        FunctionTypeImpl.synthetic(
-      DynamicTypeImpl.instance,
-      [],
-      [],
+    (node.functionType as GenericFunctionTypeImpl).type = FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: const [],
+      returnType: DynamicTypeImpl.instance,
       nullabilitySuffix: _unitNullability,
     );
   }
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index dfda000..bc7fe97 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -77,10 +77,10 @@
       );
     }).toList();
 
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      formalParameters,
+    return FunctionTypeImpl(
+      typeFormals: typeParameters,
+      parameters: formalParameters,
+      returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
     );
   }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 6b90f74..2f88f6f 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -890,8 +890,7 @@
       // This member will need a check, however, because we are calling through
       // an unsafe target.
       if (element.isPrivate && element.parameters.isNotEmpty) {
-        _covariantPrivateMembers
-            .add(element is ExecutableMember ? element.baseElement : element);
+        _covariantPrivateMembers.add(element.declaration);
       }
 
       // Get the lower bound of the declared return type (e.g. `F<bottom>`) and
@@ -903,16 +902,14 @@
       // parameters are properly substituted.
       var classElement = targetType.element;
 
-      var rawElement =
-          (element is ExecutableMember) ? element.baseElement : element;
+      var rawElement = element.declaration;
       var rawReturnType = rawElement.returnType;
 
       // Check if the return type uses a class type parameter contravariantly.
       bool needsCheck = false;
       for (var typeParameter in classElement.typeParameters) {
-        var variance = computeVariance(typeParameter, rawReturnType);
-        if (variance == Variance.contravariant ||
-            variance == Variance.invariant) {
+        var variance = Variance(typeParameter, rawReturnType);
+        if (variance.isContravariant || variance.isInvariant) {
           needsCheck = true;
           break;
         }
@@ -1692,17 +1689,9 @@
 
   static Set<Element> _createCovariantCheckSet() {
     return new LinkedHashSet(
-        equals: _equalMemberElements, hashCode: _hashCodeMemberElements);
-  }
-
-  /// When finding superclass covariance checks, we need to track the
-  /// substituted member/parameter type, but we don't want this type to break
-  /// equality, because [Member] does not implement equality/hashCode, so
-  /// instead we jump to the declaring element.
-  static bool _equalMemberElements(Element x, Element y) {
-    x = x is Member ? x.baseElement : x;
-    y = y is Member ? y.baseElement : y;
-    return x == y;
+      equals: (a, b) => a.declaration == b.declaration,
+      hashCode: (e) => e.declaration.hashCode,
+    );
   }
 
   /// Find all generic interfaces that are implemented by [element], including
@@ -1766,11 +1755,6 @@
     }
     return members;
   }
-
-  static int _hashCodeMemberElements(Element x) {
-    x = x is Member ? x.baseElement : x;
-    return x.hashCode;
-  }
 }
 
 class _TopLevelInitializerValidator extends RecursiveAstVisitor<void> {
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index cd8c597..63503b2 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -23,6 +23,7 @@
   final InheritanceManager3 inheritance;
   final Set<ClassElement> elementsBeingInferred = new HashSet<ClassElement>();
 
+  bool isNonNullableLibrary;
   InterfaceType interfaceType;
 
   /**
@@ -35,6 +36,7 @@
    * compilation [unit].
    */
   void inferCompilationUnit(CompilationUnitElement unit) {
+    isNonNullableLibrary = unit.library.isNonNullableByDefault;
     _inferClasses(unit.mixins);
     _inferClasses(unit.types);
   }
@@ -325,7 +327,7 @@
    * getter or setter, infer the return type and any parameter type(s) where
    * they were not provided.
    */
-  void _inferExecutable(ExecutableElement element) {
+  void _inferExecutable(MethodElementImpl element) {
     if (element.isSynthetic || element.isStatic) {
       return;
     }
@@ -351,11 +353,8 @@
     // Infer the return type.
     //
     if (element.hasImplicitReturnType && element.displayName != '[]=') {
-      (element as ExecutableElementImpl).returnType =
+      element.returnType =
           _computeReturnType(overriddenTypes.map((t) => t.returnType));
-      if (element is PropertyAccessorElement) {
-        _updateSyntheticVariableType(element);
-      }
     }
     //
     // Infer the parameter types.
@@ -369,12 +368,11 @@
 
         if (parameter.hasImplicitType) {
           parameter.type = _computeParameterType(parameter, i, overriddenTypes);
-          if (element is PropertyAccessorElement) {
-            _updateSyntheticVariableType(element);
-          }
         }
       }
     }
+
+    _resetOperatorEqualParameterTypeToDynamic(element, overriddenElements);
   }
 
   /**
@@ -447,6 +445,56 @@
     }
   }
 
+  /// In legacy mode, an override of `operator==` with no explicit parameter
+  /// type inherits the parameter type of the overridden method if any override
+  /// of `operator==` between the overriding method and `Object.==` has an
+  /// explicit parameter type.  Otherwise, the parameter type of the
+  /// overriding method is `dynamic`.
+  ///
+  /// https://github.com/dart-lang/language/issues/569
+  void _resetOperatorEqualParameterTypeToDynamic(
+    MethodElementImpl element,
+    List<ExecutableElement> overriddenElements,
+  ) {
+    if (element.name != '==') return;
+
+    var parameters = element.parameters;
+    if (parameters.length != 1) {
+      element.isOperatorEqualWithParameterTypeFromObject = false;
+      return;
+    }
+
+    ParameterElementImpl parameter = parameters[0];
+    if (!parameter.hasImplicitType) {
+      element.isOperatorEqualWithParameterTypeFromObject = false;
+      return;
+    }
+
+    for (MethodElement overridden in overriddenElements) {
+      overridden = overridden.declaration;
+
+      // Skip Object itself.
+      var enclosingElement = overridden.enclosingElement;
+      if (enclosingElement is ClassElement &&
+          enclosingElement.isDartCoreObject) {
+        continue;
+      }
+
+      // Keep the type if it is not directly from Object.
+      if (overridden is MethodElementImpl &&
+          !overridden.isOperatorEqualWithParameterTypeFromObject) {
+        element.isOperatorEqualWithParameterTypeFromObject = false;
+        return;
+      }
+    }
+
+    // Reset the type.
+    if (!isNonNullableLibrary) {
+      parameter.type = typeProvider.dynamicType;
+    }
+    element.isOperatorEqualWithParameterTypeFromObject = true;
+  }
+
   /**
    * Return the [FunctionType] of the [overriddenElement] that [element]
    * overrides. Return `null`, in case of type parameters inconsistency.
@@ -493,33 +541,6 @@
     }
     return overriddenTypes;
   }
-
-  /**
-   * If the given [element] is a non-synthetic getter or setter, update its
-   * synthetic variable's type to match the getter's return type, or if no
-   * corresponding getter exists, use the setter's parameter type.
-   *
-   * In general, the type of the synthetic variable should not be used, because
-   * getters and setters are independent methods. But this logic matches what
-   * `TypeResolverVisitor.visitMethodDeclaration` would fill in there.
-   */
-  void _updateSyntheticVariableType(PropertyAccessorElement element) {
-    assert(!element.isSynthetic);
-    PropertyAccessorElement getter = element;
-    if (element.isSetter) {
-      // See if we can find any getter.
-      getter = element.correspondingGetter;
-    }
-    DartType newType;
-    if (getter != null) {
-      newType = getter.returnType;
-    } else if (element.isSetter && element.parameters.isNotEmpty) {
-      newType = element.parameters[0].type;
-    }
-    if (newType != null) {
-      (element.variable as VariableElementImpl).type = newType;
-    }
-  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 5d6413f..2ae5993 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -411,7 +411,7 @@
   int get hashCode => 0;
   Type get runtimeType => null;
 
-  bool operator ==(other) => identical(this, other);
+  bool operator ==(Object other) => identical(this, other);
 
   String toString() => 'a string';
   dynamic noSuchMethod(Invocation invocation) => null;
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
index ccc3b5e..e442dec 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
@@ -972,10 +972,10 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeFormals,
-      parameters,
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
     );
   }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5e16cc2..816ee39 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -14,10 +14,8 @@
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.29
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
-  kernel: 0.3.29
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 4e274a6..d5cf46c 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1196,112 +1196,6 @@
     ]);
   }
 
-  test_extendsDisallowedClass_class_bool() async {
-    await assertErrorsInCode('''
-class A extends bool {}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
-    ]);
-  }
-
-  test_extendsDisallowedClass_class_double() async {
-    await assertErrorsInCode('''
-class A extends double {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
-    ]);
-  }
-
-  test_extendsDisallowedClass_class_int() async {
-    await assertErrorsInCode('''
-class A extends int {}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
-    ]);
-  }
-
-  test_extendsDisallowedClass_class_Null() async {
-    await assertErrorsInCode('''
-class A extends Null {}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
-    ]);
-  }
-
-  test_extendsDisallowedClass_class_num() async {
-    await assertErrorsInCode('''
-class A extends num {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
-    ]);
-  }
-
-  test_extendsDisallowedClass_class_String() async {
-    await assertErrorsInCode('''
-class A extends String {}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_bool() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = bool with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_double() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = double with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_int() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = int with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_Null() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = Null with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_num() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = num with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
-    ]);
-  }
-
-  test_extendsDisallowedClass_classTypeAlias_String() async {
-    await assertErrorsInCode(r'''
-class M {}
-class C = String with M;
-''', [
-      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
-    ]);
-  }
-
   test_extraPositionalArguments_const() async {
     await assertErrorsInCode(r'''
 class A {
@@ -1732,134 +1626,6 @@
     ]);
   }
 
-  test_implementsDisallowedClass_class_bool() async {
-    await assertErrorsInCode('''
-class A implements bool {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_double() async {
-    await assertErrorsInCode('''
-class A implements double {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_int() async {
-    await assertErrorsInCode('''
-class A implements int {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_Null() async {
-    await assertErrorsInCode('''
-class A implements Null {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_num() async {
-    await assertErrorsInCode('''
-class A implements num {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_String() async {
-    await assertErrorsInCode('''
-class A implements String {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
-    ]);
-  }
-
-  test_implementsDisallowedClass_class_String_num() async {
-    await assertErrorsInCode('''
-class A implements String, num {}
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 27, 3),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_bool() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements bool;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_double() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements double;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_int() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements int;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_Null() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements Null;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_num() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements num;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_String() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements String;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
-    ]);
-  }
-
-  test_implementsDisallowedClass_classTypeAlias_String_num() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class C = A with M implements String, num;
-''', [
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
-      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 60, 3),
-    ]);
-  }
-
   test_implementsNonClass_class() async {
     await assertErrorsInCode(r'''
 int A;
@@ -2951,118 +2717,6 @@
     ]);
   }
 
-  test_mixinOfDisallowedClass_class_bool() async {
-    await assertErrorsInCode('''
-class A extends Object with bool {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_class_double() async {
-    await assertErrorsInCode('''
-class A extends Object with double {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_class_int() async {
-    await assertErrorsInCode('''
-class A extends Object with int {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_class_Null() async {
-    await assertErrorsInCode('''
-class A extends Object with Null {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_class_num() async {
-    await assertErrorsInCode('''
-class A extends Object with num {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_class_String() async {
-    await assertErrorsInCode('''
-class A extends Object with String {}
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_bool() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with bool;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_double() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with double;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_int() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with int;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_Null() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with Null;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_num() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with num;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_String() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with String;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
-    ]);
-  }
-
-  test_mixinOfDisallowedClass_classTypeAlias_String_num() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C = A with String, num;
-''', [
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
-      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 36, 3),
-    ]);
-  }
-
   test_mixinOfNonClass() async {
     // TODO(brianwilkerson) Compare with MIXIN_WITH_NON_CLASS_SUPERCLASS.
     // TODO(brianwilkerson) Fix the offset and length.
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index a13cddc..cff157f 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:meta/meta.dart';
@@ -14,6 +15,12 @@
 mixin ElementsTypesMixin {
   DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
 
+  NeverTypeImpl get neverNone => NeverTypeImpl.instance;
+
+  NeverTypeImpl get neverQuestion => NeverTypeImpl.instanceNullable;
+
+  NeverTypeImpl get neverStar => NeverTypeImpl.instanceLegacy;
+
   TypeProvider get typeProvider;
 
   ClassElementImpl class_({
@@ -40,10 +47,10 @@
     @required DartType returnType,
     @required NullabilitySuffix nullabilitySuffix,
   }) {
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeFormals,
-      parameters,
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
     );
   }
@@ -161,6 +168,16 @@
     return parameter;
   }
 
+  ParameterElement namedRequiredParameter({
+    @required String name,
+    @required DartType type,
+  }) {
+    var parameter = ParameterElementImpl(name, 0);
+    parameter.parameterKind = ParameterKind.NAMED_REQUIRED;
+    parameter.type = type;
+    return parameter;
+  }
+
   ParameterElement positionalParameter({String name, @required DartType type}) {
     var parameter = ParameterElementImpl(name ?? '', 0);
     parameter.parameterKind = ParameterKind.POSITIONAL;
@@ -175,9 +192,11 @@
     return parameter;
   }
 
-  TypeParameterElementImpl typeParameter(String name, {DartType bound}) {
+  TypeParameterElementImpl typeParameter(String name,
+      {DartType bound, Variance variance}) {
     var element = TypeParameterElementImpl.synthetic(name);
     element.bound = bound;
+    element.variance = variance;
     return element;
   }
 
@@ -190,4 +209,17 @@
       nullabilitySuffix: nullabilitySuffix,
     );
   }
+
+  TypeParameterTypeImpl typeParameterTypeNone(TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.none);
+  }
+
+  TypeParameterTypeImpl typeParameterTypeQuestion(
+      TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.question);
+  }
+
+  TypeParameterTypeImpl typeParameterTypeStar(TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
+  }
 }
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 761699e..695844b 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -4344,6 +4344,38 @@
         featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
   }
 
+  void test_class_enabled_multiple() {
+    var unit = parseCompilationUnit('class A<in T, inout U, out V, W> { }');
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+
+    expect(classDecl.typeParameters.typeParameters, hasLength(4));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+    expect(classDecl.typeParameters.typeParameters[1].name.name, 'U');
+    expect(classDecl.typeParameters.typeParameters[2].name.name, 'V');
+    expect(classDecl.typeParameters.typeParameters[3].name.name, 'W');
+
+    var typeParameterImplList = classDecl.typeParameters.typeParameters;
+    expect((typeParameterImplList[0] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[0] as TypeParameterImpl).varianceKeyword.lexeme,
+        "in");
+    expect((typeParameterImplList[1] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[1] as TypeParameterImpl).varianceKeyword.lexeme,
+        "inout");
+    expect((typeParameterImplList[2] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[2] as TypeParameterImpl).varianceKeyword.lexeme,
+        "out");
+    expect((typeParameterImplList[3] as TypeParameterImpl).varianceKeyword,
+        isNull);
+  }
+
   void test_class_disabled_single() {
     parseCompilationUnit('class A<out T> { }',
         errors: [
@@ -4371,6 +4403,11 @@
     expect(classDecl.name.name, 'A');
     expect(classDecl.typeParameters.typeParameters, hasLength(1));
     expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+
+    var typeParameterImpl =
+        classDecl.typeParameters.typeParameters[0] as TypeParameterImpl;
+    expect(typeParameterImpl.varianceKeyword, isNotNull);
+    expect(typeParameterImpl.varianceKeyword.lexeme, "in");
   }
 
   void test_function_disabled() {
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 73583f8..b2c9106 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -358,12 +358,10 @@
 
 /// Instances of the class [TestInstrumentor] implement an instrumentation
 /// service that can be used by tests.
-class TestInstrumentor extends InstrumentationService {
+class TestInstrumentor extends NoopInstrumentationService {
   /// All logged messages.
   List<String> log = [];
 
-  TestInstrumentor() : super(null);
-
   @override
   void logError(String message) {
     log.add("error: $message");
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index ff7a764..ee8f7eb 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -12,21 +12,21 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/token.dart' show KeywordToken;
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart'
     show NonExistingSource, UriKind;
 import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' show toUri;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'elements_types_mixin.dart';
 import 'test_analysis_context.dart';
 
 main() {
@@ -41,22 +41,14 @@
   });
 }
 
-abstract class AbstractTypeSystemTest {
+abstract class AbstractTypeSystemTest with ElementsTypesMixin {
   TypeProvider typeProvider;
   Dart2TypeSystem typeSystem;
 
-  DartType get bottomType => typeProvider.bottomType;
-
   InterfaceType get doubleType => typeProvider.doubleType;
 
-  DartType get dynamicType => typeProvider.dynamicType;
-
-  InterfaceType get functionType => typeProvider.functionType;
-
   InterfaceType get intType => typeProvider.intType;
 
-  DartType get neverType => typeProvider.neverType;
-
   DartType get nullType => typeProvider.nullType;
 
   InterfaceType get numType => typeProvider.numType;
@@ -73,22 +65,22 @@
 
   DartType futureOrType(DartType T) {
     var futureOrElement = typeProvider.futureOrElement;
-    return _interfaceType(futureOrElement, typeArguments: [T]);
+    return interfaceType(futureOrElement, typeArguments: [T]);
   }
 
   DartType futureType(DartType T) {
     var futureElement = typeProvider.futureElement;
-    return _interfaceType(futureElement, typeArguments: [T]);
+    return interfaceType(futureElement, typeArguments: [T]);
   }
 
   DartType iterableType(DartType T) {
     var iterableElement = typeProvider.iterableElement;
-    return _interfaceType(iterableElement, typeArguments: [T]);
+    return interfaceType(iterableElement, typeArguments: [T]);
   }
 
   DartType listType(DartType T) {
     var listElement = typeProvider.listElement;
-    return _interfaceType(listElement, typeArguments: [T]);
+    return interfaceType(listElement, typeArguments: [T]);
   }
 
   void setUp() {
@@ -97,140 +89,16 @@
     );
     typeProvider = analysisContext.typeProvider;
     typeSystem = analysisContext.typeSystem;
-  }
 
-  ClassElementImpl _class({
-    @required String name,
-    bool isAbstract = false,
-    InterfaceType superType,
-    List<TypeParameterElement> typeParameters = const [],
-    List<InterfaceType> interfaces = const [],
-    List<InterfaceType> mixins = const [],
-    List<MethodElement> methods = const [],
-  }) {
-    var element = ClassElementImpl(name, 0);
-    element.typeParameters = typeParameters;
-    element.supertype = superType ?? objectType;
-    element.interfaces = interfaces;
-    element.mixins = mixins;
-    element.methods = methods;
-    return element;
-  }
-
-  /**
-   * Creates a function type with the given parameter and return types.
-   *
-   * The return type defaults to `void` if omitted.
-   */
-  FunctionType _functionType({
-    List<TypeParameterElement> typeFormals,
-    List<DartType> required,
-    List<DartType> optional,
-    Map<String, DartType> named,
-    DartType returns,
-    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
-  }) {
-    if (optional != null && named != null) {
-      throw ArgumentError(
-        'Cannot have both optional positional and named parameters.',
-      );
-    }
-
-    var parameters = <ParameterElement>[];
-    if (required != null) {
-      for (var i = 0; i < required.length; ++i) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            'r$i',
-            required[i],
-            ParameterKind.REQUIRED,
-          ),
-        );
-      }
-    }
-    if (optional != null) {
-      for (var i = 0; i < optional.length; ++i) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            'p$i',
-            optional[i],
-            ParameterKind.POSITIONAL,
-          ),
-        );
-      }
-    }
-    if (named != null) {
-      for (var namedEntry in named.entries) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            namedEntry.key,
-            namedEntry.value,
-            ParameterKind.NAMED,
-          ),
-        );
-      }
-    }
-
-    return FunctionTypeImpl.synthetic(
-      returns ?? voidType,
-      typeFormals ?? const <TypeParameterElement>[],
-      parameters,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-
-  InterfaceType _interfaceType(
-    ClassElement element, {
-    List<DartType> typeArguments = const [],
-    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
-  }) {
-    return InterfaceTypeImpl.explicit(
-      element,
-      typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-
-  MethodElementImpl _method(
-    String name,
-    DartType returnType, {
-    List<TypeParameterElement> typeFormals = const [],
-    List<ParameterElement> parameters = const [],
-  }) {
-    return MethodElementImpl(name, 0)
-      ..parameters = parameters
-      ..returnType = returnType
-      ..typeParameters = typeFormals;
-  }
-
-  ParameterElement _requiredParameter(String name, DartType type) {
-    var parameter = ParameterElementImpl(name, 0);
-    parameter.parameterKind = ParameterKind.REQUIRED;
-    parameter.type = type;
-    return parameter;
-  }
-
-  TypeParameterElementImpl _typeParameter(String name, {DartType bound}) {
-    var element = TypeParameterElementImpl.synthetic(name);
-    element.bound = bound;
-    return element;
-  }
-
-  TypeParameterTypeImpl _typeParameterType(
-    TypeParameterElement element, {
-    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
-  }) {
-    return TypeParameterTypeImpl(
-      element,
-      nullabilitySuffix: nullabilitySuffix,
-    );
+    typeProvider = typeProvider;
+    typeSystem = typeSystem;
   }
 }
 
 @reflectiveTest
 class AssignabilityTest extends AbstractTypeSystemTest {
   void test_isAssignableTo_bottom_isBottom() {
-    var A = _class(name: 'A');
+    var A = class_(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
@@ -238,59 +106,64 @@
       doubleType,
       numType,
       stringType,
-      _interfaceType(A),
-      bottomType,
+      interfaceType(A),
+      neverStar,
     ];
 
-    _checkGroups(bottomType, interassignable: interassignable);
+    _checkGroups(neverStar, interassignable: interassignable);
   }
 
   void test_isAssignableTo_call_method() {
-    var B = _class(
+    var B = class_(
       name: 'B',
       methods: [
-        _method('call', objectType, parameters: [
-          _requiredParameter('_', intType),
+        method('call', objectType, parameters: [
+          requiredParameter(name: '_', type: intType),
         ]),
       ],
     );
 
     _checkIsStrictAssignableTo(
-      _interfaceType(B),
-      _functionType(required: [intType], returns: objectType),
+      interfaceType(B),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: objectType,
+      ),
     );
   }
 
   void test_isAssignableTo_classes() {
-    var classTop = _class(name: 'A');
-    var classLeft = _class(name: 'B', superType: _interfaceType(classTop));
-    var classRight = _class(name: 'C', superType: _interfaceType(classTop));
-    var classBottom = _class(
+    var classTop = class_(name: 'A');
+    var classLeft = class_(name: 'B', superType: interfaceType(classTop));
+    var classRight = class_(name: 'C', superType: interfaceType(classTop));
+    var classBottom = class_(
       name: 'D',
-      superType: _interfaceType(classLeft),
-      interfaces: [_interfaceType(classRight)],
+      superType: interfaceType(classLeft),
+      interfaces: [interfaceType(classRight)],
     );
-    var top = _interfaceType(classTop);
-    var left = _interfaceType(classLeft);
-    var right = _interfaceType(classRight);
-    var bottom = _interfaceType(classBottom);
+    var top = interfaceType(classTop);
+    var left = interfaceType(classLeft);
+    var right = interfaceType(classRight);
+    var bottom = interfaceType(classBottom);
 
     _checkLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_double() {
-    var A = _class(name: 'A');
+    var A = class_(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       doubleType,
       numType,
-      bottomType,
+      neverStar,
     ];
     List<DartType> unrelated = <DartType>[
       intType,
       stringType,
-      _interfaceType(A),
+      interfaceType(A),
     ];
 
     _checkGroups(doubleType,
@@ -298,7 +171,7 @@
   }
 
   void test_isAssignableTo_dynamic_isTop() {
-    var A = _class(name: 'A');
+    var A = class_(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
@@ -306,49 +179,51 @@
       doubleType,
       numType,
       stringType,
-      _interfaceType(A),
-      bottomType,
+      interfaceType(A),
+      neverStar,
     ];
     _checkGroups(dynamicType, interassignable: interassignable);
   }
 
   void test_isAssignableTo_generics() {
-    var LT = _typeParameter('T');
-    var L = _class(name: 'L', typeParameters: [LT]);
+    var LT = typeParameter('T');
+    var L = class_(name: 'L', typeParameters: [LT]);
 
-    var MT = _typeParameter('T');
-    var M = _class(
+    var MT = typeParameter('T');
+    var M = class_(
       name: 'M',
       typeParameters: [MT],
       interfaces: [
-        _interfaceType(
+        interfaceType(
           L,
-          typeArguments: [_typeParameterType(MT)],
+          typeArguments: [
+            typeParameterTypeStar(MT),
+          ],
         ),
       ],
     );
 
-    var top = _interfaceType(L, typeArguments: [dynamicType]);
-    var left = _interfaceType(M, typeArguments: [dynamicType]);
-    var right = _interfaceType(L, typeArguments: [intType]);
-    var bottom = _interfaceType(M, typeArguments: [intType]);
+    var top = interfaceType(L, typeArguments: [dynamicType]);
+    var left = interfaceType(M, typeArguments: [dynamicType]);
+    var right = interfaceType(L, typeArguments: [intType]);
+    var bottom = interfaceType(M, typeArguments: [intType]);
 
     _checkCrossLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_int() {
-    var A = _class(name: 'A');
+    var A = class_(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       intType,
       numType,
-      bottomType,
+      neverStar,
     ];
     List<DartType> unrelated = <DartType>[
       doubleType,
       stringType,
-      _interfaceType(A),
+      interfaceType(A),
     ];
 
     _checkGroups(intType,
@@ -356,35 +231,67 @@
   }
 
   void test_isAssignableTo_named_optional() {
-    var r = _functionType(required: [intType], returns: intType);
-    var o = _functionType(optional: [intType], returns: intType);
-    var n = _functionType(named: {'x': intType}, returns: intType);
+    var r = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: intType,
+    );
+    var o = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+      ],
+      returnType: intType,
+    );
+    var n = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'x', type: intType),
+      ],
+      returnType: intType,
+    );
 
-    var rr = _functionType(
-      required: [intType, intType],
-      returns: intType,
+    var rr = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: intType,
     );
-    var ro = _functionType(
-      required: [intType],
-      optional: [intType],
-      returns: intType,
+    var ro = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: intType,
     );
-    var rn = _functionType(
-      required: [intType],
-      named: {'x': intType},
-      returns: intType,
+    var rn = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        namedParameter(name: 'x', type: intType),
+      ],
+      returnType: intType,
     );
-    var oo = _functionType(
-      optional: [intType, intType],
-      returns: intType,
+    var oo = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: intType,
     );
-    var nn = _functionType(
-      named: {'x': intType, 'y': intType},
-      returns: intType,
+    var nn = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'x', type: intType),
+        namedParameter(name: 'y', type: intType),
+      ],
+      returnType: intType,
     );
-    var nnn = _functionType(
-      named: {'x': intType, 'y': intType, 'z': intType},
-      returns: intType,
+    var nnn = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'x', type: intType),
+        namedParameter(name: 'y', type: intType),
+        namedParameter(name: 'z', type: intType),
+      ],
+      returnType: intType,
     );
 
     _checkGroups(r,
@@ -406,18 +313,18 @@
   }
 
   void test_isAssignableTo_num() {
-    var A = _class(name: 'A');
+    var A = class_(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       numType,
       intType,
       doubleType,
-      bottomType,
+      neverStar,
     ];
     List<DartType> unrelated = <DartType>[
       stringType,
-      _interfaceType(A),
+      interfaceType(A),
     ];
 
     _checkGroups(numType,
@@ -425,17 +332,51 @@
   }
 
   void test_isAssignableTo_simple_function() {
-    var top = _functionType(required: [intType], returns: objectType);
-    var left = _functionType(required: [intType], returns: intType);
-    var right = _functionType(required: [objectType], returns: objectType);
-    var bottom = _functionType(required: [objectType], returns: intType);
+    var top = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: objectType,
+    );
+
+    var left = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: intType,
+    );
+
+    var right = functionTypeStar(
+      parameters: [
+        requiredParameter(type: objectType),
+      ],
+      returnType: objectType,
+    );
+
+    var bottom = functionTypeStar(
+      parameters: [
+        requiredParameter(type: objectType),
+      ],
+      returnType: intType,
+    );
 
     _checkCrossLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_void_functions() {
-    var top = _functionType(required: [intType], returns: voidType);
-    var bottom = _functionType(required: [objectType], returns: intType);
+    var top = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
+
+    var bottom = functionTypeStar(
+      parameters: [
+        requiredParameter(type: objectType),
+      ],
+      returnType: intType,
+    );
 
     _checkEquivalent(bottom, top);
   }
@@ -508,45 +449,28 @@
       DartType type1, DartType type2, DartType expectedResult) {
     var glb = typeSystem.getGreatestLowerBound(type1, type2);
     expect(glb, expectedResult);
+
     // Check that the result is a lower bound.
     expect(typeSystem.isSubtypeOf(glb, type1), true);
     expect(typeSystem.isSubtypeOf(glb, type2), true);
-    // Check for symmetry while we're at it.  Unfortunately,
-    // for function types, the current version of equality
-    // does not respect re-ordering of named parameters, so
-    // for function types we just check if they are mutual subtypes.
-    // https://github.com/dart-lang/sdk/issues/26126
-    // TODO(leafp): Fix this.
+
+    // Check for symmetry while we're at it.
     glb = typeSystem.getGreatestLowerBound(type2, type1);
-    if (glb is FunctionTypeImpl) {
-      expect(typeSystem.isSubtypeOf(glb, expectedResult), true);
-      expect(typeSystem.isSubtypeOf(expectedResult, glb), true);
-    } else {
-      expect(glb, expectedResult);
-    }
+    expect(glb, expectedResult);
   }
 
   void _checkLeastUpperBound(
       DartType type1, DartType type2, DartType expectedResult) {
     var lub = typeSystem.getLeastUpperBound(type1, type2);
     expect(lub, expectedResult);
+
     // Check that the result is an upper bound.
     expect(typeSystem.isSubtypeOf(type1, lub), true);
     expect(typeSystem.isSubtypeOf(type2, lub), true);
 
-    // Check for symmetry while we're at it.  Unfortunately,
-    // for function types, the current version of equality
-    // does not respect re-ordering of named parameters, so
-    // for function types we just check if they are mutual subtypes.
-    // https://github.com/dart-lang/sdk/issues/26126
-    // TODO(leafp): Fix this.
+    // Check for symmetry while we're at it.
     lub = typeSystem.getLeastUpperBound(type2, type1);
-    if (lub is FunctionTypeImpl) {
-      expect(typeSystem.isSubtypeOf(lub, expectedResult), true);
-      expect(typeSystem.isSubtypeOf(expectedResult, lub), true);
-    } else {
-      expect(lub, expectedResult);
-    }
+    expect(lub, expectedResult);
   }
 }
 
@@ -556,16 +480,20 @@
 
   void setUp() {
     super.setUp();
-    T = _typeParameterType(
-      _typeParameter('T'),
-      nullabilitySuffix: NullabilitySuffix.star,
+    T = typeParameterTypeStar(
+      typeParameter('T'),
     );
   }
 
   void test_function_coreFunction() {
     _checkOrdinarySubtypeMatch(
-      _functionType(required: [intType], returns: stringType),
-      functionType,
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
+      typeProvider.functionType,
       [T],
       covariant: true,
     );
@@ -573,8 +501,18 @@
 
   void test_function_parameter_types() {
     _checkIsSubtypeMatchOf(
-      _functionType(required: [T], returns: intType),
-      _functionType(required: [stringType], returns: intType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: T),
+        ],
+        returnType: intType,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: stringType),
+        ],
+        returnType: intType,
+      ),
       [T],
       ['String <: T'],
       covariant: true,
@@ -583,8 +521,18 @@
 
   void test_function_return_types() {
     _checkIsSubtypeMatchOf(
-      _functionType(required: [intType], returns: T),
-      _functionType(required: [intType], returns: stringType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: T,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
       [T],
       ['T <: String'],
       covariant: true,
@@ -635,7 +583,12 @@
     _checkOrdinarySubtypeMatch(nullType, nullType, [T], covariant: false);
     _checkOrdinarySubtypeMatch(
       nullType,
-      _functionType(required: [intType], returns: stringType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
       [T],
       covariant: false,
     );
@@ -651,9 +604,7 @@
     //
     // In other words, List<S> <: List<T> is satisfied provided that
     // S <: T.
-    var S = _typeParameterType(
-      _typeParameter('S'),
-    );
+    var S = typeParameterTypeStar(typeParameter('S'));
     _checkIsSubtypeMatchOf(listType(S), listType(T), [T], ['S <: T'],
         covariant: false);
   }
@@ -666,12 +617,10 @@
     //
     // In other words, S <: List<T> is satisfied provided that
     // bound(S) <: List<T>.
-    var S = _typeParameterType(
-      _typeParameter(
-        'S',
-        bound: listType(stringType),
-      ),
-    );
+    var S = typeParameterTypeStar(typeParameter(
+      'S',
+      bound: listType(stringType),
+    ));
     _checkIsSubtypeMatchOf(S, listType(T), [T], ['String <: T'],
         covariant: false);
   }
@@ -699,9 +648,7 @@
     //
     // In other words, T <: S can be satisfied trivially by the constraint
     // T <: S.
-    var S = _typeParameterType(
-      _typeParameter('S'),
-    );
+    var S = typeParameterTypeStar(typeParameter('S'));
     _checkIsSubtypeMatchOf(T, S, [T], ['T <: S'], covariant: true);
   }
 
@@ -715,9 +662,7 @@
     //
     // In other words, no match can be found for List<T> <: S because regardless
     // of T, we can't guarantee that List<T> <: S for all S.
-    var S = _typeParameterType(
-      _typeParameter('S'),
-    );
+    var S = typeParameterTypeStar(typeParameter('S'));
     _checkIsNotSubtypeMatchOf(listType(T), S, [T], covariant: true);
   }
 
@@ -745,7 +690,12 @@
     _checkOrdinarySubtypeMatch(objectType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(
-      _functionType(required: [intType], returns: stringType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
       dynamicType,
       [T],
       covariant: true,
@@ -765,7 +715,12 @@
     _checkOrdinarySubtypeMatch(objectType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(
-      _functionType(required: [intType], returns: stringType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
       objectType,
       [T],
       covariant: true,
@@ -784,7 +739,12 @@
     _checkOrdinarySubtypeMatch(objectType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(
-      _functionType(required: [intType], returns: stringType),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intType),
+        ],
+        returnType: stringType,
+      ),
       voidType,
       [T],
       covariant: true,
@@ -911,13 +871,17 @@
 class GenericFunctionInferenceTest extends AbstractTypeSystemTest {
   void test_boundedByAnotherTypeParameter() {
     // <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
-    var tFrom = _typeParameter('TFrom');
+    var tFrom = typeParameter('TFrom');
     var tTo =
-        _typeParameter('TTo', bound: iterableType(_typeParameterType(tFrom)));
-    var cast = _functionType(
+        typeParameter('TTo', bound: iterableType(typeParameterTypeStar(tFrom)));
+    var cast = functionTypeStar(
       typeFormals: [tFrom, tTo],
-      required: [_typeParameterType(tFrom)],
-      returns: _typeParameterType(tTo),
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeStar(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeStar(tTo),
     );
     expect(
         _inferCall(cast, [stringType]), [stringType, iterableType(stringType)]);
@@ -927,37 +891,42 @@
     // Regression test for https://github.com/dart-lang/sdk/issues/25740.
 
     // class A {}
-    var A = _class(name: 'A', superType: objectType);
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A', superType: objectType);
+    var typeA = interfaceType(A);
 
     // class B extends A {}
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
     // class C<T extends A> {
-    var CT = _typeParameter('T', bound: typeA);
-    var C = _class(
+    var CT = typeParameter('T', bound: typeA);
+    var C = class_(
       name: 'C',
       superType: objectType,
       typeParameters: [CT],
     );
     //   S m<S extends T>(S);
-    var S = _typeParameter('S', bound: _typeParameterType(CT));
-    var m = _method(
+    var S = typeParameter('S', bound: typeParameterTypeStar(CT));
+    var m = method(
       'm',
-      _typeParameterType(S),
+      typeParameterTypeStar(S),
       typeFormals: [S],
-      parameters: [_requiredParameter('_', _typeParameterType(S))],
+      parameters: [
+        requiredParameter(
+          name: '_',
+          type: typeParameterTypeStar(S),
+        ),
+      ],
     );
     C.methods = [m];
     // }
 
     // C<Object> cOfObject;
-    var cOfObject = _interfaceType(C, typeArguments: [objectType]);
+    var cOfObject = interfaceType(C, typeArguments: [objectType]);
     // C<A> cOfA;
-    var cOfA = _interfaceType(C, typeArguments: [typeA]);
+    var cOfA = interfaceType(C, typeArguments: [typeA]);
     // C<B> cOfB;
-    var cOfB = _interfaceType(C, typeArguments: [typeB]);
+    var cOfB = interfaceType(C, typeArguments: [typeB]);
     // B b;
     // cOfB.m(b); // infer <B>
     expect(_inferCall2(cOfB.getMethod('m').type, [typeB]).toString(),
@@ -974,38 +943,43 @@
     // Regression test for https://github.com/dart-lang/sdk/issues/25740.
 
     // class A {}
-    var A = _class(name: 'A', superType: objectType);
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A', superType: objectType);
+    var typeA = interfaceType(A);
 
     // class B extends A {}
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
     // class C<T extends A> {
-    var CT = _typeParameter('T', bound: typeA);
-    var C = _class(
+    var CT = typeParameter('T', bound: typeA);
+    var C = class_(
       name: 'C',
       superType: objectType,
       typeParameters: [CT],
     );
     //   S m<S extends Iterable<T>>(S);
-    var iterableOfT = iterableType(_typeParameterType(CT));
-    var S = _typeParameter('S', bound: iterableOfT);
-    var m = _method(
+    var iterableOfT = iterableType(typeParameterTypeStar(CT));
+    var S = typeParameter('S', bound: iterableOfT);
+    var m = method(
       'm',
-      _typeParameterType(S),
+      typeParameterTypeStar(S),
       typeFormals: [S],
-      parameters: [_requiredParameter('_', _typeParameterType(S))],
+      parameters: [
+        requiredParameter(
+          name: '_',
+          type: typeParameterTypeStar(S),
+        ),
+      ],
     );
     C.methods = [m];
     // }
 
     // C<Object> cOfObject;
-    var cOfObject = _interfaceType(C, typeArguments: [objectType]);
+    var cOfObject = interfaceType(C, typeArguments: [objectType]);
     // C<A> cOfA;
-    var cOfA = _interfaceType(C, typeArguments: [typeA]);
+    var cOfA = interfaceType(C, typeArguments: [typeA]);
     // C<B> cOfB;
-    var cOfB = _interfaceType(C, typeArguments: [typeB]);
+    var cOfB = interfaceType(C, typeArguments: [typeB]);
     // List<B> b;
     var listOfB = listType(typeB);
     // cOfB.m(b); // infer <B>
@@ -1021,32 +995,35 @@
 
   void test_boundedRecursively() {
     // class A<T extends A<T>>
-    var T = _typeParameter('T');
-    var A = _class(
+    var T = typeParameter('T');
+    var A = class_(
       name: 'Cloneable',
       superType: objectType,
       typeParameters: [T],
     );
-    T.bound = _interfaceType(
+    T.bound = interfaceType(
       A,
-      typeArguments: [_typeParameterType(T)],
+      typeArguments: [typeParameterTypeStar(T)],
     );
 
     // class B extends A<B> {}
-    var B = _class(name: 'B', superType: null);
-    B.supertype = _interfaceType(A, typeArguments: [_interfaceType(B)]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: null);
+    B.supertype = interfaceType(A, typeArguments: [interfaceType(B)]);
+    var typeB = interfaceType(B);
 
     // <S extends A<S>>
-    var S = _typeParameter('S');
-    var typeS = _typeParameterType(S);
-    S.bound = _interfaceType(A, typeArguments: [typeS]);
+    var S = typeParameter('S');
+    var typeS = typeParameterTypeStar(S);
+    S.bound = interfaceType(A, typeArguments: [typeS]);
 
     // (S, S) -> S
-    var clone = _functionType(
+    var clone = functionTypeStar(
       typeFormals: [S],
-      required: [typeS, typeS],
-      returns: typeS,
+      parameters: [
+        requiredParameter(type: typeS),
+        requiredParameter(type: typeS),
+      ],
+      returnType: typeS,
     );
     expect(_inferCall(clone, [typeB, typeB]), [typeB]);
 
@@ -1059,46 +1036,65 @@
 
   void test_genericCastFunction() {
     // <TFrom, TTo>(TFrom) -> TTo
-    var tFrom = _typeParameter('TFrom');
-    var tTo = _typeParameter('TTo');
-    var cast = _functionType(
+    var tFrom = typeParameter('TFrom');
+    var tTo = typeParameter('TTo');
+    var cast = functionTypeStar(
       typeFormals: [tFrom, tTo],
-      required: [_typeParameterType(tFrom)],
-      returns: _typeParameterType(tTo),
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeStar(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeStar(tTo),
     );
     expect(_inferCall(cast, [intType]), [intType, dynamicType]);
   }
 
   void test_genericCastFunctionWithUpperBound() {
     // <TFrom, TTo extends TFrom>(TFrom) -> TTo
-    var tFrom = _typeParameter('TFrom');
-    var tTo = _typeParameter('TTo', bound: _typeParameterType(tFrom));
-    var cast = _functionType(
+    var tFrom = typeParameter('TFrom');
+    var tTo = typeParameter(
+      'TTo',
+      bound: typeParameterTypeStar(tFrom),
+    );
+    var cast = functionTypeStar(
       typeFormals: [tFrom, tTo],
-      required: [_typeParameterType(tFrom)],
-      returns: _typeParameterType(tTo),
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeStar(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeStar(tTo),
     );
     expect(_inferCall(cast, [intType]), [intType, intType]);
   }
 
   void test_parametersToFunctionParam() {
     // <T>(f(T t)) -> T
-    var T = _typeParameter('T');
-    var cast = _functionType(
+    var T = typeParameter('T');
+    var cast = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [_typeParameterType(T)],
-          returns: dynamicType,
-        )
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeStar(T),
+              ),
+            ],
+            returnType: dynamicType,
+          ),
+        ),
       ],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(
       _inferCall(cast, [
-        _functionType(
-          required: [numType],
-          returns: dynamicType,
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: numType),
+          ],
+          returnType: dynamicType,
         )
       ]),
       [numType],
@@ -1107,54 +1103,61 @@
 
   void test_parametersUseLeastUpperBound() {
     // <T>(T x, T y) -> T
-    var T = _typeParameter('T');
-    var cast = _functionType(
+    var T = typeParameter('T');
+    var cast = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _typeParameterType(T),
-        _typeParameterType(T),
+      parameters: [
+        requiredParameter(type: typeParameterTypeStar(T)),
+        requiredParameter(type: typeParameterTypeStar(T)),
       ],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(cast, [intType, doubleType]), [numType]);
   }
 
   void test_parameterTypeUsesUpperBound() {
     // <T extends num>(T) -> dynamic
-    var T = _typeParameter('T', bound: numType);
-    var f = _functionType(
+    var T = typeParameter('T', bound: numType);
+    var f = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _typeParameterType(T),
+      parameters: [
+        requiredParameter(type: typeParameterTypeStar(T)),
       ],
-      returns: dynamicType,
+      returnType: dynamicType,
     );
     expect(_inferCall(f, [intType]), [intType]);
   }
 
   void test_returnFunctionWithGenericParameter() {
     // <T>(T -> T) -> (T -> void)
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [
-            _typeParameterType(T),
-          ],
-          returns: _typeParameterType(T),
-        )
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: typeParameterTypeStar(T)),
+            ],
+            returnType: typeParameterTypeStar(T),
+          ),
+        ),
       ],
-      returns: _functionType(
-        required: [
-          _typeParameterType(T),
+      returnType: functionTypeStar(
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(T)),
         ],
-        returns: voidType,
+        returnType: voidType,
       ),
     );
     expect(
       _inferCall(f, [
-        _functionType(required: [numType], returns: intType)
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: numType),
+          ],
+          returnType: intType,
+        ),
       ]),
       [intType],
     );
@@ -1162,31 +1165,35 @@
 
   void test_returnFunctionWithGenericParameterAndContext() {
     // <T>(T -> T) -> (T -> Null)
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [
-            _typeParameterType(T),
-          ],
-          returns: _typeParameterType(T),
-        )
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: typeParameterTypeStar(T)),
+            ],
+            returnType: typeParameterTypeStar(T),
+          ),
+        ),
       ],
-      returns: _functionType(
-        required: [
-          _typeParameterType(T),
+      returnType: functionTypeStar(
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(T)),
         ],
-        returns: nullType,
+        returnType: nullType,
       ),
     );
     expect(
       _inferCall(
         f,
         [],
-        returnType: _functionType(
-          required: [numType],
-          returns: intType,
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: numType),
+          ],
+          returnType: intType,
         ),
       ),
       [numType],
@@ -1195,29 +1202,33 @@
 
   void test_returnFunctionWithGenericParameterAndReturn() {
     // <T>(T -> T) -> (T -> T)
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [
-            _typeParameterType(T),
-          ],
-          returns: _typeParameterType(T),
-        )
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: typeParameterTypeStar(T)),
+            ],
+            returnType: typeParameterTypeStar(T),
+          ),
+        ),
       ],
-      returns: _functionType(
-        required: [
-          _typeParameterType(T),
+      returnType: functionTypeStar(
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(T)),
         ],
-        returns: _typeParameterType(T),
+        returnType: typeParameterTypeStar(T),
       ),
     );
     expect(
       _inferCall(f, [
-        _functionType(
-          required: [numType],
-          returns: intType,
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: numType),
+          ],
+          returnType: intType,
         )
       ]),
       [intType],
@@ -1226,26 +1237,30 @@
 
   void test_returnFunctionWithGenericReturn() {
     // <T>(T -> T) -> (() -> T)
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [
-            _typeParameterType(T),
-          ],
-          returns: _typeParameterType(T),
-        )
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: typeParameterTypeStar(T)),
+            ],
+            returnType: typeParameterTypeStar(T),
+          ),
+        ),
       ],
-      returns: _functionType(
-        returns: _typeParameterType(T),
+      returnType: functionTypeStar(
+        returnType: typeParameterTypeStar(T),
       ),
     );
     expect(
       _inferCall(f, [
-        _functionType(
-          required: [numType],
-          returns: intType,
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: numType),
+          ],
+          returnType: intType,
         )
       ]),
       [intType],
@@ -1254,55 +1269,77 @@
 
   void test_returnTypeFromContext() {
     // <T>() -> T
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(f, [], returnType: stringType), [stringType]);
   }
 
   void test_returnTypeWithBoundFromContext() {
     // <T extends num>() -> T
-    var T = _typeParameter('T', bound: numType);
-    var f = _functionType(
+    var T = typeParameter('T', bound: numType);
+    var f = functionTypeStar(
       typeFormals: [T],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(f, [], returnType: doubleType), [doubleType]);
   }
 
   void test_returnTypeWithBoundFromInvalidContext() {
     // <T extends num>() -> T
-    var T = _typeParameter('T', bound: numType);
-    var f = _functionType(
+    var T = typeParameter('T', bound: numType);
+    var f = functionTypeStar(
       typeFormals: [T],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(f, [], returnType: stringType), [nullType]);
   }
 
   void test_unifyParametersToFunctionParam() {
     // <T>(f(T t), g(T t)) -> T
-    var T = _typeParameter('T');
-    var cast = _functionType(
+    var T = typeParameter('T');
+    var cast = functionTypeStar(
       typeFormals: [T],
-      required: [
-        _functionType(
-          required: [_typeParameterType(T)],
-          returns: dynamicType,
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeStar(T),
+              ),
+            ],
+            returnType: dynamicType,
+          ),
         ),
-        _functionType(
-          required: [_typeParameterType(T)],
-          returns: dynamicType,
-        )
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeStar(T),
+              ),
+            ],
+            returnType: dynamicType,
+          ),
+        ),
       ],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(
       _inferCall(cast, [
-        _functionType(required: [intType], returns: dynamicType),
-        _functionType(required: [doubleType], returns: dynamicType)
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: intType),
+          ],
+          returnType: dynamicType,
+        ),
+        functionTypeStar(
+          parameters: [
+            requiredParameter(type: doubleType),
+          ],
+          returnType: dynamicType,
+        )
       ]),
       [nullType],
     );
@@ -1310,20 +1347,20 @@
 
   void test_unusedReturnTypeIsDynamic() {
     // <T>() -> T
-    var T = _typeParameter('T');
-    var f = _functionType(
+    var T = typeParameter('T');
+    var f = functionTypeStar(
       typeFormals: [T],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(f, []), [dynamicType]);
   }
 
   void test_unusedReturnTypeWithUpperBound() {
     // <T extends num>() -> T
-    var T = _typeParameter('T', bound: numType);
-    var f = _functionType(
+    var T = typeParameter('T', bound: numType);
+    var f = functionTypeStar(
       typeFormals: [T],
-      returns: _typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
     expect(_inferCall(f, []), [numType]);
   }
@@ -1372,17 +1409,18 @@
 @reflectiveTest
 class GreatestLowerBoundTest extends BoundTestBase {
   void test_bottom_function() {
-    _checkGreatestLowerBound(bottomType, _functionType(), bottomType);
+    _checkGreatestLowerBound(
+        neverStar, functionTypeStar(returnType: voidType), neverStar);
   }
 
   void test_bottom_interface() {
-    var A = _class(name: 'A');
-    _checkGreatestLowerBound(bottomType, _interfaceType(A), bottomType);
+    var A = class_(name: 'A');
+    _checkGreatestLowerBound(neverStar, interfaceType(A), neverStar);
   }
 
   void test_bottom_typeParam() {
-    var T = _typeParameter('T');
-    _checkGreatestLowerBound(bottomType, _typeParameterType(T), bottomType);
+    var T = typeParameter('T');
+    _checkGreatestLowerBound(neverStar, typeParameterTypeStar(T), neverStar);
   }
 
   void test_bounds_of_top_types_complete() {
@@ -1447,13 +1485,13 @@
     // class A
     // class B extends A
     // class C extends B
-    var A = _class(name: 'A');
-    var B = _class(name: 'B', superType: _interfaceType(A));
-    var C = _class(name: 'C', superType: _interfaceType(B));
+    var A = class_(name: 'A');
+    var B = class_(name: 'B', superType: interfaceType(A));
+    var C = class_(name: 'C', superType: interfaceType(B));
     _checkGreatestLowerBound(
-      _interfaceType(A),
-      _interfaceType(C),
-      _interfaceType(C),
+      interfaceType(A),
+      interfaceType(C),
+      interfaceType(C),
     );
   }
 
@@ -1461,33 +1499,36 @@
     // class A
     // class B implements A
     // class C implements B
-    var A = _class(name: 'A');
-    var B = _class(name: 'B', interfaces: [_interfaceType(A)]);
-    var C = _class(name: 'C', interfaces: [_interfaceType(B)]);
+    var A = class_(name: 'A');
+    var B = class_(name: 'B', interfaces: [interfaceType(A)]);
+    var C = class_(name: 'C', interfaces: [interfaceType(B)]);
     _checkGreatestLowerBound(
-      _interfaceType(A),
-      _interfaceType(C),
-      _interfaceType(C),
+      interfaceType(A),
+      interfaceType(C),
+      interfaceType(C),
     );
   }
 
   void test_dynamic_bottom() {
-    _checkGreatestLowerBound(dynamicType, bottomType, bottomType);
+    _checkGreatestLowerBound(dynamicType, neverStar, neverStar);
   }
 
   void test_dynamic_function() {
-    _checkGreatestLowerBound(dynamicType, _functionType(), _functionType());
+    _checkGreatestLowerBound(
+        dynamicType,
+        functionTypeStar(returnType: voidType),
+        functionTypeStar(returnType: voidType));
   }
 
   void test_dynamic_interface() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
     _checkGreatestLowerBound(dynamicType, typeA, typeA);
   }
 
   void test_dynamic_typeParam() {
-    var T = _typeParameter('T');
-    var typeT = _typeParameterType(T);
+    var T = typeParameter('T');
+    var typeT = typeParameterTypeStar(T);
     _checkGreatestLowerBound(dynamicType, typeT, typeT);
   }
 
@@ -1497,110 +1538,224 @@
   }
 
   void test_functionsDifferentNamedTakeUnion() {
-    var type1 = _functionType(
-      named: {'a': intType, 'b': intType},
+    var type1 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'b', type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      named: {'b': doubleType, 'c': stringType},
+    var type2 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'b', type: doubleType),
+        namedParameter(name: 'c', type: stringType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      named: {'a': intType, 'b': numType, 'c': stringType},
+    var expected = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'b', type: numType),
+        namedParameter(name: 'c', type: stringType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsDifferentOptionalArityTakeMax() {
-    var type1 = _functionType(
-      optional: [intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      optional: [doubleType, stringType, objectType],
+    var type2 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: doubleType),
+        positionalParameter(type: stringType),
+        positionalParameter(type: objectType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      optional: [numType, stringType, objectType],
+    var expected = functionTypeStar(
+      parameters: [
+        positionalParameter(type: numType),
+        positionalParameter(type: stringType),
+        positionalParameter(type: objectType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsDifferentRequiredArityBecomeOptional() {
-    var type1 = _functionType(
-      required: [intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      required: [intType, intType, intType],
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      required: [intType],
-      optional: [intType, intType],
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsFromDynamic() {
-    var type1 = _functionType(required: [dynamicType]);
-    var type2 = _functionType(required: [intType]);
-    var expected = _functionType(required: [dynamicType]);
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: dynamicType),
+      ],
+      returnType: voidType,
+    );
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: dynamicType),
+      ],
+      returnType: voidType,
+    );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsGlbReturnType() {
-    var type1 = _functionType(returns: intType);
-    var type2 = _functionType(returns: numType);
-    var expected = _functionType(returns: intType);
+    var type1 = functionTypeStar(
+      returnType: intType,
+    );
+    var type2 = functionTypeStar(
+      returnType: numType,
+    );
+    var expected = functionTypeStar(
+      returnType: intType,
+    );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsLubNamedParams() {
-    var type1 = _functionType(
-      named: {'a': stringType, 'b': intType},
+    var type1 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: stringType),
+        namedParameter(name: 'b', type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      named: {'a': intType, 'b': numType},
+    var type2 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'b', type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      named: {'a': objectType, 'b': numType},
+    var expected = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: objectType),
+        namedParameter(name: 'b', type: numType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsLubPositionalParams() {
-    var type1 = _functionType(
-      optional: [stringType, intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: stringType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      optional: [intType, numType],
+    var type2 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+        positionalParameter(type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      optional: [objectType, numType],
+    var expected = functionTypeStar(
+      parameters: [
+        positionalParameter(type: objectType),
+        positionalParameter(type: numType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsLubRequiredParams() {
-    var type1 = _functionType(
-      required: [stringType, intType, intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      required: [intType, doubleType, numType],
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: doubleType),
+        requiredParameter(type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      required: [objectType, numType, numType],
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: objectType),
+        requiredParameter(type: numType),
+        requiredParameter(type: numType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsMixedOptionalAndRequiredBecomeOptional() {
-    var type1 = _functionType(
-      required: [intType, intType],
-      optional: [intType, intType, intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      required: [intType],
-      optional: [intType, intType],
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      required: [intType],
-      optional: [intType, intType, intType, intType],
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
     _checkGreatestLowerBound(type1, type2, expected);
   }
@@ -1608,64 +1763,98 @@
   void test_functionsReturnBottomIfMixOptionalAndNamed() {
     // Dart doesn't allow a function to have both optional and named parameters,
     // so if we would have synthethized that, pick bottom instead.
-    var type1 = _functionType(
-      required: [intType],
-      named: {'a': intType},
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        namedParameter(name: 'a', type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      named: {'a': intType},
+    var type2 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+      ],
+      returnType: voidType,
     );
-    _checkGreatestLowerBound(type1, type2, bottomType);
+    _checkGreatestLowerBound(type1, type2, neverStar);
   }
 
   void test_functionsSameType_withNamed() {
-    var type1 = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
-    var type2 = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
-    var expected = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_functionsSameType_withOptional() {
-    var type1 = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
-    var type2 = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
-    var expected = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
     _checkGreatestLowerBound(type1, type2, expected);
   }
 
   void test_interface_function() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
-    _checkGreatestLowerBound(typeA, _functionType(), bottomType);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
+    _checkGreatestLowerBound(
+      typeA,
+      functionTypeStar(returnType: voidType),
+      neverStar,
+    );
   }
 
   void test_mixin() {
@@ -1673,21 +1862,21 @@
     // class B
     // class C
     // class D extends A with B, C
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B');
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B');
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C');
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C');
+    var typeC = interfaceType(C);
 
-    var D = _class(
+    var D = class_(
       name: 'D',
-      superType: _interfaceType(A),
+      superType: interfaceType(A),
       mixins: [typeB, typeC],
     );
-    var typeD = _interfaceType(D);
+    var typeD = interfaceType(D);
 
     _checkGreatestLowerBound(typeA, typeD, typeD);
     _checkGreatestLowerBound(typeB, typeD, typeD);
@@ -1695,16 +1884,16 @@
   }
 
   void test_self() {
-    var T = _typeParameter('T');
-    var A = _class(name: 'A');
+    var T = typeParameter('T');
+    var A = class_(name: 'A');
 
     List<DartType> types = [
       dynamicType,
       voidType,
-      bottomType,
-      _typeParameterType(T),
-      _interfaceType(A),
-      _functionType(),
+      neverStar,
+      typeParameterTypeStar(T),
+      interfaceType(A),
+      functionTypeStar(returnType: voidType),
     ];
 
     for (DartType type in types) {
@@ -1713,36 +1902,36 @@
   }
 
   void test_typeParam_function_noBound() {
-    var T = _typeParameter('T');
+    var T = typeParameter('T');
     _checkGreatestLowerBound(
-      _typeParameterType(T),
-      _functionType(),
-      bottomType,
+      typeParameterTypeStar(T),
+      functionTypeStar(returnType: voidType),
+      neverStar,
     );
   }
 
   void test_typeParam_interface_bounded() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeB);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeB);
+    var typeC = interfaceType(C);
 
-    var T = _typeParameter('T', bound: typeB);
-    _checkGreatestLowerBound(_typeParameterType(T), typeC, bottomType);
+    var T = typeParameter('T', bound: typeB);
+    _checkGreatestLowerBound(typeParameterTypeStar(T), typeC, neverStar);
   }
 
   void test_typeParam_interface_noBound() {
     // GLB(T, A) = ⊥
-    var T = _typeParameter('T');
-    var A = _class(name: 'A');
+    var T = typeParameter('T');
+    var A = class_(name: 'A');
     _checkGreatestLowerBound(
-      _typeParameterType(T),
-      _interfaceType(A),
-      bottomType,
+      typeParameterTypeStar(T),
+      interfaceType(A),
+      neverStar,
     );
   }
 
@@ -1751,7 +1940,7 @@
     var listOfIntType = listType(intType);
     var listOfDoubleType = listType(doubleType);
     // TODO(rnystrom): Can we do something better here?
-    _checkGreatestLowerBound(listOfIntType, listOfDoubleType, bottomType);
+    _checkGreatestLowerBound(listOfIntType, listOfDoubleType, neverStar);
   }
 
   void test_typeParameters_same() {
@@ -1760,29 +1949,160 @@
     _checkGreatestLowerBound(listOfIntType, listOfIntType, listOfIntType);
   }
 
+  void test_typeParameters_covariant_same() {
+    // class A<out T>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+
+    _checkLeastUpperBound(aNum, aNum, aNum);
+  }
+
+  void test_typeParameters_covariant_different() {
+    // class A<out T>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    // A<int>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+    var aInt = interfaceType(A, typeArguments: [intType]);
+
+    _checkLeastUpperBound(aInt, aNum, aNum);
+  }
+
+  void test_typeParameters_contravariant_same() {
+    // class A<in T>
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+
+    _checkLeastUpperBound(aNum, aNum, aNum);
+  }
+
+  void test_typeParameters_contravariant_different() {
+    // class A<in T>
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    // A<int>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+    var aInt = interfaceType(A, typeArguments: [intType]);
+
+    _checkLeastUpperBound(aInt, aNum, aInt);
+  }
+
+  void test_typeParameters_invariant_same() {
+    // class A<inout T>
+    var T = typeParameter('T', variance: Variance.invariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+
+    _checkLeastUpperBound(aNum, aNum, aNum);
+  }
+
+  void test_typeParameters_invariant_object() {
+    // class A<inout T>
+    var T = typeParameter('T', variance: Variance.invariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    // A<num>
+    // A<int>
+    var aNum = interfaceType(A, typeArguments: [numType]);
+    var aInt = interfaceType(A, typeArguments: [intType]);
+
+    _checkLeastUpperBound(aNum, aInt, objectType);
+  }
+
+  void test_typeParameters_multi_basic() {
+    // class Multi<out T, inout U, in V>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var U = typeParameter('T', variance: Variance.invariant);
+    var V = typeParameter('T', variance: Variance.contravariant);
+    var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+    // Multi<num, num, num>
+    // Multi<int, num, int>
+    var multiNumNumNum =
+        interfaceType(Multi, typeArguments: [numType, numType, numType]);
+    var multiIntNumInt =
+        interfaceType(Multi, typeArguments: [intType, numType, intType]);
+
+    // We expect Multi<num, num, int>
+    var multiNumNumInt =
+        interfaceType(Multi, typeArguments: [numType, numType, intType]);
+
+    _checkLeastUpperBound(multiNumNumNum, multiIntNumInt, multiNumNumInt);
+  }
+
+  void test_typeParameters_multi_objectInterface() {
+    // class Multi<out T, inout U, in V>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var U = typeParameter('T', variance: Variance.invariant);
+    var V = typeParameter('T', variance: Variance.contravariant);
+    var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+    // Multi<num, String, num>
+    // Multi<int, num, int>
+    var multiNumStringNum =
+        interfaceType(Multi, typeArguments: [numType, stringType, numType]);
+    var multiIntNumInt =
+        interfaceType(Multi, typeArguments: [intType, numType, intType]);
+
+    _checkLeastUpperBound(multiNumStringNum, multiIntNumInt, objectType);
+  }
+
+  void test_typeParameters_multi_objectType() {
+    // class Multi<out T, inout U, in V>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var U = typeParameter('T', variance: Variance.invariant);
+    var V = typeParameter('T', variance: Variance.contravariant);
+    var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+    // Multi<String, num, num>
+    // Multi<int, num, int>
+    var multiStringNumNum =
+        interfaceType(Multi, typeArguments: [stringType, numType, numType]);
+    var multiIntNumInt =
+        interfaceType(Multi, typeArguments: [intType, numType, intType]);
+
+    // We expect Multi<Object, num, int>
+    var multiObjectNumInt =
+        interfaceType(Multi, typeArguments: [objectType, numType, intType]);
+
+    _checkLeastUpperBound(multiStringNumNum, multiIntNumInt, multiObjectNumInt);
+  }
+
   void test_unrelatedClasses() {
     // class A
     // class B
     // class C
-    var A = _class(name: 'A');
-    var B = _class(name: 'B');
-    _checkGreatestLowerBound(_interfaceType(A), _interfaceType(B), bottomType);
+    var A = class_(name: 'A');
+    var B = class_(name: 'B');
+    _checkGreatestLowerBound(interfaceType(A), interfaceType(B), neverStar);
   }
 
   void test_void() {
-    var A = _class(name: 'A');
-    var T = _typeParameter('T');
+    var A = class_(name: 'A');
+    var T = typeParameter('T');
     List<DartType> types = [
-      bottomType,
-      _functionType(),
-      _interfaceType(A),
-      _typeParameterType(T),
+      neverStar,
+      functionTypeStar(returnType: voidType),
+      interfaceType(A),
+      typeParameterTypeStar(T),
     ];
     for (DartType type in types) {
       _checkGreatestLowerBound(
-        _functionType(returns: voidType),
-        _functionType(returns: type),
-        _functionType(returns: type),
+        functionTypeStar(returnType: voidType),
+        functionTypeStar(returnType: type),
+        functionTypeStar(returnType: type),
       );
     }
   }
@@ -1791,179 +2111,292 @@
 @reflectiveTest
 class LeastUpperBoundFunctionsTest extends BoundTestBase {
   void test_differentRequiredArity() {
-    var type1 = _functionType(required: [intType, intType]);
-    var type2 = _functionType(required: [intType, intType, intType]);
-    _checkLeastUpperBound(type1, type2, functionType);
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
+    _checkLeastUpperBound(type1, type2, typeProvider.functionType);
   }
 
   void test_fuzzyArrows() {
-    var type1 = _functionType(required: [dynamicType]);
-    var type2 = _functionType(required: [intType]);
-    var expected = _functionType(required: [intType]);
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: dynamicType),
+      ],
+      returnType: voidType,
+    );
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
+    );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_glbNamedParams() {
-    var type1 = _functionType(
-      named: {'a': stringType, 'b': intType},
+    var type1 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: stringType),
+        namedParameter(name: 'b', type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      named: {'a': intType, 'b': numType},
+    var type2 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'b', type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      named: {'a': bottomType, 'b': intType},
+    var expected = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: neverStar),
+        namedParameter(name: 'b', type: intType),
+      ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_glbPositionalParams() {
-    var type1 = _functionType(
-      optional: [stringType, intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: stringType),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      optional: [intType, numType],
+    var type2 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+        positionalParameter(type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      optional: [bottomType, intType],
+    var expected = functionTypeStar(
+      parameters: [
+        positionalParameter(type: neverStar),
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_glbRequiredParams() {
-    var type1 = _functionType(
-      required: [stringType, intType, intType],
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      required: [intType, doubleType, numType],
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+        requiredParameter(type: doubleType),
+        requiredParameter(type: numType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      required: [bottomType, bottomType, intType],
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: neverStar),
+        requiredParameter(type: neverStar),
+        requiredParameter(type: intType),
+      ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_ignoreExtraNamedParams() {
-    var type1 = _functionType(
-      named: {'a': intType, 'b': intType},
+    var type1 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'b', type: intType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      named: {'a': intType, 'c': intType},
+    var type2 = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+        namedParameter(name: 'c', type: intType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      named: {'a': intType},
+    var expected = functionTypeStar(
+      parameters: [
+        namedParameter(name: 'a', type: intType),
+      ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_ignoreExtraPositionalParams() {
-    var type1 = _functionType(
-      optional: [intType, intType, stringType],
+    var type1 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+        positionalParameter(type: intType),
+        positionalParameter(type: stringType),
+      ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      optional: [intType],
+    var type2 = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      optional: [intType],
+    var expected = functionTypeStar(
+      parameters: [
+        positionalParameter(type: intType),
+      ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_lubReturnType() {
-    var type1 = _functionType(returns: intType);
-    var type2 = _functionType(returns: doubleType);
-    var expected = _functionType(returns: numType);
+    var type1 = functionTypeStar(returnType: intType);
+    var type2 = functionTypeStar(returnType: doubleType);
+    var expected = functionTypeStar(returnType: numType);
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_sameType_withNamed() {
-    var type1 = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
-    var type2 = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
-    var expected = _functionType(
-      required: [stringType, intType, numType],
-      named: {'n': numType},
-      returns: intType,
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        namedParameter(name: 'n', type: numType),
+      ],
+      returnType: intType,
     );
 
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_sameType_withOptional() {
-    var type1 = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
-    var type2 = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
-    var expected = _functionType(
-      required: [stringType, intType, numType],
-      optional: [doubleType],
-      returns: intType,
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(type: stringType),
+        requiredParameter(type: intType),
+        requiredParameter(type: numType),
+        positionalParameter(type: doubleType),
+      ],
+      returnType: intType,
     );
 
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_typeFormals_differentBounds() {
-    var T1 = _typeParameter('T1', bound: intType);
-    var type1 = _functionType(
+    var T1 = typeParameter('T1', bound: intType);
+    var type1 = functionTypeStar(
       typeFormals: [T1],
-      returns: _typeParameterType(T1),
+      returnType: typeParameterTypeStar(T1),
     );
 
-    var T2 = _typeParameter('T2', bound: doubleType);
-    var type2 = _functionType(
+    var T2 = typeParameter('T2', bound: doubleType);
+    var type2 = functionTypeStar(
       typeFormals: [T2],
-      returns: _typeParameterType(T2),
+      returnType: typeParameterTypeStar(T2),
     );
 
-    _checkLeastUpperBound(type1, type2, functionType);
+    _checkLeastUpperBound(type1, type2, typeProvider.functionType);
   }
 
   void test_typeFormals_differentNumber() {
-    var T1 = _typeParameter('T1', bound: numType);
-    var type1 = _functionType(
+    var T1 = typeParameter('T1', bound: numType);
+    var type1 = functionTypeStar(
       typeFormals: [T1],
-      returns: _typeParameterType(T1),
+      returnType: typeParameterTypeStar(T1),
     );
 
-    var type2 = _functionType(returns: intType);
+    var type2 = functionTypeStar(returnType: intType);
 
-    _checkLeastUpperBound(type1, type2, functionType);
+    _checkLeastUpperBound(type1, type2, typeProvider.functionType);
   }
 
   void test_typeFormals_sameBounds() {
-    var T1 = _typeParameter('T1', bound: numType);
-    var type1 = _functionType(
+    var T1 = typeParameter('T1', bound: numType);
+    var type1 = functionTypeStar(
       typeFormals: [T1],
-      returns: _typeParameterType(T1),
+      returnType: typeParameterTypeStar(T1),
     );
 
-    var T2 = _typeParameter('T2', bound: numType);
-    var type2 = _functionType(
+    var T2 = typeParameter('T2', bound: numType);
+    var type2 = functionTypeStar(
       typeFormals: [T2],
-      returns: _typeParameterType(T2),
+      returnType: typeParameterTypeStar(T2),
     );
 
-    var TE = _typeParameter('T', bound: numType);
-    var expected = _functionType(
+    var TE = typeParameter('T', bound: numType);
+    var expected = functionTypeStar(
       typeFormals: [TE],
-      returns: _typeParameterType(TE),
+      returnType: typeParameterTypeStar(TE),
     );
 
     _checkLeastUpperBound(type1, type2, expected);
@@ -1973,19 +2406,20 @@
 @reflectiveTest
 class LeastUpperBoundTest extends BoundTestBase {
   void test_bottom_function() {
-    _checkLeastUpperBound(bottomType, _functionType(), _functionType());
+    _checkLeastUpperBound(neverStar, functionTypeStar(returnType: voidType),
+        functionTypeStar(returnType: voidType));
   }
 
   void test_bottom_interface() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
-    _checkLeastUpperBound(bottomType, typeA, typeA);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
+    _checkLeastUpperBound(neverStar, typeA, typeA);
   }
 
   void test_bottom_typeParam() {
-    var T = _typeParameter('T');
-    var typeT = _typeParameterType(T);
-    _checkLeastUpperBound(bottomType, typeT, typeT);
+    var T = typeParameter('T');
+    var typeT = typeParameterTypeStar(T);
+    _checkLeastUpperBound(neverStar, typeT, typeT);
   }
 
   void test_directInterfaceCase() {
@@ -1993,14 +2427,14 @@
     // class B implements A
     // class C implements B
 
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', interfaces: [typeA]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', interfaces: [typeA]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', interfaces: [typeB]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', interfaces: [typeB]);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeB);
   }
@@ -2010,45 +2444,45 @@
     // class B extends A
     // class C extends B
 
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeB);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeB);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeB);
   }
 
   void test_directSuperclass_nullability() {
-    var aElement = _class(name: 'A');
-    var aQuestion = _interfaceType(
+    var aElement = class_(name: 'A');
+    var aQuestion = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.question,
     );
-    var aStar = _interfaceType(
+    var aStar = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.star,
     );
-    var aNone = _interfaceType(
+    var aNone = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.none,
     );
 
-    var bElementStar = _class(name: 'B', superType: aStar);
-    var bElementNone = _class(name: 'B', superType: aNone);
+    var bElementStar = class_(name: 'B', superType: aStar);
+    var bElementNone = class_(name: 'B', superType: aNone);
 
     InterfaceTypeImpl _bTypeStarElement(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         bElementStar,
         nullabilitySuffix: nullability,
       );
     }
 
     InterfaceTypeImpl _bTypeNoneElement(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         bElementNone,
         nullabilitySuffix: nullability,
       );
@@ -2093,21 +2527,22 @@
   }
 
   void test_dynamic_bottom() {
-    _checkLeastUpperBound(dynamicType, bottomType, dynamicType);
+    _checkLeastUpperBound(dynamicType, neverStar, dynamicType);
   }
 
   void test_dynamic_function() {
-    _checkLeastUpperBound(dynamicType, _functionType(), dynamicType);
+    _checkLeastUpperBound(
+        dynamicType, functionTypeStar(returnType: voidType), dynamicType);
   }
 
   void test_dynamic_interface() {
-    var A = _class(name: 'A');
-    _checkLeastUpperBound(dynamicType, _interfaceType(A), dynamicType);
+    var A = class_(name: 'A');
+    _checkLeastUpperBound(dynamicType, interfaceType(A), dynamicType);
   }
 
   void test_dynamic_typeParam() {
-    var T = _typeParameter('T');
-    _checkLeastUpperBound(dynamicType, _typeParameterType(T), dynamicType);
+    var T = typeParameter('T');
+    _checkLeastUpperBound(dynamicType, typeParameterTypeStar(T), dynamicType);
   }
 
   void test_dynamic_void() {
@@ -2116,22 +2551,23 @@
   }
 
   void test_interface_function() {
-    var A = _class(name: 'A');
-    _checkLeastUpperBound(_interfaceType(A), _functionType(), objectType);
+    var A = class_(name: 'A');
+    _checkLeastUpperBound(
+        interfaceType(A), functionTypeStar(returnType: voidType), objectType);
   }
 
   void test_interface_sameElement_nullability() {
-    var aElement = _class(name: 'A');
+    var aElement = class_(name: 'A');
 
-    var aQuestion = _interfaceType(
+    var aQuestion = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.question,
     );
-    var aStar = _interfaceType(
+    var aStar = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.star,
     );
-    var aNone = _interfaceType(
+    var aNone = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.none,
     );
@@ -2155,10 +2591,10 @@
   }
 
   void test_mixinAndClass_constraintAndInterface() {
-    var classA = _class(name: 'A');
+    var classA = class_(name: 'A');
     var instA = InstantiatedClass(classA, []);
 
-    var classB = _class(
+    var classB = class_(
       name: 'B',
       interfaces: [instA.withNullabilitySuffixNone],
     );
@@ -2169,11 +2605,11 @@
     );
 
     _checkLeastUpperBound(
-      _interfaceType(
+      interfaceType(
         classB,
         nullabilitySuffix: NullabilitySuffix.star,
       ),
-      _interfaceType(
+      interfaceType(
         mixinM,
         nullabilitySuffix: NullabilitySuffix.star,
       ),
@@ -2182,21 +2618,21 @@
   }
 
   void test_mixinAndClass_object() {
-    var classA = _class(name: 'A');
+    var classA = class_(name: 'A');
     var mixinM = ElementFactory.mixinElement(name: 'M');
 
     _checkLeastUpperBound(
-      _interfaceType(classA),
-      _interfaceType(mixinM),
+      interfaceType(classA),
+      interfaceType(mixinM),
       objectType,
     );
   }
 
   void test_mixinAndClass_sharedInterface() {
-    var classA = _class(name: 'A');
+    var classA = class_(name: 'A');
     var instA = InstantiatedClass(classA, []);
 
-    var classB = _class(
+    var classB = class_(
       name: 'B',
       interfaces: [instA.withNullabilitySuffixNone],
     );
@@ -2207,11 +2643,11 @@
     );
 
     _checkLeastUpperBound(
-      _interfaceType(
+      interfaceType(
         classB,
         nullabilitySuffix: NullabilitySuffix.star,
       ),
-      _interfaceType(
+      interfaceType(
         mixinM,
         nullabilitySuffix: NullabilitySuffix.star,
       ),
@@ -2225,73 +2661,168 @@
     // class C extends A
     // class D extends B with M, N, O, P
 
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeA);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeA);
+    var typeC = interfaceType(C);
 
-    var D = _class(
+    var D = class_(
       name: 'D',
       superType: typeB,
       mixins: [
-        _interfaceType(_class(name: 'M')),
-        _interfaceType(_class(name: 'N')),
-        _interfaceType(_class(name: 'O')),
-        _interfaceType(_class(name: 'P')),
+        interfaceType(class_(name: 'M')),
+        interfaceType(class_(name: 'N')),
+        interfaceType(class_(name: 'O')),
+        interfaceType(class_(name: 'P')),
       ],
     );
-    var typeD = _interfaceType(D);
+    var typeD = interfaceType(D);
 
     _checkLeastUpperBound(typeD, typeC, typeA);
   }
 
   void test_nestedFunctionsLubInnerParamTypes() {
-    var type1 = _functionType(
-      required: [
-        _functionType(required: [stringType, intType, intType])
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: stringType),
+              requiredParameter(type: intType),
+              requiredParameter(type: intType),
+            ],
+            returnType: voidType,
+          ),
+        ),
       ],
+      returnType: voidType,
     );
-    var type2 = _functionType(
-      required: [
-        _functionType(required: [intType, doubleType, numType])
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: intType),
+              requiredParameter(type: doubleType),
+              requiredParameter(type: numType),
+            ],
+            returnType: voidType,
+          ),
+        ),
       ],
+      returnType: voidType,
     );
-    var expected = _functionType(
-      required: [
-        _functionType(required: [objectType, numType, numType])
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: objectType),
+              requiredParameter(type: numType),
+              requiredParameter(type: numType),
+            ],
+            returnType: voidType,
+          ),
+        ),
       ],
+      returnType: voidType,
     );
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_nestedNestedFunctionsGlbInnermostParamTypes() {
-    var type1 = _functionType(required: [
-      _functionType(required: [
-        _functionType(required: [stringType, intType, intType])
-      ])
-    ]);
-    var type2 = _functionType(required: [
-      _functionType(required: [
-        _functionType(required: [intType, doubleType, numType])
-      ])
-    ]);
-    var expected = _functionType(required: [
-      _functionType(required: [
-        _functionType(required: [bottomType, bottomType, intType])
-      ])
-    ]);
+    var type1 = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: functionTypeStar(
+                  parameters: [
+                    requiredParameter(type: stringType),
+                    requiredParameter(type: intType),
+                    requiredParameter(type: intType)
+                  ],
+                  returnType: voidType,
+                ),
+              ),
+            ],
+            returnType: voidType,
+          ),
+        ),
+      ],
+      returnType: voidType,
+    );
+    expect(
+      type1.toString(withNullability: true),
+      'void Function(void Function(void Function(String*, int*, int*)*)*)*',
+    );
+
+    var type2 = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: functionTypeStar(
+                  parameters: [
+                    requiredParameter(type: intType),
+                    requiredParameter(type: doubleType),
+                    requiredParameter(type: numType)
+                  ],
+                  returnType: voidType,
+                ),
+              ),
+            ],
+            returnType: voidType,
+          ),
+        ),
+      ],
+      returnType: voidType,
+    );
+    expect(
+      type2.toString(withNullability: true),
+      'void Function(void Function(void Function(int*, double*, num*)*)*)*',
+    );
+    var expected = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(
+                type: functionTypeStar(
+                  parameters: [
+                    requiredParameter(type: neverStar),
+                    requiredParameter(type: neverStar),
+                    requiredParameter(type: intType)
+                  ],
+                  returnType: voidType,
+                ),
+              ),
+            ],
+            returnType: voidType,
+          ),
+        ),
+      ],
+      returnType: voidType,
+    );
+    expect(
+      expected.toString(withNullability: true),
+      'void Function(void Function(void Function(Never*, Never*, int*)*)*)*',
+    );
+
     _checkLeastUpperBound(type1, type2, expected);
   }
 
   void test_object() {
-    var A = _class(name: 'A');
-    var B = _class(name: 'B');
-    var typeA = _interfaceType(A);
-    var typeB = _interfaceType(B);
+    var A = class_(name: 'A');
+    var B = class_(name: 'B');
+    var typeA = interfaceType(A);
+    var typeB = interfaceType(B);
     var typeObject = typeA.element.supertype;
     // assert that object does not have a super type
     expect(typeObject.element.supertype, isNull);
@@ -2302,16 +2833,16 @@
   }
 
   void test_self() {
-    var T = _typeParameter('T');
-    var A = _class(name: 'A');
+    var T = typeParameter('T');
+    var A = class_(name: 'A');
 
     List<DartType> types = [
       dynamicType,
       voidType,
-      bottomType,
-      _typeParameterType(T),
-      _interfaceType(A),
-      _functionType()
+      neverStar,
+      typeParameterTypeStar(T),
+      interfaceType(A),
+      functionTypeStar(returnType: voidType)
     ];
 
     for (DartType type in types) {
@@ -2320,48 +2851,48 @@
   }
 
   void test_sharedSuperclass1() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeA);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeA);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperclass1_nullability() {
-    var aElement = _class(name: 'A');
-    var aQuestion = _interfaceType(
+    var aElement = class_(name: 'A');
+    var aQuestion = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.question,
     );
-    var aStar = _interfaceType(
+    var aStar = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.star,
     );
-    var aNone = _interfaceType(
+    var aNone = interfaceType(
       aElement,
       nullabilitySuffix: NullabilitySuffix.none,
     );
 
-    var bElementNone = _class(name: 'B', superType: aNone);
-    var bElementStar = _class(name: 'B', superType: aStar);
+    var bElementNone = class_(name: 'B', superType: aNone);
+    var bElementStar = class_(name: 'B', superType: aStar);
 
-    var cElementNone = _class(name: 'C', superType: aNone);
-    var cElementStar = _class(name: 'C', superType: aStar);
+    var cElementNone = class_(name: 'C', superType: aNone);
+    var cElementStar = class_(name: 'C', superType: aStar);
 
     InterfaceTypeImpl bTypeElementNone(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         bElementNone,
         nullabilitySuffix: nullability,
       );
     }
 
     InterfaceTypeImpl bTypeElementStar(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         bElementStar,
         nullabilitySuffix: nullability,
       );
@@ -2376,14 +2907,14 @@
     var bStarNone = bTypeElementStar(NullabilitySuffix.none);
 
     InterfaceTypeImpl cTypeElementNone(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         cElementNone,
         nullabilitySuffix: nullability,
       );
     }
 
     InterfaceTypeImpl cTypeElementStar(NullabilitySuffix nullability) {
-      return _interfaceType(
+      return interfaceType(
         cElementStar,
         nullabilitySuffix: nullability,
       );
@@ -2446,116 +2977,116 @@
   }
 
   void test_sharedSuperclass2() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeA);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeA);
+    var typeC = interfaceType(C);
 
-    var D = _class(name: 'D', superType: typeC);
-    var typeD = _interfaceType(D);
+    var D = class_(name: 'D', superType: typeC);
+    var typeD = interfaceType(D);
 
     _checkLeastUpperBound(typeB, typeD, typeA);
   }
 
   void test_sharedSuperclass3() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeB);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeB);
+    var typeC = interfaceType(C);
 
-    var D = _class(name: 'D', superType: typeB);
-    var typeD = _interfaceType(D);
+    var D = class_(name: 'D', superType: typeB);
+    var typeD = interfaceType(D);
 
     _checkLeastUpperBound(typeC, typeD, typeB);
   }
 
   void test_sharedSuperclass4() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var A2 = _class(name: 'A2');
-    var typeA2 = _interfaceType(A2);
+    var A2 = class_(name: 'A2');
+    var typeA2 = interfaceType(A2);
 
-    var A3 = _class(name: 'A3');
-    var typeA3 = _interfaceType(A3);
+    var A3 = class_(name: 'A3');
+    var typeA3 = interfaceType(A3);
 
-    var B = _class(name: 'B', superType: typeA, interfaces: [typeA2]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA, interfaces: [typeA2]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeA, interfaces: [typeA3]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeA, interfaces: [typeA3]);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperinterface1() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', interfaces: [typeA]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', interfaces: [typeA]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', interfaces: [typeA]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', interfaces: [typeA]);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperinterface2() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', interfaces: [typeA]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', interfaces: [typeA]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', interfaces: [typeA]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', interfaces: [typeA]);
+    var typeC = interfaceType(C);
 
-    var D = _class(name: 'D', interfaces: [typeC]);
-    var typeD = _interfaceType(D);
+    var D = class_(name: 'D', interfaces: [typeC]);
+    var typeD = interfaceType(D);
 
     _checkLeastUpperBound(typeB, typeD, typeA);
   }
 
   void test_sharedSuperinterface3() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', interfaces: [typeA]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', interfaces: [typeA]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', interfaces: [typeB]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', interfaces: [typeB]);
+    var typeC = interfaceType(C);
 
-    var D = _class(name: 'D', interfaces: [typeB]);
-    var typeD = _interfaceType(D);
+    var D = class_(name: 'D', interfaces: [typeB]);
+    var typeD = interfaceType(D);
 
     _checkLeastUpperBound(typeC, typeD, typeB);
   }
 
   void test_sharedSuperinterface4() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var A2 = _class(name: 'A2');
-    var typeA2 = _interfaceType(A2);
+    var A2 = class_(name: 'A2');
+    var typeA2 = interfaceType(A2);
 
-    var A3 = _class(name: 'A3');
-    var typeA3 = _interfaceType(A3);
+    var A3 = class_(name: 'A3');
+    var typeA3 = interfaceType(A3);
 
-    var B = _class(name: 'B', interfaces: [typeA, typeA2]);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', interfaces: [typeA, typeA2]);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', interfaces: [typeA, typeA3]);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', interfaces: [typeA, typeA3]);
+    var typeC = interfaceType(C);
 
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
@@ -2565,72 +3096,81 @@
   }
 
   void test_typeParam_boundedByParam() {
-    var S = _typeParameter('S');
-    var typeS = _typeParameterType(S);
+    var S = typeParameter('S');
+    var typeS = typeParameterTypeStar(S);
 
-    var T = _typeParameter('T', bound: typeS);
-    var typeT = _typeParameterType(T);
+    var T = typeParameter('T', bound: typeS);
+    var typeT = typeParameterTypeStar(T);
 
     _checkLeastUpperBound(typeT, typeS, typeS);
   }
 
   void test_typeParam_class_implements_Function_ignored() {
-    var A = _class(name: 'A', superType: functionType);
-    var T = _typeParameter('T', bound: _interfaceType(A));
-    _checkLeastUpperBound(_typeParameterType(T), _functionType(), objectType);
+    var A = class_(name: 'A', superType: typeProvider.functionType);
+    var T = typeParameter('T', bound: interfaceType(A));
+    _checkLeastUpperBound(typeParameterTypeStar(T),
+        functionTypeStar(returnType: voidType), objectType);
   }
 
   void test_typeParam_fBounded() {
-    var T = _typeParameter('Q');
-    var A = _class(name: 'A', typeParameters: [T]);
+    var T = typeParameter('Q');
+    var A = class_(name: 'A', typeParameters: [T]);
 
-    var S = _typeParameter('S');
-    var typeS = _typeParameterType(S);
-    S.bound = _interfaceType(A, typeArguments: [typeS]);
+    var S = typeParameter('S');
+    var typeS = typeParameterTypeStar(S);
+    S.bound = interfaceType(A, typeArguments: [typeS]);
 
-    var U = _typeParameter('U');
-    var typeU = _typeParameterType(U);
-    U.bound = _interfaceType(A, typeArguments: [typeU]);
+    var U = typeParameter('U');
+    var typeU = typeParameterTypeStar(U);
+    U.bound = interfaceType(A, typeArguments: [typeU]);
 
     _checkLeastUpperBound(
       typeS,
-      _typeParameterType(U),
-      _interfaceType(A, typeArguments: [objectType]),
+      typeParameterTypeStar(U),
+      interfaceType(A, typeArguments: [objectType]),
     );
   }
 
   void test_typeParam_function_bounded() {
-    var T = _typeParameter('T', bound: functionType);
-    _checkLeastUpperBound(_typeParameterType(T), _functionType(), functionType);
+    var T = typeParameter('T', bound: typeProvider.functionType);
+    _checkLeastUpperBound(
+      typeParameterTypeStar(T),
+      functionTypeStar(returnType: voidType),
+      typeProvider.functionType,
+    );
   }
 
   void test_typeParam_function_noBound() {
-    var T = _typeParameter('T');
-    _checkLeastUpperBound(_typeParameterType(T), _functionType(), objectType);
+    var T = typeParameter('T');
+    _checkLeastUpperBound(
+      typeParameterTypeStar(T),
+      functionTypeStar(returnType: voidType),
+      objectType,
+    );
   }
 
   void test_typeParam_interface_bounded() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
+    var A = class_(name: 'A');
+    var typeA = interfaceType(A);
 
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceType(B);
 
-    var C = _class(name: 'C', superType: typeA);
-    var typeC = _interfaceType(C);
+    var C = class_(name: 'C', superType: typeA);
+    var typeC = interfaceType(C);
 
-    var T = _typeParameter('T', bound: typeB);
-    var typeT = _typeParameterType(T);
+    var T = typeParameter('T', bound: typeB);
+    var typeT = typeParameterTypeStar(T);
 
     _checkLeastUpperBound(typeT, typeC, typeA);
   }
 
   void test_typeParam_interface_noBound() {
-    var T = _typeParameter('T');
-    var A = _class(name: 'A');
+    var T = typeParameter('T');
+    var A = class_(name: 'A');
     _checkLeastUpperBound(
-      _typeParameterType(T),
-      _interfaceType(A),
+      typeParameterTypeStar(T),
+      interfaceType(A),
       objectType,
     );
   }
@@ -2664,22 +3204,41 @@
   }
 
   void test_void() {
+    var T = typeParameter('T');
+    var A = class_(name: 'A');
     List<DartType> types = [
-      bottomType,
-      _functionType(),
-      _interfaceType(_class(name: 'A')),
-      _typeParameterType(_typeParameter('T')),
+      neverStar,
+      functionTypeStar(returnType: voidType),
+      interfaceType(A),
+      typeParameterTypeStar(T),
     ];
     for (DartType type in types) {
       _checkLeastUpperBound(
-        _functionType(returns: voidType),
-        _functionType(returns: type),
-        _functionType(returns: voidType),
+        functionTypeStar(returnType: voidType),
+        functionTypeStar(returnType: type),
+        functionTypeStar(returnType: voidType),
       );
     }
   }
 }
 
+//class Mix with ElementsTypesMixin {
+//  TypeProvider typeProvider;
+//  Dart2TypeSystem typeSystem;
+//
+//  FeatureSet get testFeatureSet {
+//    return FeatureSet.forTesting();
+//  }
+//
+//  void setUp() {
+//    var analysisContext = TestAnalysisContext(
+//      featureSet: testFeatureSet,
+//    );
+//    typeProvider = analysisContext.typeProvider;
+//    typeSystem = analysisContext.typeSystem;
+//  }
+//}
+
 class SubtypingTestBase extends AbstractTypeSystemTest {
   void _checkEquivalent(DartType type1, DartType type2) {
     _checkIsSubtypeOf(type1, type2);
@@ -2763,21 +3322,21 @@
 @reflectiveTest
 class TypeSystemTest extends AbstractTypeSystemTest {
   InterfaceTypeImpl get functionClassTypeNone {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.functionType.element,
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl get functionClassTypeQuestion {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.functionType.element,
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl get functionClassTypeStar {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.functionType.element,
       nullabilitySuffix: NullabilitySuffix.star,
     );
@@ -2787,23 +3346,20 @@
       .withNullability(NullabilitySuffix.none);
 
   FunctionTypeImpl get nothingToVoidFunctionTypeNone {
-    return _functionType(
-      returns: voidType,
-      nullabilitySuffix: NullabilitySuffix.none,
+    return functionTypeNone(
+      returnType: voidType,
     );
   }
 
   FunctionTypeImpl get nothingToVoidFunctionTypeQuestion {
-    return _functionType(
-      returns: voidType,
-      nullabilitySuffix: NullabilitySuffix.question,
+    return functionTypeQuestion(
+      returnType: voidType,
     );
   }
 
   FunctionTypeImpl get nothingToVoidFunctionTypeStar {
-    return _functionType(
-      returns: voidType,
-      nullabilitySuffix: NullabilitySuffix.star,
+    return functionTypeStar(
+      returnType: voidType,
     );
   }
 
@@ -2823,21 +3379,21 @@
       .withNullability(NullabilitySuffix.star);
 
   InterfaceTypeImpl get stringClassTypeNone {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.stringType.element,
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl get stringClassTypeQuestion {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.stringType.element,
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl get stringClassTypeStar {
-    return _interfaceType(
+    return interfaceType(
       typeProvider.stringType.element,
       nullabilitySuffix: NullabilitySuffix.star,
     );
@@ -2845,7 +3401,7 @@
 
   InterfaceTypeImpl futureOrTypeNone({@required DartType argument}) {
     var element = typeProvider.futureOrElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.none,
@@ -2854,7 +3410,7 @@
 
   InterfaceTypeImpl futureOrTypeQuestion({@required DartType argument}) {
     var element = typeProvider.futureOrElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.question,
@@ -2863,7 +3419,7 @@
 
   InterfaceTypeImpl futureOrTypeStar({@required DartType argument}) {
     var element = typeProvider.futureOrElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.star,
@@ -2872,7 +3428,7 @@
 
   InterfaceTypeImpl listClassTypeNone(DartType argument) {
     var element = typeProvider.listElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.none,
@@ -2881,7 +3437,7 @@
 
   InterfaceTypeImpl listClassTypeQuestion(DartType argument) {
     var element = typeProvider.listElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.question,
@@ -2890,7 +3446,7 @@
 
   InterfaceTypeImpl listClassTypeStar(DartType argument) {
     var element = typeProvider.listElement;
-    return _interfaceType(
+    return interfaceType(
       element,
       typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.star,
@@ -3019,7 +3575,7 @@
   }
 
   test_isNonNullable_never() {
-    expect(typeSystem.isNonNullable(neverType), true);
+    expect(typeSystem.isNonNullable(neverNone), true);
   }
 
   test_isNonNullable_null() {
@@ -3029,7 +3585,7 @@
   test_isNonNullable_typeParameter_noneBound_none() {
     expect(
       typeSystem.isNonNullable(
-        typeParameterTypeNone(bound: noneType),
+        _typeParameterTypeNone(bound: noneType),
       ),
       true,
     );
@@ -3038,7 +3594,7 @@
   test_isNonNullable_typeParameter_noneBound_question() {
     expect(
       typeSystem.isNonNullable(
-        typeParameterTypeQuestion(bound: noneType),
+        _typeParameterTypeQuestion(bound: noneType),
       ),
       false,
     );
@@ -3047,7 +3603,7 @@
   test_isNonNullable_typeParameter_questionBound_none() {
     expect(
       typeSystem.isNonNullable(
-        typeParameterTypeNone(bound: questionType),
+        _typeParameterTypeNone(bound: questionType),
       ),
       false,
     );
@@ -3056,7 +3612,7 @@
   test_isNonNullable_typeParameter_questionBound_question() {
     expect(
       typeSystem.isNonNullable(
-        typeParameterTypeQuestion(bound: questionType),
+        _typeParameterTypeQuestion(bound: questionType),
       ),
       false,
     );
@@ -3065,7 +3621,7 @@
   test_isNonNullable_typeParameter_starBound_star() {
     expect(
       typeSystem.isNonNullable(
-        typeParameterTypeStar(bound: starType),
+        _typeParameterTypeStar(bound: starType),
       ),
       true,
     );
@@ -3197,11 +3753,11 @@
   }
 
   test_isNullable_Never() {
-    expect(typeSystem.isNullable(neverType), false);
+    expect(typeSystem.isNullable(neverNone), false);
   }
 
   test_isNullable_never() {
-    expect(typeSystem.isNullable(neverType), false);
+    expect(typeSystem.isNullable(neverNone), false);
   }
 
   test_isNullable_null() {
@@ -3211,7 +3767,7 @@
   test_isNullable_typeParameter_noneBound_none() {
     expect(
       typeSystem.isNullable(
-        typeParameterTypeNone(bound: noneType),
+        _typeParameterTypeNone(bound: noneType),
       ),
       false,
     );
@@ -3220,7 +3776,7 @@
   test_isNullable_typeParameter_noneBound_question() {
     expect(
       typeSystem.isNullable(
-        typeParameterTypeQuestion(bound: noneType),
+        _typeParameterTypeQuestion(bound: noneType),
       ),
       true,
     );
@@ -3229,7 +3785,7 @@
   test_isNullable_typeParameter_questionBound_none() {
     expect(
       typeSystem.isNullable(
-        typeParameterTypeNone(bound: questionType),
+        _typeParameterTypeNone(bound: questionType),
       ),
       false,
     );
@@ -3238,7 +3794,7 @@
   test_isNullable_typeParameter_questionBound_question() {
     expect(
       typeSystem.isNullable(
-        typeParameterTypeQuestion(bound: questionType),
+        _typeParameterTypeQuestion(bound: questionType),
       ),
       true,
     );
@@ -3247,7 +3803,7 @@
   test_isNullable_typeParameter_starBound_star() {
     expect(
       typeSystem.isNullable(
-        typeParameterTypeStar(bound: starType),
+        _typeParameterTypeStar(bound: starType),
       ),
       false,
     );
@@ -3289,7 +3845,7 @@
   }
 
   test_isPotentiallyNonNullable_never() {
-    expect(typeSystem.isPotentiallyNonNullable(neverType), true);
+    expect(typeSystem.isPotentiallyNonNullable(neverNone), true);
   }
 
   test_isPotentiallyNonNullable_none() {
@@ -3344,7 +3900,7 @@
   }
 
   test_isPotentiallyNullable_never() {
-    expect(typeSystem.isPotentiallyNullable(neverType), false);
+    expect(typeSystem.isPotentiallyNullable(neverNone), false);
   }
 
   test_isPotentiallyNullable_none() {
@@ -3432,28 +3988,22 @@
   }
 
   test_promoteToNonNull_never() {
-    expect(typeSystem.promoteToNonNull(neverType), neverType);
+    expect(typeSystem.promoteToNonNull(neverNone), neverNone);
   }
 
   test_promoteToNonNull_null() {
-    expect(typeSystem.promoteToNonNull(nullType), neverType);
+    expect(typeSystem.promoteToNonNull(nullType), neverNone);
   }
 
   test_promoteToNonNull_typeParameter_noneBound_none() {
-    var element = _typeParameter('T', bound: noneType);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
+    var element = typeParameter('T', bound: noneType);
+    var type = typeParameterTypeNone(element);
     expect(typeSystem.promoteToNonNull(type), same(type));
   }
 
   test_promoteToNonNull_typeParameter_noneBound_question() {
-    var element = _typeParameter('T', bound: stringClassTypeNone);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.question,
-    );
+    var element = typeParameter('T', bound: stringClassTypeNone);
+    var type = typeParameterTypeQuestion(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3462,11 +4012,8 @@
   }
 
   test_promoteToNonNull_typeParameter_nullBound_none() {
-    var element = _typeParameter('T', bound: null);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
+    var element = typeParameter('T', bound: null);
+    var type = typeParameterTypeNone(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3476,11 +4023,8 @@
   }
 
   test_promoteToNonNull_typeParameter_questionBound_none() {
-    var element = _typeParameter('T', bound: stringClassTypeQuestion);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
+    var element = typeParameter('T', bound: stringClassTypeQuestion);
+    var type = typeParameterTypeNone(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3490,11 +4034,8 @@
   }
 
   test_promoteToNonNull_typeParameter_questionBound_question() {
-    var element = _typeParameter('T', bound: stringClassTypeQuestion);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.question,
-    );
+    var element = typeParameter('T', bound: stringClassTypeQuestion);
+    var type = typeParameterTypeQuestion(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3504,11 +4045,8 @@
   }
 
   test_promoteToNonNull_typeParameter_questionBound_star() {
-    var element = _typeParameter('T', bound: stringClassTypeQuestion);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
+    var element = typeParameter('T', bound: stringClassTypeQuestion);
+    var type = typeParameterTypeStar(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3518,11 +4056,8 @@
   }
 
   test_promoteToNonNull_typeParameter_starBound_none() {
-    var element = _typeParameter('T', bound: stringClassTypeStar);
-    var type = _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
+    var element = typeParameter('T', bound: stringClassTypeStar);
+    var type = typeParameterTypeNone(element);
     _assertPromotedTypeParameterType(
       typeSystem.promoteToNonNull(type),
       baseElement: element,
@@ -3538,30 +4073,6 @@
     );
   }
 
-  DartType typeParameterTypeNone({@required DartType bound}) {
-    var element = _typeParameter('T', bound: bound);
-    return _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
-  }
-
-  DartType typeParameterTypeQuestion({@required DartType bound}) {
-    var element = _typeParameter('T', bound: bound);
-    return _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.question,
-    );
-  }
-
-  DartType typeParameterTypeStar({@required DartType bound}) {
-    var element = _typeParameter('T', bound: bound);
-    return _typeParameterType(
-      element,
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-  }
-
   /// If [expectedBound] is `null`, the element of [actual] must be the same
   /// as the [baseElement].  Otherwise the element of [actual] must be a
   /// [TypeParameterMember] with the [baseElement] and the [expectedBound].
@@ -3573,11 +4084,26 @@
   }) {
     if (expectedBound != null) {
       var actualMember = actual.element as TypeParameterMember;
-      expect(actualMember.baseElement, same(baseElement));
+      expect(actualMember.declaration, same(baseElement));
       expect(actualMember.bound, expectedBound);
     } else {
       expect(actual.element, same(baseElement));
     }
     expect(actual.nullabilitySuffix, expectedNullabilitySuffix);
   }
+
+  DartType _typeParameterTypeNone({@required DartType bound}) {
+    var element = typeParameter('T', bound: bound);
+    return typeParameterTypeNone(element);
+  }
+
+  DartType _typeParameterTypeQuestion({@required DartType bound}) {
+    var element = typeParameter('T', bound: bound);
+    return typeParameterTypeQuestion(element);
+  }
+
+  DartType _typeParameterTypeStar({@required DartType bound}) {
+    var element = typeParameter('T', bound: bound);
+    return typeParameterTypeStar(element);
+  }
 }
diff --git a/pkg/analyzer/test/instrumentation/instrumentation_test.dart b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
index c4b408e..dd56b5e 100644
--- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart
+++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -16,57 +14,47 @@
 @reflectiveTest
 class InstrumentationServiceTest {
   void assertNormal(
-      TestInstrumentationServer server, String tag, String message) {
-    String sent = server.normalChannel.toString();
+      TestInstrumentationLogger logger, String tag, String message) {
+    String sent = logger.logged.toString();
     if (!sent.endsWith(':$tag:$message\n')) {
       fail('Expected "...:$tag:$message", found "$sent"');
     }
   }
 
   void test_logError_withColon() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     service.logError('Error:message');
-    assertNormal(server, InstrumentationService.TAG_ERROR, 'Error::message');
+    assertNormal(logger, InstrumentationLogAdapter.TAG_ERROR, 'Error::message');
   }
 
   void test_logError_withLeadingColon() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     service.logError(':a:bb');
-    assertNormal(server, InstrumentationService.TAG_ERROR, '::a::bb');
+    assertNormal(logger, InstrumentationLogAdapter.TAG_ERROR, '::a::bb');
   }
 
   void test_logError_withoutColon() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String message = 'Error message';
     service.logError(message);
-    assertNormal(server, InstrumentationService.TAG_ERROR, message);
+    assertNormal(logger, InstrumentationLogAdapter.TAG_ERROR, message);
   }
 
   void test_logException_noTrace() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String message = 'exceptionMessage';
     service.logException(message);
-    assertNormal(server, InstrumentationService.TAG_EXCEPTION, '$message:null');
-  }
-
-  void test_logFileRead() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
-    String path = '/file/path';
-    int time = 978336000000;
-    String content = 'class C {\n}\n';
-    service.logFileRead(path, time, content);
     assertNormal(
-        server, InstrumentationService.TAG_FILE_READ, '$path:$time:$content');
+        logger, InstrumentationLogAdapter.TAG_EXCEPTION, '$message:null');
   }
 
   void test_logLogEntry() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String level = 'level';
     DateTime time = new DateTime(2001);
     String message = 'message';
@@ -74,113 +62,112 @@
     String stackTraceText = 'stackTrace';
     StackTrace stackTrace = new StackTrace.fromString(stackTraceText);
     service.logLogEntry(level, time, message, exception, stackTrace);
-    assertNormal(server, InstrumentationService.TAG_LOG_ENTRY,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_LOG_ENTRY,
         '$level:${time.millisecondsSinceEpoch}:$message:$exception:$stackTraceText');
   }
 
   void test_logNotification() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String message = 'notificationText';
     service.logNotification(message);
-    assertNormal(server, InstrumentationService.TAG_NOTIFICATION, message);
+    assertNormal(logger, InstrumentationLogAdapter.TAG_NOTIFICATION, message);
   }
 
   void test_logPluginError() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     PluginData plugin = new PluginData('path', 'name', 'version');
     String code = 'code';
     String message = 'exceptionMessage';
     String stackTraceText = 'stackTrace';
     service.logPluginError(plugin, code, message, stackTraceText);
-    assertNormal(server, InstrumentationService.TAG_PLUGIN_ERROR,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_ERROR,
         '$code:$message:$stackTraceText:path:name:version');
   }
 
   void test_logPluginException_noTrace() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     PluginData plugin = new PluginData('path', 'name', 'version');
     String message = 'exceptionMessage';
     service.logPluginException(plugin, message, null);
-    assertNormal(server, InstrumentationService.TAG_PLUGIN_EXCEPTION,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_EXCEPTION,
         '$message:null:path:name:version');
   }
 
   void test_logPluginException_withTrace() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     PluginData plugin = new PluginData('path', 'name', 'version');
     String message = 'exceptionMessage';
     String stackTraceText = 'stackTrace';
     StackTrace stackTrace = new StackTrace.fromString(stackTraceText);
     service.logPluginException(plugin, message, stackTrace);
-    assertNormal(server, InstrumentationService.TAG_PLUGIN_EXCEPTION,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_EXCEPTION,
         '$message:$stackTraceText:path:name:version');
   }
 
   void test_logPluginNotification() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String notification = 'notification';
     service.logPluginNotification('path', notification);
-    assertNormal(server, InstrumentationService.TAG_PLUGIN_NOTIFICATION,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_NOTIFICATION,
         '$notification:path::');
   }
 
   void test_logPluginRequest() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String request = 'request';
     service.logPluginRequest('path', request);
-    assertNormal(
-        server, InstrumentationService.TAG_PLUGIN_REQUEST, '$request:path::');
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_REQUEST,
+        '$request:path::');
   }
 
   void test_logPluginResponse() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String response = 'response';
     service.logPluginResponse('path', response);
-    assertNormal(
-        server, InstrumentationService.TAG_PLUGIN_RESPONSE, '$response:path::');
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_RESPONSE,
+        '$response:path::');
   }
 
   void test_logPluginTimeout() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     PluginData plugin = new PluginData('path', 'name', 'version');
     String request = 'request';
     service.logPluginTimeout(plugin, request);
-    assertNormal(server, InstrumentationService.TAG_PLUGIN_TIMEOUT,
+    assertNormal(logger, InstrumentationLogAdapter.TAG_PLUGIN_TIMEOUT,
         '$request:path:name:version');
   }
 
   void test_logRequest() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String message = 'requestText';
     service.logRequest(message);
-    assertNormal(server, InstrumentationService.TAG_REQUEST, message);
+    assertNormal(logger, InstrumentationLogAdapter.TAG_REQUEST, message);
   }
 
   void test_logResponse() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     String message = 'responseText';
     service.logResponse(message);
-    assertNormal(server, InstrumentationService.TAG_RESPONSE, message);
+    assertNormal(logger, InstrumentationLogAdapter.TAG_RESPONSE, message);
   }
 
   void test_logVersion() {
-    TestInstrumentationServer server = new TestInstrumentationServer();
-    InstrumentationService service = new InstrumentationService(server);
+    TestInstrumentationLogger logger = new TestInstrumentationLogger();
+    InstrumentationService service = new InstrumentationLogAdapter(logger);
     service.logVersion('myUuid', 'someClientId', 'someClientVersion',
         'aServerVersion', 'anSdkVersion');
-    expect(server.normalChannel.toString(), '');
     expect(
-        server.priorityChannel.toString(),
+        logger.logged.toString(),
         endsWith(
             ':myUuid:someClientId:someClientVersion:aServerVersion:anSdkVersion\n'));
   }
@@ -188,67 +175,38 @@
 
 @reflectiveTest
 class MulticastInstrumentationServerTest {
-  TestInstrumentationServer serverA = new TestInstrumentationServer();
-  TestInstrumentationServer serverB = new TestInstrumentationServer();
-  MulticastInstrumentationServer server;
+  TestInstrumentationLogger loggerA = new TestInstrumentationLogger();
+  TestInstrumentationLogger loggerB = new TestInstrumentationLogger();
+  MulticastInstrumentationService logger;
 
   void setUp() {
-    server = new MulticastInstrumentationServer([serverA, serverB]);
+    logger = new MulticastInstrumentationService([
+      InstrumentationLogAdapter(loggerA),
+      InstrumentationLogAdapter(loggerB)
+    ]);
   }
 
   void test_log() {
-    server.log('foo bar');
-    _assertNormal(serverA, 'foo bar');
-    _assertNormal(serverB, 'foo bar');
+    logger.logInfo('foo bar');
+    _assertLogged(loggerA, 'foo bar');
+    _assertLogged(loggerB, 'foo bar');
   }
 
-  void test_logWithPriority() {
-    server.logWithPriority('foo bar');
-    _assertPriority(serverA, 'foo bar');
-    _assertPriority(serverB, 'foo bar');
-  }
-
-  void test_shutdown() {
-    server.shutdown();
-  }
-
-  void _assertNormal(TestInstrumentationServer server, String message) {
-    String sent = server.normalChannel.toString();
-    if (!sent.endsWith('$message\n')) {
-      fail('Expected "...$message", found "$sent"');
-    }
-  }
-
-  void _assertPriority(TestInstrumentationServer server, String message) {
-    String sent = server.priorityChannel.toString();
+  void _assertLogged(TestInstrumentationLogger logger, String message) {
+    String sent = logger.logged.toString();
     if (!sent.endsWith('$message\n')) {
       fail('Expected "...$message", found "$sent"');
     }
   }
 }
 
-class TestInstrumentationServer implements InstrumentationServer {
-  StringBuffer normalChannel = new StringBuffer();
-  StringBuffer priorityChannel = new StringBuffer();
-
-  @override
-  String get describe => 'test instrumentation';
-
-  @override
-  String get sessionId => '';
+class TestInstrumentationLogger implements InstrumentationLogger {
+  StringBuffer logged = new StringBuffer();
 
   @override
   void log(String message) {
-    normalChannel.writeln(message);
+    logged.writeln(message);
   }
 
-  @override
-  void logWithPriority(String message) {
-    priorityChannel.writeln(message);
-  }
-
-  @override
-  Future shutdown() async {
-    // Ignored
-  }
+  Future<void> shutdown() async {}
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b97a484..2bba18a 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -33,10 +33,10 @@
   });
 }
 
-final isBottomType = new TypeMatcher<BottomTypeImpl>();
-
 final isDynamicType = new TypeMatcher<DynamicTypeImpl>();
 
+final isNeverType = new TypeMatcher<NeverTypeImpl>();
+
 final isVoidType = new TypeMatcher<VoidTypeImpl>();
 
 /**
@@ -132,7 +132,7 @@
     Element expectedBase,
     Map<String, String> expectedSubstitution,
   ) {
-    expect(actual.baseElement, same(expectedBase));
+    expect(actual.declaration, same(expectedBase));
 
     var actualMapString = actual.substitution.map.map(
       (k, v) => MapEntry(k.name, '$v'),
@@ -2188,7 +2188,7 @@
     MethodMember actualElement = indexExpression.staticElement;
     MethodMember expectedElement = listIntType.getMethod('[]');
     expect(actualElement.name, '[]');
-    expect(actualElement.baseElement, same(expectedElement.baseElement));
+    expect(actualElement.declaration, same(expectedElement.declaration));
     expect(actualElement.returnType, intType);
     expect(actualElement.parameters[0].type, intType);
   }
@@ -2826,7 +2826,7 @@
     expect(result.errors, isNotEmpty);
 
     var throwExpression = findNode.throw_('throw 42;');
-    expect(throwExpression.staticType, isBottomType);
+    expect(throwExpression.staticType, isNeverType);
     assertType(throwExpression.expression, 'int');
   }
 
@@ -2838,7 +2838,7 @@
     expect(result.errors, isNotEmpty);
 
     var throwExpression = findNode.throw_('throw 42;');
-    expect(throwExpression.staticType, isBottomType);
+    expect(throwExpression.staticType, isNeverType);
     assertType(throwExpression.expression, 'int');
   }
 
@@ -3891,7 +3891,7 @@
     expect(result.errors, isNotEmpty);
 
     var rethrowExpression = findNode.rethrow_('rethrow;');
-    expect(rethrowExpression.staticType, isBottomType);
+    expect(rethrowExpression.staticType, isNeverType);
   }
 
   test_invalid_tryCatch_1() async {
@@ -4253,7 +4253,7 @@
     FunctionElement fElement = fNode.declaredElement;
 
     expect(fElement.type.toString(),
-        'void Function<T extends U,U,V extends U>(T, U, V)');
+        'void Function<T extends U, U, V extends U>(T, U, V)');
     var tElement = fElement.typeParameters[0];
     var uElement = fElement.typeParameters[1];
     var vElement = fElement.typeParameters[2];
@@ -8700,18 +8700,7 @@
       expect(actual.type, memberType);
     }
 
-    ParameterElement base = actual;
-    if (actual is ParameterMember) {
-      base = actual.baseElement;
-      // Unwrap ParameterMember one more time.
-      // By some reason we wrap in twice.
-      if (base is ParameterMember) {
-        ParameterMember member = base;
-        base = member.baseElement;
-      }
-    }
-    ParameterElement baseActual = base;
-    expect(baseActual, same(expected));
+    expect(actual.declaration, same(expected));
 
     if (argument is NamedExpression) {
       SimpleIdentifier name = argument.name.label;
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
index 13e4a36..f29e8ab 100644
--- a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -776,6 +776,34 @@
 ''');
   }
 
+  test_featureSet_add() async {
+    assertNotSameSignature(r'''
+class A {}
+''', r'''
+// @dart = 2.5
+class A {}
+''');
+  }
+
+  test_featureSet_change() async {
+    assertNotSameSignature(r'''
+// @dart = 2.6
+class A {}
+''', r'''
+// @dart = 2.5
+class A {}
+''');
+  }
+
+  test_featureSet_remove() async {
+    assertNotSameSignature(r'''
+// @dart = 2.5
+class A {}
+''', r'''
+class A {}
+''');
+  }
+
   test_function_annotation() {
     assertNotSameSignature(r'''
 const a = 0;
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
index 2dd3de6..107a20e 100644
--- a/pkg/analyzer/test/src/dart/ast/parse_base.dart
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -31,6 +31,7 @@
       ..configureFeatures(featureSet);
 
     var token = scanner.tokenize();
+    featureSet = scanner.featureSet;
 
     var useFasta = analysisOptions.useFastaParser;
     var parser = Parser(source, errorListener,
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 3af77e7..bee0bbf 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@@ -25,14 +24,6 @@
 
 VoidTypeImpl get voidType => VoidTypeImpl.instance;
 
-Element getBaseElement(Element e) {
-  if (e is Member) {
-    return e.baseElement;
-  } else {
-    return e;
-  }
-}
-
 @reflectiveTest
 class FunctionTypeTest with ElementsTypesMixin {
   final TypeProvider typeProvider = TestTypeProvider();
@@ -111,9 +102,195 @@
         nullabilitySuffix: NullabilitySuffix.star,
       );
 
+  test_equality_leftRequired_rightPositional() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        positionalParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_differentName() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'b', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_differentType() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.doubleType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_equal() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+        namedParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+        namedParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    expect(f1, f2);
+  }
+
+  test_equality_namedParameters_extraLeft() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+        namedParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_extraRight() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+        namedParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_required_left() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedRequiredParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_namedParameters_required_right() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        namedRequiredParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_requiredParameters_extraLeft() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+        requiredParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_equality_requiredParameters_extraRight() {
+    var f1 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+      ],
+    );
+    var f2 = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+        requiredParameter(name: 'b', type: typeProvider.doubleType),
+      ],
+    );
+    expect(f1, isNot(equals(f2)));
+  }
+
+  test_new_sortsNamedParameters() {
+    var f = functionTypeNone(
+      returnType: typeProvider.voidType,
+      parameters: [
+        requiredParameter(name: 'a', type: typeProvider.intType),
+        namedParameter(name: 'c', type: typeProvider.intType),
+        namedParameter(name: 'b', type: typeProvider.intType),
+      ],
+    );
+    var parameters = f.parameters;
+    expect(parameters, hasLength(3));
+    expect(parameters[0].name, 'a');
+    expect(parameters[1].name, 'b');
+    expect(parameters[2].name, 'c');
+  }
+
   test_synthetic() {
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: const [],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f, element: isNull);
   }
 
@@ -121,9 +298,12 @@
     // T Function<T>(T x)
     var t = typeParameter('T');
     var x = requiredParameter(name: 'x', type: typeParameterType(t));
-    FunctionType f = new FunctionTypeImpl.synthetic(
-        typeParameterType(t), [t], [x],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: [t],
+      parameters: [x],
+      returnType: typeParameterType(t),
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -137,14 +317,22 @@
   test_synthetic_instantiate_argument_length_mismatch() {
     // dynamic Function<T>()
     var t = typeParameter('T');
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [t], [],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: [t],
+      parameters: const [],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     expect(() => f.instantiate([]), throwsA(new TypeMatcher<ArgumentError>()));
   }
 
   test_synthetic_instantiate_no_type_formals() {
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: const [],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     expect(f.instantiate([]), same(f));
   }
 
@@ -152,9 +340,12 @@
     // T Function<T>(int x)
     var t = typeParameter('T');
     var x = requiredParameter(name: 'x', type: intType);
-    FunctionType f = new FunctionTypeImpl.synthetic(
-        typeParameterType(t), [t], [x],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: [t],
+      parameters: [x],
+      returnType: typeParameterType(t),
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -167,8 +358,12 @@
 
   test_synthetic_namedParameter() {
     var p = namedParameter(name: 'x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: [p],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function({x: Object})',
@@ -181,8 +376,12 @@
 
   test_synthetic_normalParameter() {
     var p = requiredParameter(name: 'x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: [p],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function(Object)',
@@ -196,8 +395,12 @@
 
   test_synthetic_optionalParameter() {
     var p = positionalParameter(name: 'x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: [p],
+      returnType: dynamicType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function([Object])',
@@ -210,8 +413,12 @@
   }
 
   test_synthetic_returnType() {
-    FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], [],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: const [],
+      returnType: objectType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f,
         element: isNull,
         displayName: 'Object Function()',
@@ -269,9 +476,12 @@
 
   test_synthetic_typeFormals() {
     var t = typeParameter('T');
-    FunctionType f = new FunctionTypeImpl.synthetic(
-        typeParameterType(t), [t], [],
-        nullabilitySuffix: NullabilitySuffix.star);
+    FunctionType f = new FunctionTypeImpl(
+      typeFormals: [t],
+      parameters: const [],
+      returnType: typeParameterType(t),
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     basicChecks(f,
         element: isNull,
         displayName: 'T Function<T>()',
diff --git a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
new file mode 100644
index 0000000..b0b9091
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -0,0 +1,316 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import '../../../generated/test_analysis_context.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NullabilityEliminatorTest);
+  });
+}
+
+@reflectiveTest
+class NullabilityEliminatorTest with ElementsTypesMixin, TypeProviderTypes {
+  @override
+  TypeProvider typeProvider;
+
+  void setUp() {
+    var analysisContext = TestAnalysisContext(
+      featureSet: FeatureSet.forTesting(
+        sdkVersion: '2.6.0',
+        additionalFeatures: [Feature.non_nullable],
+      ),
+    );
+    typeProvider = analysisContext.typeProvider;
+  }
+
+  test_dynamicType() {
+    _verifySame(typeProvider.dynamicType);
+  }
+
+  test_functionType() {
+    _verify(
+      functionTypeNone(returnType: voidType),
+      functionTypeStar(returnType: voidType),
+    );
+
+    _verify(
+      functionTypeQuestion(returnType: voidType),
+      functionTypeStar(returnType: voidType),
+    );
+
+    _verifySame(
+      functionTypeStar(returnType: voidType),
+    );
+  }
+
+  test_functionType_parameters() {
+    _verify(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: voidType,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidType,
+      ),
+    );
+
+    _verify(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intQuestion),
+        ],
+        returnType: voidType,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidType,
+      ),
+    );
+
+    _verifySame(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidType,
+      ),
+    );
+  }
+
+  test_functionType_returnType() {
+    _verify(
+      functionTypeStar(returnType: intNone),
+      functionTypeStar(returnType: intStar),
+    );
+
+    _verify(
+      functionTypeStar(returnType: intQuestion),
+      functionTypeStar(returnType: intStar),
+    );
+
+    _verifySame(
+      functionTypeStar(returnType: intStar),
+    );
+  }
+
+  test_functionType_typeParameters() {
+    var T = typeParameter('T');
+
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeNone(T),
+      ),
+      'T Function<T>()',
+      'T* Function<T>()*',
+    );
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeQuestion(T),
+      ),
+      'T? Function<T>()',
+      'T* Function<T>()*',
+    );
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeStar(T),
+      ),
+      'T* Function<T>()',
+      'T* Function<T>()*',
+    );
+
+    _verifySame(
+      functionTypeStar(
+        typeFormals: [T],
+        returnType: typeParameterTypeStar(T),
+      ),
+    );
+  }
+
+  test_functionType_typeParameters_bound_none() {
+    var T = typeParameter('T', bound: intNone);
+
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeNone(T),
+      ),
+      'T Function<T extends int>()',
+      'T* Function<T extends int*>()*',
+    );
+  }
+
+  test_functionType_typeParameters_bound_question() {
+    var T = typeParameter('T', bound: intQuestion);
+
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeNone(T),
+      ),
+      'T Function<T extends int?>()',
+      'T* Function<T extends int*>()*',
+    );
+  }
+
+  test_functionType_typeParameters_bound_star() {
+    var T = typeParameter('T', bound: intStar);
+
+    _verifyStr(
+      functionTypeNone(
+        typeFormals: [T],
+        returnType: typeParameterTypeNone(T),
+      ),
+      'T Function<T extends int*>()',
+      'T* Function<T extends int*>()*',
+    );
+
+    _verifySame(
+      functionTypeStar(
+        typeFormals: [T],
+        returnType: typeParameterTypeStar(T),
+      ),
+    );
+  }
+
+  test_interfaceType_int() {
+    _verify(intNone, intStar);
+    _verify(intQuestion, intStar);
+    _verifySame(intStar);
+  }
+
+  test_interfaceType_list() {
+    var expected = listStar(intStar);
+
+    _verify(listNone(intNone), expected);
+    _verify(listNone(intQuestion), expected);
+    _verify(listNone(intStar), expected);
+
+    _verify(listQuestion(intNone), expected);
+    _verify(listQuestion(intQuestion), expected);
+    _verify(listQuestion(intStar), expected);
+
+    _verify(listStar(intNone), expected);
+    _verify(listStar(intQuestion), expected);
+    _verifySame(listStar(intStar));
+  }
+
+  test_neverType() {
+    _verify(neverNone, neverStar);
+    _verify(neverQuestion, neverStar);
+    _verifySame(neverStar);
+  }
+
+  test_typeParameterType() {
+    var T = typeParameter('T');
+    _verify(
+      typeParameterTypeNone(T),
+      typeParameterTypeStar(T),
+    );
+    _verify(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeStar(T),
+    );
+    _verifySame(
+      typeParameterTypeStar(T),
+    );
+  }
+
+  test_voidType() {
+    _verifySame(typeProvider.voidType);
+  }
+
+  String _typeToString(TypeImpl type) {
+    return type.toString(withNullability: true);
+  }
+
+  void _verify(DartType input, DartType expected) {
+    var result = NullabilityEliminator.perform(input);
+    expect(result, isNot(same(input)));
+    expect(result, expected);
+  }
+
+  void _verifySame(DartType input) {
+    var result = NullabilityEliminator.perform(input);
+    expect(result, same(input));
+  }
+
+  void _verifyStr(DartType input, String inputStr, String expectedStr) {
+    expect(_typeToString(input), inputStr);
+
+    var result = NullabilityEliminator.perform(input);
+    expect(result, isNot(same(input)));
+    expect(_typeToString(result), expectedStr);
+  }
+}
+
+mixin TypeProviderTypes {
+  DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
+
+  InterfaceType get intNone {
+    return typeProvider.intElement.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get intQuestion {
+    return typeProvider.intElement.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get intStar {
+    return typeProvider.intElement.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  TypeProvider get typeProvider;
+
+  VoidTypeImpl get voidType => typeProvider.voidType;
+
+  InterfaceType listNone(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType listQuestion(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType listStar(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 4def2d5..354f34e 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -41,7 +42,7 @@
     ];
 
     var subtypes = <DartType>[
-      bottomNone,
+      neverNone,
       nullNone,
       objectNone,
     ];
@@ -96,7 +97,7 @@
     ];
 
     var subtypes = <DartType>[
-      bottomNone,
+      neverNone,
     ];
 
     var supertypes = <DartType>[
@@ -110,7 +111,7 @@
       nullNone,
       nullStar,
       nullQuestion,
-      bottomQuestion,
+      neverQuestion,
     ];
 
     _checkGroups(
@@ -133,9 +134,9 @@
       nullNone,
       nullQuestion,
       nullStar,
-      bottomNone,
-      bottomQuestion,
-      bottomStar,
+      neverNone,
+      neverQuestion,
+      neverStar,
     ];
 
     var supertypes = <DartType>[
@@ -171,9 +172,9 @@
       nullNone,
       nullStar,
       nullQuestion,
-      bottomNone,
-      bottomStar,
-      bottomQuestion,
+      neverNone,
+      neverStar,
+      neverQuestion,
     ];
 
     var supertypes = <DartType>[
@@ -202,7 +203,7 @@
       nullNone,
       nullQuestion,
       nullStar,
-      bottomQuestion,
+      neverQuestion,
     ];
 
     var supertypes = <DartType>[
@@ -215,7 +216,7 @@
     ];
 
     var subtypes = <DartType>[
-      bottomNone,
+      neverNone,
     ];
 
     var unrelated = <DartType>[
@@ -248,7 +249,7 @@
     ];
 
     var subtypes = <DartType>[
-      bottomNone,
+      neverNone,
     ];
 
     var unrelated = <DartType>[
@@ -280,9 +281,22 @@
       DartTypeVisitor.visit(type, typeParameterCollector);
       for (var typeParameter in typeParameterCollector.typeParameters) {
         if (typeParameter is TypeParameterMember) {
-          var boundTypeImpl = typeParameter.bound as TypeImpl;
-          var boundTypeStr = boundTypeImpl.toString(withNullability: true);
-          typeStr += ', ${typeParameter.name} & ' + boundTypeStr;
+          var base = typeParameter.declaration;
+          var baseBound = base.bound as TypeImpl;
+          if (baseBound != null) {
+            var baseBoundStr = baseBound.toString(withNullability: true);
+            typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
+          }
+
+          var bound = typeParameter.bound as TypeImpl;
+          var boundStr = bound.toString(withNullability: true);
+          typeStr += ', ${typeParameter.name} & ' + boundStr;
+        } else {
+          var bound = typeParameter.bound as TypeImpl;
+          if (bound != null) {
+            var boundStr = bound.toString(withNullability: true);
+            typeStr += ', ${typeParameter.name} extends ' + boundStr;
+          }
         }
       }
 
@@ -351,13 +365,6 @@
     expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
   }
 
-  void isSubtype3({
-    String strT0,
-    String strT1,
-  }) {
-    isSubtype2(strT0, strT1);
-  }
-
   InterfaceType iterableStar(DartType type) {
     return typeProvider.iterableElement.instantiate(
       typeArguments: [type],
@@ -400,30 +407,6 @@
     _defineTypes();
   }
 
-  test_bottom_01() {
-    isSubtype(bottomNone, numNone, strT0: 'Never', strT1: 'num');
-  }
-
-  test_bottom_02() {
-    isSubtype(bottomNone, numStar, strT0: 'Never', strT1: 'num*');
-  }
-
-  test_bottom_03() {
-    isSubtype(bottomNone, numQuestion, strT0: 'Never', strT1: 'num?');
-  }
-
-  test_bottom_04() {
-    isSubtype(bottomNone, nullQuestion, strT0: 'Never', strT1: 'Null?');
-  }
-
-  test_bottom_05() {
-    isSubtype(bottomNone, bottomNone, strT0: 'Never', strT1: 'Never');
-  }
-
-  test_bottom_06() {
-    isSubtype(bottomNone, neverNone, strT0: 'Never', strT1: 'Never');
-  }
-
   test_functionType_01() {
     var E0 = typeParameter('E0');
     var E1 = typeParameter('E1', bound: numStar);
@@ -636,7 +619,7 @@
         ],
         returnType: intStar,
       ),
-      strT0: 'int* Function<E0,F0>(int*)*',
+      strT0: 'int* Function<E0, F0>(int*)*',
       strT1: 'int* Function<E1>(int*)*',
     );
   }
@@ -1714,28 +1697,6 @@
     );
   }
 
-  test_functionType_65() {
-    isSubtype(
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'c', type: intStar),
-          namedParameter(name: 'b', type: intStar),
-          namedParameter(name: 'a', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'a', type: intStar),
-          namedParameter(name: 'c', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      strT0: 'void Function({c: int*, b: int*, a: int*})*',
-      strT1: 'void Function({a: int*, c: int*})*',
-    );
-  }
-
   test_functionType_66() {
     isSubtype(
       functionTypeStar(
@@ -1758,28 +1719,6 @@
     );
   }
 
-  test_functionType_67() {
-    isSubtype(
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'c', type: intStar),
-          namedParameter(name: 'b', type: intStar),
-          namedParameter(name: 'a', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'b', type: intStar),
-          namedParameter(name: 'c', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      strT0: 'void Function({c: int*, b: int*, a: int*})*',
-      strT1: 'void Function({b: int*, c: int*})*',
-    );
-  }
-
   test_functionType_68() {
     isSubtype(
       functionTypeStar(
@@ -1801,27 +1740,6 @@
     );
   }
 
-  test_functionType_69() {
-    isSubtype(
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'c', type: intStar),
-          namedParameter(name: 'b', type: intStar),
-          namedParameter(name: 'a', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      functionTypeStar(
-        parameters: [
-          namedParameter(name: 'c', type: intStar),
-        ],
-        returnType: voidNone,
-      ),
-      strT0: 'void Function({c: int*, b: int*, a: int*})*',
-      strT1: 'void Function({c: int*})*',
-    );
-  }
-
   test_functionType_70() {
     isSubtype(
       functionTypeNone(
@@ -1962,7 +1880,7 @@
           returnType: typeParameterTypeNone(E1),
         ),
       ),
-      strT0: 'E0 Function(F0)* Function<E0,F0>(E0)*',
+      strT0: 'E0 Function(F0)* Function<E0, F0>(E0)*',
       strT1: 'E1 Function<F1>(F1)* Function<E1>(E1)*',
     );
 
@@ -1991,8 +1909,8 @@
           returnType: typeParameterTypeNone(E1),
         ),
       ),
-      strT0: 'E0 Function(F0)* Function<E0,F0>(E0)*',
-      strT1: 'E1 Function(F1)* Function<F1,E1>(E1)*',
+      strT0: 'E0 Function(F0)* Function<E0, F0>(E0)*',
+      strT1: 'E1 Function(F1)* Function<F1, E1>(E1)*',
     );
   }
 
@@ -2291,6 +2209,36 @@
     );
   }
 
+  test_functionType_requiredNamedParameter() {
+    var F0 = functionTypeNone(
+      returnType: voidNone,
+      parameters: [
+        namedRequiredParameter(name: 'a', type: intNone),
+      ],
+    );
+
+    var F1 = functionTypeNone(
+      returnType: voidNone,
+      parameters: [
+        namedParameter(name: 'a', type: intNone),
+      ],
+    );
+
+    isSubtype(
+      F1,
+      F0,
+      strT0: 'void Function({a: int})',
+      strT1: 'void Function({required a: int})',
+    );
+
+    isNotSubtype(
+      F0,
+      F1,
+      strT0: 'void Function({required a: int})',
+      strT1: 'void Function({a: int})',
+    );
+  }
+
   test_futureOr_01() {
     isSubtype(
       intStar,
@@ -2480,12 +2428,12 @@
   test_futureOr_21() {
     isSubtype(
       functionTypeStar(
-        parameters: [],
+        parameters: const [],
         returnType: stringStar,
       ),
       futureOrStar(
         functionTypeStar(
-          parameters: [],
+          parameters: const [],
           returnType: voidNone,
         ),
       ),
@@ -2497,12 +2445,12 @@
   test_futureOr_22() {
     isNotSubtype(
       functionTypeStar(
-        parameters: [],
+        parameters: const [],
         returnType: voidNone,
       ),
       futureOrStar(
         functionTypeStar(
-          parameters: [],
+          parameters: const [],
           returnType: stringStar,
         ),
       ),
@@ -2876,8 +2824,8 @@
       listNone(
         typeParameterTypeNone(T),
       ),
-      strT0: 'List<T>, T & int',
-      strT1: 'List<T>',
+      strT0: 'List<T>, T extends Object?, T & int',
+      strT1: 'List<T>, T extends Object?',
     );
   }
 
@@ -2893,11 +2841,90 @@
       listNone(
         typeParameterTypeNone(T),
       ),
-      strT0: 'List<T>, T & int?',
-      strT1: 'List<T>',
+      strT0: 'List<T>, T extends Object?, T & int?',
+      strT1: 'List<T>, T extends Object?',
     );
   }
 
+  test_interfaceType_covariant_01() {
+    var T = typeParameter('T', variance: Variance.covariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var A_num = A.instantiate(
+      typeArguments: [numNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    var A_int = A.instantiate(
+      typeArguments: [intNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
+    isNotSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
+  }
+
+  test_interfaceType_covariant_02() {
+    var T = typeParameter('T', variance: Variance.covariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var A_num = A.instantiate(
+      typeArguments: [numNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
+  }
+
+  test_interfaceType_contravariant_01() {
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var A_num = A.instantiate(
+      typeArguments: [numNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    var A_int = A.instantiate(
+      typeArguments: [intNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
+    isNotSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
+  }
+
+  test_interfaceType_contravariant_02() {
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var A_num = A.instantiate(
+      typeArguments: [numNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
+  }
+
+  test_interfaceType_invariant() {
+    var T = typeParameter('T', variance: Variance.invariant);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var A_num = A.instantiate(
+      typeArguments: [numNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    var A_int = A.instantiate(
+      typeArguments: [intNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
+    isNotSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
+    isNotSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
+  }
+
   test_multi_function_nonGeneric_oneArgument() {
     isSubtype2('num* Function(num*)*', 'num* Function(int*)*');
     isSubtype2('int* Function(num*)*', 'num* Function(num*)*');
@@ -2913,6 +2940,34 @@
     isNotSubtype2('num* Function(num*)?', 'Object');
     isNotSubtype2('Null?', 'num* Function(int*)');
     isNotSubtype2('num* Function(int*)', 'Never');
+
+    isNotSubtype2('num', 'num Function(num)');
+    isNotSubtype2('Object', 'num Function(num)');
+    isNotSubtype2('Object*', 'num Function(num)');
+    isNotSubtype2('Object?', 'num Function(num)');
+    isNotSubtype2('dynamic', 'num Function(num)');
+
+    isSubtype2('num Function(num)', 'num Function(num)*');
+    isSubtype2('num Function(num)*', 'num Function(num)');
+    isSubtype2('num Function(num)?', 'num Function(num)*');
+    isSubtype2('num Function(num)*', 'num Function(num)?');
+    isSubtype2('num Function(num)', 'num Function(num)?');
+    isNotSubtype2('num Function(num)?', 'num Function(num)');
+
+    isSubtype2('num Function(num)', 'num? Function(num)');
+    isSubtype2('num Function(num?)', 'num Function(num)');
+    isSubtype2('num Function(num?)', 'num? Function(num)');
+    isNotSubtype2('num Function(num)', 'num? Function(num?)');
+
+    isSubtype2('num Function({num x})', 'num? Function({num x})');
+    isSubtype2('num Function({num? x})', 'num Function({num x})');
+    isSubtype2('num Function({num? x})', 'num? Function({num x})');
+    isNotSubtype2('num Function({num x})', 'num? Function({num? x})');
+
+    isSubtype2('num Function([num])', 'num? Function([num])');
+    isSubtype2('num Function([num?])', 'num Function([num])');
+    isSubtype2('num Function([num?])', 'num? Function([num])');
+    isNotSubtype2('num Function([num])', 'num? Function([num?])');
   }
 
   test_multi_function_nonGeneric_zeroArguments() {
@@ -2942,6 +2997,63 @@
   }
 
   test_multi_futureOr() {
+    isSubtype2('int*', 'FutureOr<int*>*');
+    isSubtype2('int*', 'FutureOr<num*>*');
+    isSubtype2('Future<int*>*', 'FutureOr<int*>*');
+    isSubtype2('Future<int*>*', 'FutureOr<num*>*');
+    isSubtype2('Future<int*>*', 'FutureOr<Object*>*');
+    isSubtype2('FutureOr<int*>*', 'FutureOr<int*>*');
+    isSubtype2('FutureOr<int*>*', 'FutureOr<num*>*');
+    isSubtype2('FutureOr<int*>*', 'Object*');
+    isSubtype2('Null?', 'FutureOr<num?>');
+    isSubtype2('Null?', 'FutureOr<num>?');
+    isSubtype2('num?', 'FutureOr<num?>');
+    isSubtype2('num?', 'FutureOr<num>?');
+    isSubtype2('Future<num>', 'FutureOr<num?>');
+    isSubtype2('Future<num>', 'FutureOr<num>?');
+    isSubtype2('Future<num>', 'FutureOr<num?>?');
+    isSubtype2('Future<num?>', 'FutureOr<num?>');
+    isNotSubtype2('Future<num?>', 'FutureOr<num>?');
+    isSubtype2('Future<num?>', 'FutureOr<num?>?');
+
+    isSubtype2('num?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype2('Future<num>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype2('Future<Future<num>>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype2(
+      'Future<Future<Future<num>>>?',
+      'FutureOr<FutureOr<FutureOr<num>>?>',
+    );
+    isSubtype2('Future<num>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype2('Future<Future<num>>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype2(
+      'Future<Future<Future<num>>>?',
+      'FutureOr<FutureOr<FutureOr<num?>>>',
+    );
+    isSubtype2('Future<num?>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype2('Future<Future<num?>?>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype2(
+      'Future<Future<Future<num?>?>?>?',
+      'FutureOr<FutureOr<FutureOr<num?>>>',
+    );
+
+    isSubtype2('FutureOr<num>?', 'FutureOr<num?>');
+    isNotSubtype2('FutureOr<num?>', 'FutureOr<num>?');
+
+    isSubtype2('dynamic', 'FutureOr<Object?>');
+    isSubtype2('dynamic', 'FutureOr<Object>?');
+    isSubtype2('void', 'FutureOr<Object?>');
+    isSubtype2('void', 'FutureOr<Object>?');
+    isSubtype2('Object*', 'FutureOr<Object?>');
+    isSubtype2('Object*', 'FutureOr<Object>?');
+    isSubtype2('Object?', 'FutureOr<Object?>');
+    isSubtype2('Object?', 'FutureOr<Object>?');
+    isSubtype2('Object', 'FutureOr<Object?>');
+    isSubtype2('Object', 'FutureOr<Object>?');
+    isNotSubtype2('dynamic', 'FutureOr<Object>');
+    isNotSubtype2('void', 'FutureOr<Object>');
+    isNotSubtype2('Object?', 'FutureOr<Object>');
+    isSubtype2('Object', 'FutureOr<Object>');
+
     isSubtype2('FutureOr<int>', 'Object');
     isSubtype2('FutureOr<int>', 'Object*');
     isSubtype2('FutureOr<int>', 'Object?');
@@ -2972,6 +3084,467 @@
     isNotSubtype2('FutureOr<num>?', 'Object');
   }
 
+  test_multi_futureOr_functionType() {
+    isSubtype(
+      functionTypeStar(
+        returnType: stringStar,
+      ),
+      futureOrStar(
+        functionTypeStar(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String* Function()*',
+      strT1: 'FutureOr<void Function()*>*',
+    );
+
+    isSubtype(
+      functionTypeNone(
+        returnType: stringNone,
+      ),
+      futureOrNone(
+        functionTypeNone(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()',
+      strT1: 'FutureOr<void Function()>',
+    );
+
+    isSubtype(
+      functionTypeNone(
+        returnType: stringNone,
+      ),
+      futureOrNone(
+        functionTypeQuestion(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()',
+      strT1: 'FutureOr<void Function()?>',
+    );
+
+    isSubtype(
+      functionTypeNone(
+        returnType: stringNone,
+      ),
+      futureOrQuestion(
+        functionTypeNone(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()',
+      strT1: 'FutureOr<void Function()>?',
+    );
+
+    isSubtype(
+      functionTypeQuestion(
+        returnType: stringNone,
+      ),
+      futureOrNone(
+        functionTypeQuestion(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()?',
+      strT1: 'FutureOr<void Function()?>',
+    );
+
+    isSubtype(
+      functionTypeQuestion(
+        returnType: stringNone,
+      ),
+      futureOrQuestion(
+        functionTypeNone(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()?',
+      strT1: 'FutureOr<void Function()>?',
+    );
+
+    isNotSubtype(
+      functionTypeQuestion(
+        returnType: stringNone,
+      ),
+      futureOrNone(
+        functionTypeNone(
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String Function()?',
+      strT1: 'FutureOr<void Function()>',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      futureOrStar(
+        functionTypeStar(
+          returnType: stringNone,
+        ),
+      ),
+      strT0: 'void Function()*',
+      strT1: 'FutureOr<String Function()*>*',
+    );
+  }
+
+  test_multi_futureOr_typeParameter() {
+    TypeParameterElement E;
+
+    E = typeParameter('E', bound: objectStar);
+    isSubtype(
+      typeParameterTypeStar(E),
+      futureOrStar(
+        typeParameterTypeStar(E),
+      ),
+      strT0: 'E*, E extends Object*',
+      strT1: 'FutureOr<E*>*, E extends Object*',
+    );
+
+    E = typeParameter('E', bound: objectNone);
+    isSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrQuestion(
+        typeParameterTypeNone(E),
+      ),
+      strT0: 'E?, E extends Object',
+      strT1: 'FutureOr<E>?, E extends Object',
+    );
+    isSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrNone(
+        typeParameterTypeQuestion(E),
+      ),
+      strT0: 'E?, E extends Object',
+      strT1: 'FutureOr<E?>, E extends Object',
+    );
+    isNotSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrNone(
+        typeParameterTypeNone(E),
+      ),
+      strT0: 'E?, E extends Object',
+      strT1: 'FutureOr<E>, E extends Object',
+    );
+
+    E = typeParameter('E', bound: objectQuestion);
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrQuestion(
+        typeParameterTypeNone(E),
+      ),
+      strT0: 'E, E extends Object?',
+      strT1: 'FutureOr<E>?, E extends Object?',
+    );
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrNone(
+        typeParameterTypeQuestion(E),
+      ),
+      strT0: 'E, E extends Object?',
+      strT1: 'FutureOr<E?>, E extends Object?',
+    );
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrNone(
+        typeParameterTypeNone(E),
+      ),
+      strT0: 'E, E extends Object?',
+      strT1: 'FutureOr<E>, E extends Object?',
+    );
+
+    E = typeParameter('E', bound: objectStar);
+    isNotSubtype(
+      typeParameterTypeStar(E),
+      futureOrStar(stringStar),
+      strT0: 'E*, E extends Object*',
+      strT1: 'FutureOr<String*>*',
+    );
+
+    E = typeParameter('E', bound: stringNone);
+    isSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrQuestion(stringNone),
+      strT0: 'E?, E extends String',
+      strT1: 'FutureOr<String>?',
+    );
+    isSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrNone(stringQuestion),
+      strT0: 'E?, E extends String',
+      strT1: 'FutureOr<String?>',
+    );
+    isNotSubtype(
+      typeParameterTypeQuestion(E),
+      futureOrNone(stringNone),
+      strT0: 'E?, E extends String',
+      strT1: 'FutureOr<String>',
+    );
+
+    E = typeParameter('E', bound: stringQuestion);
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrQuestion(stringNone),
+      strT0: 'E, E extends String?',
+      strT1: 'FutureOr<String>?',
+    );
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrNone(stringQuestion),
+      strT0: 'E, E extends String?',
+      strT1: 'FutureOr<String?>',
+    );
+    isNotSubtype(
+      typeParameterTypeNone(E),
+      futureOrNone(stringNone),
+      strT0: 'E, E extends String?',
+      strT1: 'FutureOr<String>',
+    );
+  }
+
+  test_multi_futureOr_typeParameter_promotion() {
+    TypeParameterElement S;
+    TypeParameterElement T;
+
+    T = typeParameter('T', bound: objectStar);
+    isSubtype(
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      futureOrStar(numStar),
+      strT0: 'T*, T extends Object*, T & int*',
+      strT1: 'FutureOr<num*>*',
+    );
+
+    T = typeParameter('T', bound: objectNone);
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object, T & int',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object, T & int',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object, T & int',
+      strT1: 'FutureOr<num>?',
+    );
+
+    T = typeParameter('T', bound: objectQuestion);
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object?, T & int',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object?, T & int',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object?, T & int',
+      strT1: 'FutureOr<num>?',
+    );
+
+    T = typeParameter('T', bound: objectQuestion);
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intQuestion),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object?, T & int?',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intQuestion),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object?, T & int?',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intQuestion),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object?, T & int?',
+      strT1: 'FutureOr<num>?',
+    );
+
+    T = typeParameter('T', bound: objectQuestion);
+    S = typeParameter('S', bound: typeParameterTypeNone(T));
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, typeParameterTypeNone(S)),
+      ),
+      futureOrNone(objectNone),
+      strT0: 'T, T extends Object?, T & S',
+      strT1: 'FutureOr<Object>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, typeParameterTypeNone(S)),
+      ),
+      futureOrNone(objectQuestion),
+      strT0: 'T, T extends Object?, T & S',
+      strT1: 'FutureOr<Object?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, typeParameterTypeNone(S)),
+      ),
+      futureOrQuestion(objectNone),
+      strT0: 'T, T extends Object?, T & S',
+      strT1: 'FutureOr<Object>?',
+    );
+
+    T = typeParameter('T', bound: objectStar);
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureStar(numStar)),
+      ),
+      futureOrStar(numStar),
+      strT0: 'T, T extends Object*, T & Future<num*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureStar(intStar)),
+      ),
+      futureOrStar(numStar),
+      strT0: 'T, T extends Object*, T & Future<int*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+
+    T = typeParameter('T', bound: objectNone);
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object, T & Future<int>',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object, T & Future<int>',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object, T & Future<int>',
+      strT1: 'FutureOr<num>?',
+    );
+
+    T = typeParameter('T', bound: objectQuestion);
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object?, T & Future<int>',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object?, T & Future<int>',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intNone)),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object?, T & Future<int>',
+      strT1: 'FutureOr<num>?',
+    );
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureQuestion(intNone)),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureQuestion(intNone)),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT1: 'FutureOr<num?>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureQuestion(intNone)),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT1: 'FutureOr<num>?',
+    );
+
+    T = typeParameter('T', bound: objectNone);
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intQuestion)),
+      ),
+      futureOrNone(numNone),
+      strT0: 'T, T extends Object, T & Future<int?>',
+      strT1: 'FutureOr<num>',
+    );
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intQuestion)),
+      ),
+      futureOrNone(numQuestion),
+      strT0: 'T, T extends Object, T & Future<int?>',
+      strT1: 'FutureOr<num?>',
+    );
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, futureNone(intQuestion)),
+      ),
+      futureOrQuestion(numNone),
+      strT0: 'T, T extends Object, T & Future<int?>',
+      strT1: 'FutureOr<num>?',
+    );
+  }
+
   test_multi_list_subTypes_superTypes() {
     isSubtype2('List<int*>*', 'List<int*>*');
     isSubtype2('List<int*>*', 'Iterable<int*>*');
@@ -3033,9 +3606,6 @@
     isSubtype2('Never', 'num');
     isSubtype2('Never', 'num*');
     isSubtype2('Never', 'num?');
-    isSubtype2('bottom', 'num');
-    isSubtype2('bottom', 'num*');
-    isSubtype2('bottom', 'num?');
 
     isNotSubtype2('int*', 'double*');
     isNotSubtype2('int*', 'Comparable<int*>*');
@@ -3047,7 +3617,6 @@
   }
 
   test_multi_object_topAndBottom() {
-    isSubtype2('bottom', 'Object');
     isSubtype2('Never', 'Object');
     isSubtype2('Object', 'dynamic');
     isSubtype2('Object', 'void');
@@ -3055,9 +3624,8 @@
     isSubtype2('Object', 'Object*');
     isSubtype2('Object*', 'Object');
 
-    isNotSubtype2('Object', 'bottom');
-    isNotSubtype2('Object', 'Null?');
     isNotSubtype2('Object', 'Never');
+    isNotSubtype2('Object', 'Null?');
     isNotSubtype2('dynamic', 'Object');
     isNotSubtype2('void', 'Object');
     isNotSubtype2('Object?', 'Object');
@@ -3089,14 +3657,9 @@
 
   test_multi_topAndBottom() {
     isSubtype2('Null?', 'Null?');
-    isNotSubtype2('Null?', 'bottom');
-    isNotSubtype2('Null?', 'Never');
-    isSubtype2('bottom', 'Null?');
-    isSubtype2('bottom', 'bottom');
-    isSubtype2('bottom', 'Never');
     isSubtype2('Never', 'Null?');
-//    isNotSubtype2('Never', 'bottom');
     isSubtype2('Never', 'Never');
+    isNotSubtype2('Null?', 'Never');
 
     isSubtype2('Null?', 'Never?');
     isSubtype2('Never?', 'Null?');
@@ -3124,29 +3687,115 @@
     isSubtype2('Never', 'Object*');
     isSubtype2('Never', 'dynamic');
     isSubtype2('Never', 'void');
-    isSubtype2('bottom', 'Object?');
-    isSubtype2('bottom', 'Object*');
-    isSubtype2('bottom', 'dynamic');
-    isSubtype2('bottom', 'void');
     isSubtype2('Null?', 'Object?');
     isSubtype2('Null?', 'Object*');
     isSubtype2('Null?', 'dynamic');
     isSubtype2('Null?', 'void');
 
     isNotSubtype2('Object?', 'Never');
-    isNotSubtype2('Object?', 'bottom');
     isNotSubtype2('Object?', 'Null?');
     isNotSubtype2('Object*', 'Never');
-    isNotSubtype2('Object*', 'bottom');
     isNotSubtype2('Object*', 'Null?');
     isNotSubtype2('dynamic', 'Never');
-    isNotSubtype2('dynamic', 'bottom');
     isNotSubtype2('dynamic', 'Null?');
     isNotSubtype2('void', 'Never');
-    isNotSubtype2('void', 'bottom');
     isNotSubtype2('void', 'Null?');
   }
 
+  test_multi_typeParameter_promotion() {
+    TypeParameterElement T;
+
+    T = typeParameter('T', bound: intStar);
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      strT0: 'T*, T extends int*',
+      strT1: 'T*, T extends int*, T & int*',
+    );
+
+    T = typeParameter('T', bound: intNone);
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      strT0: 'T, T extends int',
+      strT1: 'T, T extends int, T & int',
+    );
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      strT0: 'T?, T extends int',
+      strT1: 'T, T extends int, T & int',
+    );
+
+    T = typeParameter('T', bound: intQuestion);
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intNone),
+      ),
+      strT0: 'T, T extends int?',
+      strT1: 'T, T extends int?, T & int',
+    );
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intQuestion),
+      ),
+      strT0: 'T, T extends int?',
+      strT1: 'T, T extends int?, T & int?',
+    );
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intQuestion),
+      ),
+      strT0: 'T?, T extends int?',
+      strT1: 'T, T extends int?, T & int?',
+    );
+
+    T = typeParameter('T', bound: numStar);
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(T),
+      strT0: 'T*, T extends num*',
+      strT1: 'T*, T extends num*',
+    );
+
+    T = typeParameter('T', bound: numNone);
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(T),
+      strT0: 'T, T extends num',
+      strT1: 'T, T extends num',
+    );
+    isSubtype(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeQuestion(T),
+      strT0: 'T?, T extends num',
+      strT1: 'T?, T extends num',
+    );
+
+    T = typeParameter('T', bound: numQuestion);
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(T),
+      strT0: 'T, T extends num?',
+      strT1: 'T, T extends num?',
+    );
+    isSubtype(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeQuestion(T),
+      strT0: 'T?, T extends num?',
+      strT1: 'T?, T extends num?',
+    );
+  }
+
   test_never_01() {
     isSubtype(
       neverNone,
@@ -3199,7 +3848,7 @@
         promoteTypeParameter(T, numStar),
       ),
       strT0: 'Never',
-      strT1: 'T*, T & num*',
+      strT1: 'T*, T extends Object*, T & num*',
     );
   }
 
@@ -3211,7 +3860,7 @@
         promoteTypeParameter(T, numStar),
       ),
       neverNone,
-      strT0: 'T*, T & num*',
+      strT0: 'T*, T extends Object*, T & num*',
       strT1: 'Never',
     );
   }
@@ -3222,7 +3871,7 @@
     isSubtype(
       typeParameterTypeNone(T),
       neverNone,
-      strT0: 'T',
+      strT0: 'T, T extends Never',
       strT1: 'Never',
     );
   }
@@ -3235,7 +3884,7 @@
         promoteTypeParameter(T, neverNone),
       ),
       neverNone,
-      strT0: 'T, T & Never',
+      strT0: 'T, T extends Object, T & Never',
       strT1: 'Never',
     );
   }
@@ -3247,7 +3896,7 @@
       neverNone,
       typeParameterTypeQuestion(T),
       strT0: 'Never',
-      strT1: 'T?',
+      strT1: 'T?, T extends Object',
     );
   }
 
@@ -3258,7 +3907,7 @@
       neverNone,
       typeParameterTypeQuestion(T),
       strT0: 'Never',
-      strT1: 'T?',
+      strT1: 'T?, T extends Object?',
     );
   }
 
@@ -3269,7 +3918,7 @@
       neverNone,
       typeParameterTypeNone(T),
       strT0: 'Never',
-      strT1: 'T',
+      strT1: 'T, T extends Object',
     );
   }
 
@@ -3280,7 +3929,7 @@
       neverNone,
       typeParameterTypeNone(T),
       strT0: 'Never',
-      strT1: 'T',
+      strT1: 'T, T extends Object?',
     );
   }
 
@@ -3290,7 +3939,7 @@
     isSubtype(
       typeParameterTypeNone(T),
       neverNone,
-      strT0: 'T',
+      strT0: 'T, T extends Never',
       strT1: 'Never',
     );
   }
@@ -3301,7 +3950,7 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       neverNone,
-      strT0: 'T',
+      strT0: 'T, T extends Never?',
       strT1: 'Never',
     );
   }
@@ -3312,7 +3961,7 @@
     isNotSubtype(
       typeParameterTypeQuestion(T),
       neverNone,
-      strT0: 'T?',
+      strT0: 'T?, T extends Never',
       strT1: 'Never',
     );
   }
@@ -3323,7 +3972,7 @@
     isNotSubtype(
       typeParameterTypeQuestion(T),
       neverNone,
-      strT0: 'T?',
+      strT0: 'T?, T extends Never?',
       strT1: 'Never',
     );
   }
@@ -3334,7 +3983,7 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       neverNone,
-      strT0: 'T',
+      strT0: 'T, T extends Object',
       strT1: 'Never',
     );
   }
@@ -3345,13 +3994,13 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       neverNone,
-      strT0: 'T',
+      strT0: 'T, T extends Object?',
       strT1: 'Never',
     );
   }
 
   test_never_29() {
-    isSubtype(bottomNone, nullQuestion, strT0: 'Never', strT1: 'Null?');
+    isSubtype(neverNone, nullQuestion, strT0: 'Never', strT1: 'Null?');
   }
 
   test_null_01() {
@@ -3424,7 +4073,7 @@
       nullQuestion,
       typeParameterTypeNone(T),
       strT0: 'Null?',
-      strT1: 'T',
+      strT1: 'T, T extends Object*',
     );
   }
 
@@ -3497,7 +4146,7 @@
         promoteTypeParameter(T, numStar),
       ),
       strT0: 'Null?',
-      strT1: 'T*, T & num*',
+      strT1: 'T*, T extends Object*, T & num*',
     );
   }
 
@@ -3510,7 +4159,7 @@
         promoteTypeParameter(T, numNone),
       ),
       strT0: 'Null?',
-      strT1: 'T, T & num',
+      strT1: 'T, T extends Object?, T & num',
     );
   }
 
@@ -3523,7 +4172,7 @@
         promoteTypeParameter(T, numQuestion),
       ),
       strT0: 'Null?',
-      strT1: 'T, T & num?',
+      strT1: 'T, T extends Object?, T & num?',
     );
   }
 
@@ -3536,7 +4185,7 @@
         promoteTypeParameter(T, numNone),
       ),
       strT0: 'Null?',
-      strT1: 'T, T & num',
+      strT1: 'T, T extends Object, T & num',
     );
   }
 
@@ -3553,7 +4202,7 @@
         ),
       ),
       strT0: 'Null?',
-      strT1: 'T, T & S',
+      strT1: 'T, T extends Object?, T & S',
     );
   }
 
@@ -3564,7 +4213,7 @@
       nullQuestion,
       typeParameterTypeQuestion(T),
       strT0: 'Null?',
-      strT1: 'T?',
+      strT1: 'T?, T extends Object',
     );
   }
 
@@ -3575,7 +4224,7 @@
       nullQuestion,
       typeParameterTypeQuestion(T),
       strT0: 'Null?',
-      strT1: 'T?',
+      strT1: 'T?, T extends Object?',
     );
   }
 
@@ -3586,7 +4235,7 @@
       nullQuestion,
       typeParameterTypeNone(T),
       strT0: 'Null?',
-      strT1: 'T',
+      strT1: 'T, T extends Object',
     );
   }
 
@@ -3597,7 +4246,7 @@
       nullQuestion,
       typeParameterTypeNone(T),
       strT0: 'Null?',
-      strT1: 'T',
+      strT1: 'T, T extends Object?',
     );
   }
 
@@ -3607,7 +4256,7 @@
     isSubtype(
       typeParameterTypeNone(T),
       nullQuestion,
-      strT0: 'T',
+      strT0: 'T, T extends Null?',
       strT1: 'Null?',
     );
   }
@@ -3618,7 +4267,7 @@
     isSubtype(
       typeParameterTypeQuestion(T),
       nullQuestion,
-      strT0: 'T?',
+      strT0: 'T?, T extends Null?',
       strT1: 'Null?',
     );
   }
@@ -3629,7 +4278,7 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       nullQuestion,
-      strT0: 'T',
+      strT0: 'T, T extends Object',
       strT1: 'Null?',
     );
   }
@@ -3640,7 +4289,7 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       nullQuestion,
-      strT0: 'T',
+      strT0: 'T, T extends Object?',
       strT1: 'Null?',
     );
   }
@@ -3779,8 +4428,8 @@
     isSubtype(
       type,
       type,
-      strT0: 'T, T & int?',
-      strT1: 'T, T & int?',
+      strT0: 'T, T extends Object*, T & int?',
+      strT1: 'T, T extends Object*, T & int?',
     );
   }
 
@@ -3792,8 +4441,8 @@
     isSubtype(
       type,
       type,
-      strT0: 'T?, T & int?',
-      strT1: 'T?, T & int?',
+      strT0: 'T?, T extends Object, T & int?',
+      strT1: 'T?, T extends Object, T & int?',
     );
   }
 
@@ -3952,8 +4601,8 @@
         ],
         returnType: voidNone,
       ),
-      strT0: 'void Function<S extends Object*,T extends void>(S, T)*',
-      strT1: 'void Function<U extends dynamic,V extends Object*>(U, V)*',
+      strT0: 'void Function<S extends Object*, T extends void>(S, T)*',
+      strT1: 'void Function<U extends dynamic, V extends Object*>(U, V)*',
     );
   }
 
@@ -4269,7 +4918,7 @@
       functionTypeStar(
         returnType: voidNone,
       ),
-      strT0: 'T*',
+      strT0: 'T*, T extends void Function()*',
       strT1: 'void Function()*',
     );
   }
@@ -4381,7 +5030,7 @@
         promoteTypeParameter(T, voidNone),
       ),
       strT0: 'void',
-      strT1: 'T, T & void',
+      strT1: 'T, T extends void, T & void',
     );
   }
 
@@ -4466,8 +5115,8 @@
         promoteTypeParameter(T, intStar),
       ),
       typeParameterTypeStar(T),
-      strT0: 'T*, T & int*',
-      strT1: 'T*',
+      strT0: 'T*, T extends int*, T & int*',
+      strT1: 'T*, T extends int*',
     );
   }
 
@@ -4479,8 +5128,8 @@
         promoteTypeParameter(T, intStar),
       ),
       typeParameterTypeStar(T),
-      strT0: 'T*, T & int*',
-      strT1: 'T*',
+      strT0: 'T*, T extends num*, T & int*',
+      strT1: 'T*, T extends num*',
     );
   }
 
@@ -4492,8 +5141,8 @@
         promoteTypeParameter(T, numStar),
       ),
       typeParameterTypeStar(T),
-      strT0: 'T*, T & num*',
-      strT1: 'T*',
+      strT0: 'T*, T extends num*, T & num*',
+      strT1: 'T*, T extends num*',
     );
   }
 
@@ -4505,8 +5154,8 @@
       typeParameterTypeStar(
         promoteTypeParameter(T, intStar),
       ),
-      strT0: 'T*',
-      strT1: 'T*, T & int*',
+      strT0: 'T*, T extends int*',
+      strT1: 'T*, T extends int*, T & int*',
     );
   }
 
@@ -4518,8 +5167,8 @@
       typeParameterTypeStar(
         promoteTypeParameter(T, numStar),
       ),
-      strT0: 'T*',
-      strT1: 'T*, T & num*',
+      strT0: 'T*, T extends int*',
+      strT1: 'T*, T extends int*, T & num*',
     );
   }
 
@@ -4531,8 +5180,8 @@
       typeParameterTypeStar(
         promoteTypeParameter(T, intStar),
       ),
-      strT0: 'T*',
-      strT1: 'T*, T & int*',
+      strT0: 'T*, T extends num*',
+      strT1: 'T*, T extends num*, T & int*',
     );
   }
 
@@ -4542,8 +5191,8 @@
     isSubtype(
       typeParameterTypeStar(T),
       typeParameterTypeStar(T),
-      strT0: 'T*',
-      strT1: 'T*',
+      strT0: 'T*, T extends num*',
+      strT1: 'T*, T extends num*',
     );
   }
 
@@ -4576,8 +5225,8 @@
     isSubtype(
       typeParameterTypeStar(T),
       typeParameterTypeStar(T),
-      strT0: 'T*',
-      strT1: 'T*',
+      strT0: 'T*, T extends Object*',
+      strT1: 'T*, T extends Object*',
     );
   }
 
@@ -4588,8 +5237,8 @@
     isNotSubtype(
       typeParameterTypeNone(S),
       typeParameterTypeNone(T),
-      strT0: 'S',
-      strT1: 'T',
+      strT0: 'S, S extends Object*',
+      strT1: 'T, T extends Object*',
     );
   }
 
@@ -4599,8 +5248,8 @@
     isSubtype(
       typeParameterTypeStar(T),
       typeParameterTypeStar(T),
-      strT0: 'T*',
-      strT1: 'T*',
+      strT0: 'T*, T extends dynamic',
+      strT1: 'T*, T extends dynamic',
     );
   }
 
@@ -4611,8 +5260,8 @@
     isNotSubtype(
       typeParameterTypeNone(S),
       typeParameterTypeNone(T),
-      strT0: 'S',
-      strT1: 'T',
+      strT0: 'S, S extends dynamic',
+      strT1: 'T, T extends dynamic',
     );
   }
 
@@ -4624,13 +5273,13 @@
       typeParameterTypeNone(S),
       typeParameterTypeNone(T),
       strT0: 'S',
-      strT1: 'T',
+      strT1: 'T, T extends S',
     );
 
     isSubtype(
       typeParameterTypeNone(T),
       typeParameterTypeNone(S),
-      strT0: 'T',
+      strT0: 'T, T extends S',
       strT1: 'S',
     );
   }
@@ -4723,7 +5372,7 @@
     isSubtype(
       typeParameterTypeStar(S),
       intStar,
-      strT0: 'S*',
+      strT0: 'S*, S extends int*',
       strT1: 'int*',
     );
   }
@@ -4734,7 +5383,7 @@
     isSubtype(
       typeParameterTypeStar(S),
       numStar,
-      strT0: 'S*',
+      strT0: 'S*, S extends int*',
       strT1: 'num*',
     );
   }
@@ -4745,7 +5394,7 @@
     isSubtype(
       typeParameterTypeStar(S),
       numStar,
-      strT0: 'S*',
+      strT0: 'S*, S extends num*',
       strT1: 'num*',
     );
   }
@@ -4756,7 +5405,7 @@
     isNotSubtype(
       typeParameterTypeStar(S),
       intStar,
-      strT0: 'S*',
+      strT0: 'S*, S extends num*',
       strT1: 'int*',
     );
   }
@@ -4768,7 +5417,7 @@
     isNotSubtype(
       typeParameterTypeStar(S),
       typeParameterTypeNone(T),
-      strT0: 'S*',
+      strT0: 'S*, S extends num*',
       strT1: 'T',
     );
   }
@@ -4782,7 +5431,7 @@
       typeParameterTypeNone(
         promoteTypeParameter(T, numStar),
       ),
-      strT0: 'S*',
+      strT0: 'S*, S extends num*',
       strT1: 'T, T & num*',
     );
   }
@@ -4796,7 +5445,7 @@
         promoteTypeParameter(T, dynamicNone),
       ),
       strT0: 'dynamic',
-      strT1: 'T, T & dynamic',
+      strT1: 'T, T extends dynamic, T & dynamic',
     );
   }
 
@@ -4854,7 +5503,7 @@
     isSubtype(
       typeParameterTypeNone(T),
       numNone,
-      strT0: 'T',
+      strT0: 'T, T extends num',
       strT1: 'num',
     );
   }
@@ -4866,9 +5515,24 @@
       promoteTypeParameter(T, numQuestion),
     );
 
-    isNotSubtype(type, numNone, strT0: 'T, T & num?', strT1: 'num');
-    isSubtype(type, numQuestion, strT0: 'T, T & num?', strT1: 'num?');
-    isSubtype(type, numStar, strT0: 'T, T & num?', strT1: 'num*');
+    isNotSubtype(
+      type,
+      numNone,
+      strT0: 'T, T extends Object?, T & num?',
+      strT1: 'num',
+    );
+    isSubtype(
+      type,
+      numQuestion,
+      strT0: 'T, T extends Object?, T & num?',
+      strT1: 'num?',
+    );
+    isSubtype(
+      type,
+      numStar,
+      strT0: 'T, T extends Object?, T & num?',
+      strT1: 'num*',
+    );
   }
 
   test_typeParameter_38() {
@@ -4877,7 +5541,7 @@
     isSubtype(
       typeParameterTypeStar(T),
       objectNone,
-      strT0: 'T*',
+      strT0: 'T*, T extends num*',
       strT1: 'Object',
     );
   }
@@ -4888,7 +5552,7 @@
     isSubtype(
       typeParameterTypeNone(T),
       objectNone,
-      strT0: 'T',
+      strT0: 'T, T extends num',
       strT1: 'Object',
     );
   }
@@ -4899,7 +5563,7 @@
     isNotSubtype(
       typeParameterTypeQuestion(T),
       objectNone,
-      strT0: 'T?',
+      strT0: 'T?, T extends num',
       strT1: 'Object',
     );
   }
@@ -4910,7 +5574,7 @@
     isNotSubtype(
       typeParameterTypeNone(T),
       objectNone,
-      strT0: 'T',
+      strT0: 'T, T extends num?',
       strT1: 'Object',
     );
   }
@@ -4921,24 +5585,11 @@
     isNotSubtype(
       typeParameterTypeQuestion(T),
       objectNone,
-      strT0: 'T?',
+      strT0: 'T?, T extends num?',
       strT1: 'Object',
     );
   }
 
-  TypeParameterTypeImpl typeParameterTypeNone(TypeParameterElement element) {
-    return element.instantiate(nullabilitySuffix: NullabilitySuffix.none);
-  }
-
-  TypeParameterTypeImpl typeParameterTypeQuestion(
-      TypeParameterElement element) {
-    return element.instantiate(nullabilitySuffix: NullabilitySuffix.question);
-  }
-
-  TypeParameterTypeImpl typeParameterTypeStar(TypeParameterElement element) {
-    return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
-  }
-
   void _defineType(String str, DartType type) {
     for (var key in _types.keys) {
       if (key == 'Never' || _typeStr(type) == 'Never') {
@@ -4957,11 +5608,13 @@
   }
 
   void _defineTypes() {
-    _defineType('bottom', bottomNone);
     _defineType('dynamic', dynamicNone);
     _defineType('void', voidNone);
+
     _defineType('Never', neverNone);
+    _defineType('Never*', neverStar);
     _defineType('Never?', neverQuestion);
+
     _defineType('Null?', nullQuestion);
 
     _defineType('Object', objectNone);
@@ -5023,12 +5676,29 @@
     _defineType('Function*', functionStar);
     _defineType('Function?', functionQuestion);
 
-    _defineType('FutureOr<int>', futureOrNone(intNone));
-    _defineType('FutureOr<int>*', futureOrStar(intNone));
-    _defineType('FutureOr<int>?', futureOrQuestion(intNone));
+    _defineType('FutureOr<Object*>*', futureOrStar(objectStar));
+    _defineType('FutureOr<num*>*', futureOrStar(numStar));
+    _defineType('FutureOr<int*>*', futureOrStar(intStar));
+    _defineType('FutureOr<num?>?', futureOrQuestion(numQuestion));
 
-    _defineType('FutureOr<int*>', futureOrNone(intStar));
+    _defineType('FutureOr<Object>', futureOrNone(objectNone));
+    _defineType('FutureOr<Object>?', futureOrQuestion(objectNone));
+    _defineType('FutureOr<Object?>', futureOrNone(objectQuestion));
+    _defineType('FutureOr<Object?>?', futureOrQuestion(objectQuestion));
+
+    _defineType('Future<num>', futureNone(numNone));
+    _defineType('Future<num>?', futureQuestion(numNone));
+    _defineType('Future<num?>', futureNone(numQuestion));
+    _defineType('Future<num?>?', futureQuestion(numQuestion));
+
+    _defineType('FutureOr<int>', futureOrNone(intNone));
+    _defineType('FutureOr<int>?', futureOrQuestion(intNone));
     _defineType('FutureOr<int?>', futureOrNone(intQuestion));
+    _defineType('FutureOr<int?>?', futureOrQuestion(intQuestion));
+
+    _defineType('FutureOr<int>*', futureOrStar(intNone));
+    _defineType('FutureOr<int*>', futureOrNone(intStar));
+    _defineType('Future<int*>*', futureStar(intStar));
 
     _defineType('FutureOr<num>', futureOrNone(numNone));
     _defineType('FutureOr<num>*', futureOrStar(numNone));
@@ -5064,6 +5734,53 @@
     );
 
     _defineType(
+      'Future<Future<num>>?',
+      futureQuestion(
+        futureNone(numNone),
+      ),
+    );
+    _defineType(
+      'Future<Future<num?>?>?',
+      futureQuestion(
+        futureQuestion(numQuestion),
+      ),
+    );
+
+    _defineType(
+      'Future<Future<Future<num>>>?',
+      futureQuestion(
+        futureNone(
+          futureNone(numNone),
+        ),
+      ),
+    );
+    _defineType(
+      'Future<Future<Future<num?>?>?>?',
+      futureQuestion(
+        futureQuestion(
+          futureQuestion(numQuestion),
+        ),
+      ),
+    );
+
+    _defineType(
+      'FutureOr<FutureOr<FutureOr<num>>?>',
+      futureOrNone(
+        futureOrQuestion(
+          futureOrNone(numNone),
+        ),
+      ),
+    );
+    _defineType(
+      'FutureOr<FutureOr<FutureOr<num?>>>',
+      futureOrNone(
+        futureOrNone(
+          futureOrNone(numQuestion),
+        ),
+      ),
+    );
+
+    _defineType(
       'int* Function()',
       functionTypeNone(
         returnType: intStar,
@@ -5083,6 +5800,28 @@
     );
 
     _defineType(
+      'num Function(num)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: numNone)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num Function(num)?',
+      functionTypeQuestion(
+        parameters: [requiredParameter(type: numNone)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num Function(num)*',
+      functionTypeStar(
+        parameters: [requiredParameter(type: numNone)],
+        returnType: numNone,
+      ),
+    );
+
+    _defineType(
       'num* Function(num*)',
       functionTypeNone(
         parameters: [requiredParameter(type: numStar)],
@@ -5141,6 +5880,86 @@
         returnType: intStar,
       ),
     );
+
+    _defineType(
+      'num Function(num?)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: numQuestion)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num? Function(num)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: numNone)],
+        returnType: numQuestion,
+      ),
+    );
+    _defineType(
+      'num? Function(num?)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: numQuestion)],
+        returnType: numQuestion,
+      ),
+    );
+
+    _defineType(
+      'num Function({num x})',
+      functionTypeNone(
+        parameters: [namedParameter(name: 'x', type: numNone)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num Function({num? x})',
+      functionTypeNone(
+        parameters: [namedParameter(name: 'x', type: numQuestion)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num? Function({num x})',
+      functionTypeNone(
+        parameters: [namedParameter(name: 'x', type: numNone)],
+        returnType: numQuestion,
+      ),
+    );
+    _defineType(
+      'num? Function({num? x})',
+      functionTypeNone(
+        parameters: [namedParameter(name: 'x', type: numQuestion)],
+        returnType: numQuestion,
+      ),
+    );
+
+    _defineType(
+      'num Function([num])',
+      functionTypeNone(
+        parameters: [positionalParameter(type: numNone)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num Function([num?])',
+      functionTypeNone(
+        parameters: [positionalParameter(type: numQuestion)],
+        returnType: numNone,
+      ),
+    );
+    _defineType(
+      'num? Function([num])',
+      functionTypeNone(
+        parameters: [positionalParameter(type: numNone)],
+        returnType: numQuestion,
+      ),
+    );
+    _defineType(
+      'num? Function([num?])',
+      functionTypeNone(
+        parameters: [positionalParameter(type: numQuestion)],
+        returnType: numQuestion,
+      ),
+    );
   }
 
   DartType _getTypeByStr(String str) {
@@ -5157,7 +5976,7 @@
 @reflectiveTest
 class SubtypingCompoundTest extends _SubtypingCompoundTestBase {
   test_bottom_isBottom() {
-    var equivalents = <DartType>[bottomStar];
+    var equivalents = <DartType>[neverStar];
 
     var supertypes = <DartType>[
       dynamicNone,
@@ -5170,7 +5989,7 @@
     ];
 
     _checkGroups(
-      bottomStar,
+      neverStar,
       equivalents: equivalents,
       supertypes: supertypes,
     );
@@ -5201,7 +6020,7 @@
       numStar,
       stringStar,
       functionStar,
-      bottomStar,
+      neverStar,
     ];
 
     _checkGroups(
@@ -5250,7 +6069,7 @@
       numStar,
       stringStar,
       functionStar,
-      bottomStar,
+      neverStar,
     ];
 
     _checkGroups(
@@ -5331,12 +6150,6 @@
 
   ClassElement _comparableElement;
 
-  BottomTypeImpl get bottomNone => BottomTypeImpl.instance;
-
-  BottomTypeImpl get bottomQuestion => BottomTypeImpl.instanceNullable;
-
-  BottomTypeImpl get bottomStar => BottomTypeImpl.instanceLegacy;
-
   ClassElement get comparableElement {
     return _comparableElement ??=
         typeProvider.intType.element.library.getType('Comparable');
@@ -5416,10 +6229,6 @@
     );
   }
 
-  BottomTypeImpl get neverNone => BottomTypeImpl.instance;
-
-  BottomTypeImpl get neverQuestion => BottomTypeImpl.instanceNullable;
-
   InterfaceType get nullNone {
     var element = typeProvider.nullType.element;
     return element.instantiate(
@@ -5492,6 +6301,22 @@
     );
   }
 
+  InterfaceType get stringNone {
+    var element = typeProvider.stringType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get stringQuestion {
+    var element = typeProvider.stringType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
   InterfaceType get stringStar {
     var element = typeProvider.stringType.element;
     return element.instantiate(
@@ -5560,19 +6385,22 @@
 class _TypeParameterCollector extends DartTypeVisitor<void> {
   final Set<TypeParameterElement> typeParameters = Set();
 
+  /// We don't need to print bounds for these type parameters, because
+  /// they are already included into the function type itself, and cannot
+  /// be promoted.
+  final Set<TypeParameterElement> functionTypeParameters = Set();
+
   @override
   void defaultDartType(DartType type) {
     throw UnimplementedError('(${type.runtimeType}) $type');
   }
 
   @override
-  void visitBottomType(BottomTypeImpl type) {}
-
-  @override
   void visitDynamicType(DynamicTypeImpl type) {}
 
   @override
   void visitFunctionType(FunctionType type) {
+    functionTypeParameters.addAll(type.typeFormals);
     for (var typeParameter in type.typeFormals) {
       var bound = typeParameter.bound;
       if (bound != null) {
@@ -5593,8 +6421,13 @@
   }
 
   @override
+  void visitNeverType(NeverTypeImpl type) {}
+
+  @override
   void visitTypeParameterType(TypeParameterType type) {
-    typeParameters.add(type.element);
+    if (!functionTypeParameters.contains(type.element)) {
+      typeParameters.add(type.element);
+    }
   }
 
   @override
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index f24eff5..9cccdad 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -8,8 +8,10 @@
 import 'function_type_test.dart' as function_type;
 import 'inheritance_manager3_test.dart' as inheritance_manager3;
 import 'least_upper_bound_helper_test.dart' as least_upper_bound_helper;
+import 'nullability_eliminator_test.dart' as nullability_eliminator;
 import 'subtype_test.dart' as subtype;
 import 'type_algebra_test.dart' as type_algebra;
+import 'type_parameter_element_test.dart' as type_parameter_element;
 
 /// Utility for manually running all tests.
 main() {
@@ -18,7 +20,9 @@
     function_type.main();
     inheritance_manager3.main();
     least_upper_bound_helper.main();
+    nullability_eliminator.main();
     subtype.main();
     type_algebra.main();
+    type_parameter_element.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index a1c1663..977b926 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -101,7 +101,7 @@
 
     var result = Substitution.fromUpperAndLowerBounds(
       {T: typeProvider.intType},
-      {T: BottomTypeImpl.instance},
+      {T: NeverTypeImpl.instance},
     ).substituteType(type);
     expect(result.toString(), 'int Function(Never)');
   }
@@ -200,13 +200,13 @@
 
     assertElementTypeString(
       type,
-      'bool Function<T extends Triple<T, U, V>,U>()',
+      'bool Function<T extends Triple<T, U, V>, U>()',
     );
 
     var result = substitute(type, {V: intType}) as FunctionType;
     assertElementTypeString(
       result,
-      'bool Function<T extends Triple<T, U, int>,U>()',
+      'bool Function<T extends Triple<T, U, int>, U>()',
     );
     var T2 = result.typeFormals[0];
     var U2 = result.typeFormals[1];
@@ -387,8 +387,9 @@
   final bool useNnbd;
 
   _Base({this.useNnbd = false})
-      : typeProvider = TestTypeProvider(null, null,
-            useNnbd ? NullabilitySuffix.none : NullabilitySuffix.question);
+      : typeProvider = TestTypeProvider(
+            nullabilitySuffix:
+                useNnbd ? NullabilitySuffix.none : NullabilitySuffix.question);
 
   InterfaceType get boolType => typeProvider.boolType;
 
diff --git a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
new file mode 100644
index 0000000..707e370
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'element_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TypeParameterElementTest);
+    defineReflectiveTests(TypeParameterTypeTest);
+  });
+}
+
+@reflectiveTest
+class TypeParameterElementTest extends _TypeParameterElementBase {
+  test_equal_elementElement_sameLocation() {
+    var T1 = typeParameter('T');
+    var T2 = typeParameter('T');
+    var U = typeParameter('U');
+
+    _setEnclosingElement(T1);
+    _setEnclosingElement(T2);
+    _setEnclosingElement(U);
+
+    expect(T1 == T1, isTrue);
+    expect(T2 == T2, isTrue);
+    expect(U == U, isTrue);
+
+    expect(T1 == T2, isTrue);
+    expect(T2 == T1, isTrue);
+
+    expect(U == T1, isFalse);
+    expect(T1 == U, isFalse);
+  }
+
+  test_equal_elementElement_synthetic() {
+    var T1 = typeParameter('T');
+    var T2 = typeParameter('T');
+    expect(T1 == T1, isTrue);
+    expect(T2 == T2, isTrue);
+    expect(T1 == T2, isFalse);
+    expect(T2 == T1, isFalse);
+  }
+
+  test_equal_elementMember_sameBase_differentBounds() {
+    var T = typeParameter('T');
+    _setEnclosingElement(T);
+
+    var M = TypeParameterMember(T, null, typeProvider.intType);
+
+    expect(_equal(T, M), isTrue);
+    expect(_equal(M, T), isTrue);
+  }
+
+  test_equal_elementMember_sameBase_equalBounds() {
+    var T = typeParameter('T', bound: typeProvider.intType);
+    _setEnclosingElement(T);
+
+    var M = TypeParameterMember(T, null, typeProvider.intType);
+
+    expect(_equal(T, M), isTrue);
+    expect(_equal(M, T), isTrue);
+  }
+
+  test_equal_memberMember_differentBase() {
+    var T1 = typeParameter('T1');
+    var T2 = typeParameter('T2');
+
+    _setEnclosingElement(T1);
+    _setEnclosingElement(T2);
+
+    var M1 = TypeParameterMember(T1, null, typeProvider.numType);
+    var M2 = TypeParameterMember(T2, null, typeProvider.numType);
+
+    expect(M1 == M2, isFalse);
+  }
+
+  test_equal_memberMember_sameBase_differentBounds() {
+    var T = typeParameter('T');
+    _setEnclosingElement(T);
+
+    var M1 = TypeParameterMember(T, null, typeProvider.intType);
+    var M2 = TypeParameterMember(T, null, typeProvider.doubleType);
+
+    expect(M1 == M2, isTrue);
+  }
+
+  test_equal_memberMember_sameBase_equalBounds() {
+    var T = typeParameter('T');
+    _setEnclosingElement(T);
+
+    var M1 = TypeParameterMember(T, null, typeProvider.numType);
+    var M2 = TypeParameterMember(T, null, typeProvider.numType);
+
+    expect(M1 == M2, isTrue);
+    expect(M2 == M1, isTrue);
+  }
+
+  /// We use this method to work around the lint for using `==` for values
+  /// that are not of the same type.
+  static bool _equal(a, b) {
+    return a == b;
+  }
+}
+
+@reflectiveTest
+class TypeParameterTypeTest extends _TypeParameterElementBase {
+  test_equal_equalElements() {
+    var T1 = typeParameter('T');
+    var T2 = typeParameter('T');
+
+    _setEnclosingElement(T1);
+    _setEnclosingElement(T2);
+
+    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isTrue);
+    expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isTrue);
+
+    expect(typeParameterTypeNone(T1) == typeParameterTypeStar(T2), isFalse);
+    expect(typeParameterTypeStar(T1) == typeParameterTypeNone(T2), isFalse);
+  }
+
+  test_equal_sameElement_differentBounds() {
+    var T = typeParameter('T');
+    _setEnclosingElement(T);
+
+    var T1 = TypeParameterMember(T, null, typeProvider.intType);
+    var T2 = TypeParameterMember(T, null, typeProvider.doubleType);
+
+    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T1), isTrue);
+
+    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isFalse);
+    expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isFalse);
+
+    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T), isFalse);
+    expect(typeParameterTypeNone(T) == typeParameterTypeNone(T1), isFalse);
+  }
+
+  test_equal_sameElements() {
+    var T = typeParameter('T');
+
+    expect(typeParameterTypeNone(T) == typeParameterTypeNone(T), isTrue);
+    expect(typeParameterTypeNone(T) == typeParameterTypeStar(T), isFalse);
+    expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse);
+
+    expect(typeParameterTypeStar(T) == typeParameterTypeNone(T), isFalse);
+    expect(typeParameterTypeStar(T) == typeParameterTypeStar(T), isTrue);
+    expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse);
+
+    expect(
+      typeParameterTypeQuestion(T) == typeParameterTypeNone(T),
+      isFalse,
+    );
+    expect(
+      typeParameterTypeQuestion(T) == typeParameterTypeStar(T),
+      isFalse,
+    );
+    expect(
+      typeParameterTypeQuestion(T) == typeParameterTypeQuestion(T),
+      isTrue,
+    );
+  }
+}
+
+class _TypeParameterElementBase extends AbstractTypeTest {
+  /// Ensure that the [element] has a location.
+  void _setEnclosingElement(TypeParameterElementImpl element) {
+    element.enclosingElement = method('foo', typeProvider.voidType);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/constructor_test.dart b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
index db7428a..984e3bd 100644
--- a/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/type.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -14,14 +15,33 @@
 
 @reflectiveTest
 class ConstructorResolutionTest extends DriverResolutionTest {
-  test_initializer_field_functionExpression_expressionBody() async {
-    await resolveTestCode(r'''
-class C {
-  final int x;
-  C(int a) : x = (() => a + 1)();
+  test_factory_redirect_generic_instantiated() async {
+    await assertNoErrorsInCode(r'''
+class A<T> implements B<T> {
+  A(T a);
 }
+class B<U> {
+  factory B(U a) = A<U>;
+}
+
+B<int> b;
 ''');
-    assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
+    var classB_constructor = findElement.class_('B').unnamedConstructor;
+    assertMember2(
+      classB_constructor.redirectedConstructor,
+      findElement.unnamedConstructor('A'),
+      {'T': 'U'},
+    );
+
+    InterfaceType B_int = findElement.topVar('b').type;
+    var B_int_constructor = B_int.constructors.single;
+    var B_int_redirect = B_int_constructor.redirectedConstructor;
+    assertMember2(
+      B_int_redirect,
+      findElement.unnamedConstructor('A'),
+      {'T': 'int'},
+    );
+    assertElementTypeString(B_int_redirect.returnType, 'A<int>');
   }
 
   test_initializer_field_functionExpression_blockBody() async {
@@ -33,4 +53,14 @@
 ''');
     assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
   }
+
+  test_initializer_field_functionExpression_expressionBody() async {
+    await resolveTestCode(r'''
+class C {
+  final int x;
+  C(int a) : x = (() => a + 1)();
+}
+''');
+    assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
index 00fd73a..a095591 100644
--- a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
@@ -302,15 +302,13 @@
   int get a => 1;
 }
 ''');
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 import 'lib.dart' as p;
 
 f(p.C c) {
   c.a;
 }
-''', [
-      error(StaticTypeWarningCode.UNDEFINED_GETTER, 40, 1),
-    ]);
+''');
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 9f09f96..efd4af8 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -22,10 +22,10 @@
 
 import '../../../generated/test_support.dart';
 
-final isBottomType = new TypeMatcher<BottomTypeImpl>();
-
 final isDynamicType = new TypeMatcher<DynamicTypeImpl>();
 
+final isNeverType = new TypeMatcher<NeverTypeImpl>();
+
 final isVoidType = new TypeMatcher<VoidTypeImpl>();
 
 /// Base for resolution tests.
@@ -82,7 +82,7 @@
   ) {
     var actual = getNodeAuxElements(node)?.staticElement as ExecutableMember;
 
-    expect(actual.baseElement, same(expectedBase));
+    expect(actual.declaration, same(expectedBase));
 
     var actualMapString = actual.substitution.map.map(
       (k, v) => MapEntry(k.name, '$v'),
@@ -103,7 +103,7 @@
   void assertConstructorElement(
       ConstructorElement expected, ConstructorElement actual) {
     if (expected is ConstructorMember && actual is ConstructorMember) {
-      expect(expected.baseElement, same(actual.baseElement));
+      expect(expected.declaration, same(actual.declaration));
       // TODO(brianwilkerson) Compare the type arguments of the two members.
     } else {
       expect(expected, same(actual));
@@ -296,8 +296,16 @@
     Map<String, String> expectedSubstitution,
   ) {
     Member actual = getNodeElement(node);
+    assertMember2(actual, expectedBase, expectedSubstitution);
+  }
 
-    expect(actual.baseElement, same(expectedBase));
+  void assertMember2(
+    Element actualElement,
+    Element expectedBase,
+    Map<String, String> expectedSubstitution,
+  ) {
+    var actual = actualElement as Member;
+    expect(actual.declaration, same(expectedBase));
 
     var actualMapString = actual.substitution.map.map(
       (k, v) => MapEntry(k.name, '$v'),
@@ -318,12 +326,7 @@
 
     // TODO(scheglov) Check for Member.
     var element = invocation.methodName.staticElement;
-    if (element is Member) {
-      element = (element as Member).baseElement;
-      expect(element, same(expectedElement));
-    } else {
-      assertElement(invocation.methodName, expectedElement);
-    }
+    expect(element?.declaration, same(expectedElement));
 
     // TODO(scheglov) Should we enforce this?
 //    if (expectedNameType == null) {
diff --git a/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart b/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
index b85f38b..1dfbedd 100644
--- a/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
@@ -34,7 +34,7 @@
   test_nullableUnit_expressionStaticType_bottom() async {
     var identifier = AstTestFactory.identifier3('foo');
     var unit = _wrapExpression(identifier);
-    identifier.staticType = BottomTypeImpl.instance;
+    identifier.staticType = NeverTypeImpl.instance;
     expect(() {
       LegacyTypeAsserter.assertLegacyTypes(unit);
     }, throwsStateError);
@@ -43,7 +43,7 @@
   test_nullableUnit_expressionStaticType_bottomQuestion() async {
     var identifier = AstTestFactory.identifier3('foo');
     var unit = _wrapExpression(identifier);
-    identifier.staticType = BottomTypeImpl.instanceNullable;
+    identifier.staticType = NeverTypeImpl.instanceNullable;
     LegacyTypeAsserter.assertLegacyTypes(unit);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
index 2a9c670..873f765 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,19 +12,104 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AmbiguousSetOrMapLiteralBothTest);
+    defineReflectiveTests(AmbiguousSetOrMapLiteralBothWithNnbdTest);
     defineReflectiveTests(AmbiguousSetOrMapLiteralEitherTest);
+    defineReflectiveTests(AmbiguousSetOrMapLiteralEitherWithNnbdTest);
   });
 }
 
 @reflectiveTest
 class AmbiguousSetOrMapLiteralBothTest extends DriverResolutionTest {
+  test_map() async {
+    await assertNoErrorsInCode('''
+f(Map<int, int> map) {
+  return {...map};
+}
+''');
+  }
+
+  test_map_dynamic() async {
+    await assertNoErrorsInCode('''
+f(Map map) {
+  return {...map};
+}
+''');
+  }
+
+  test_set() async {
+    await assertNoErrorsInCode('''
+f(Set<int> set) {
+  return {...set};
+}
+''');
+  }
+
+  test_set_dynamic() async {
+    await assertNoErrorsInCode('''
+f(Set set) {
+  return {...set};
+}
+''');
+  }
+
   test_setAndMap() async {
     await assertErrorsInCode('''
-Map<int, int> map;
-Set<int> set;
-var c = {...set, ...map};
+f(Map<int, int> map, Set<int> set) {
+  return {...set, ...map};
+}
 ''', [
-      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 41, 16),
+      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 46, 16),
+    ]);
+  }
+}
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralBothWithNnbdTest
+    extends AmbiguousSetOrMapLiteralBothTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_map_keyNonNullable_valueNullable() async {
+    await assertNoErrorsInCode('''
+f(Map<int, int?> map) {
+  return {...map};
+}
+''');
+  }
+
+  test_map_keyNullable_valueNonNullable() async {
+    await assertNoErrorsInCode('''
+f(Map<int?, int> map) {
+  return {...map};
+}
+''');
+  }
+
+  test_map_keyNullable_valueNullable() async {
+    await assertNoErrorsInCode('''
+f(Map<int?, int?> map) {
+  return {...map};
+}
+''');
+  }
+
+  test_set_elementNullable() async {
+    await assertNoErrorsInCode('''
+f(Set<int?> set) {
+  return {...set};
+}
+''');
+  }
+
+  test_setAndMap_nullable() async {
+    await assertErrorsInCode('''
+f(Map<int?, int> map, Set<int?> set) {
+  return {...set, ...map};
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 48, 16),
     ]);
   }
 }
@@ -48,3 +135,12 @@
     ]);
   }
 }
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralEitherWithNnbdTest
+    extends AmbiguousSetOrMapLiteralEitherTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+}
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
index 5e19d96..0ed9acc 100644
--- a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -51,6 +51,9 @@
 ''');
   }
 
+  @FailingTest(
+    reason: 'The type of the parameterElement for `3` is non-nullable',
+  )
   test_optOut() async {
     await assertNoErrorsInCode('''
 // @dart = 2.2
diff --git a/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart b/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart
new file mode 100644
index 0000000..39ae942
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DeferredImportOfExtensionTest);
+  });
+}
+
+@reflectiveTest
+class DeferredImportOfExtensionTest extends DriverResolutionTest {
+  test_deferredImport_withExtensions() {
+    newFile('/test/lib/foo.dart', content: '''
+extension E on C {}
+class C {}
+''');
+    assertErrorsInCode('''
+import 'foo.dart' deferred as foo;
+
+void f() {
+  foo.C();
+}
+''', [
+      error(CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION, 7, 10),
+    ]);
+  }
+
+  test_deferredImport_withHiddenExtensions() {
+    newFile('/test/lib/foo.dart', content: '''
+extension E on C {}
+class C {}
+''');
+    assertNoErrorsInCode('''
+import 'foo.dart' deferred as foo hide E;
+
+void f() {
+  foo.C();
+}
+''');
+  }
+
+  test_deferredImport_withoutExtensions() {
+    newFile('/test/lib/foo.dart', content: '''
+class C {}
+''');
+    assertNoErrorsInCode('''
+import 'foo.dart' deferred as foo;
+
+void f() {
+  foo.C();
+}
+''');
+  }
+
+  test_deferredImport_withShownNonExtensions() {
+    newFile('/test/lib/foo.dart', content: '''
+extension E on C {}
+class C {}
+''');
+    assertNoErrorsInCode('''
+import 'foo.dart' deferred as foo show C;
+
+void f() {
+  foo.C();
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index e6cf43b..0c5caf1 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -518,6 +518,38 @@
 ''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
   }
 
+  test_fieldGet_implicitGetter() async {
+    resetWithFooLibrary(r'''
+class A {
+  @Deprecated('0.9')
+  bool bob = true;
+}
+''');
+
+    newPubPackage('/pkg1');
+    await assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() { var b = A().bob; }
+''', [HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE],
+        sourceName: '/pkg1/lib/lib1.dart');
+  }
+
+  test_fieldSet_implicitSetter() async {
+    resetWithFooLibrary(r'''
+class A {
+  @Deprecated('0.9')
+  bool bob = true;
+}
+''');
+
+    newPubPackage('/pkg1');
+    await assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() { A().bob = false; }
+''', [HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE],
+        sourceName: '/pkg1/lib/lib1.dart');
+  }
+
   test_gnWorkspace() async {
     resetWithFooLibrary(r'''
 @deprecated
@@ -602,7 +634,7 @@
 ''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
   }
 
-  test_methodInvocation_contructor() async {
+  test_methodInvocation_constructor() async {
     resetWithFooLibrary(r'''
 class A {
   @Deprecated('0.9')
@@ -634,4 +666,20 @@
         [HintCode.DEPRECATED_MEMBER_USE],
         sourceName: '/workspace/package/lib/lib1.dart');
   }
+
+  test_setterInvocation_constructor() async {
+    resetWithFooLibrary(r'''
+class A {
+  @Deprecated('0.9')
+  set bob(bool b) { }
+}
+''');
+
+    newPubPackage('/pkg1');
+    await assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() { A().bob = false; }
+''', [HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE],
+        sourceName: '/pkg1/lib/lib1.dart');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/extends_disallowed_class_test.dart b/pkg/analyzer/test/src/diagnostics/extends_disallowed_class_test.dart
new file mode 100644
index 0000000..4b6905f
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extends_disallowed_class_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtendsDisallowedClassTest);
+  });
+}
+
+@reflectiveTest
+class ExtendsDisallowedClassTest extends DriverResolutionTest {
+  test_class_bool() async {
+    await assertErrorsInCode('''
+class A extends bool {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
+    ]);
+  }
+
+  test_class_double() async {
+    await assertErrorsInCode('''
+class A extends double {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
+    ]);
+  }
+
+  test_class_FutureOr() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A extends FutureOr {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 37, 8),
+    ]);
+  }
+
+  test_class_FutureOr_typeArgument() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A extends FutureOr<int> {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 37, 13),
+    ]);
+  }
+
+  test_class_FutureOr_typeVariable() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A<T> extends FutureOr<T> {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 40, 11),
+    ]);
+  }
+
+  test_class_int() async {
+    await assertErrorsInCode('''
+class A extends int {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
+    ]);
+  }
+
+  test_class_Null() async {
+    await assertErrorsInCode('''
+class A extends Null {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
+    ]);
+  }
+
+  test_class_num() async {
+    await assertErrorsInCode('''
+class A extends num {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
+    ]);
+  }
+
+  test_class_String() async {
+    await assertErrorsInCode('''
+class A extends String {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
+    ]);
+  }
+
+  test_classTypeAlias_bool() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = bool with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
+    ]);
+  }
+
+  test_classTypeAlias_double() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = double with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
+    ]);
+  }
+
+  test_classTypeAlias_FutureOr() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+class M {}
+class C = FutureOr with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 42, 8),
+    ]);
+  }
+
+  test_classTypeAlias_int() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = int with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
+    ]);
+  }
+
+  test_classTypeAlias_Null() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = Null with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
+    ]);
+  }
+
+  test_classTypeAlias_num() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = num with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
+    ]);
+  }
+
+  test_classTypeAlias_String() async {
+    await assertErrorsInCode(r'''
+class M {}
+class C = String with M;
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/implements_disallowed_class_test.dart b/pkg/analyzer/test/src/diagnostics/implements_disallowed_class_test.dart
new file mode 100644
index 0000000..f106f37
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/implements_disallowed_class_test.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImplementsDisallowedClassTest);
+  });
+}
+
+@reflectiveTest
+class ImplementsDisallowedClassTest extends DriverResolutionTest {
+  test_class_bool() async {
+    await assertErrorsInCode('''
+class A implements bool {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
+    ]);
+  }
+
+  test_class_double() async {
+    await assertErrorsInCode('''
+class A implements double {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+    ]);
+  }
+
+  test_class_FutureOr() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A implements FutureOr {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 40, 8),
+    ]);
+  }
+
+  test_class_FutureOr_typeArgument() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A implements FutureOr<int> {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 40, 13),
+    ]);
+  }
+
+  test_class_FutureOr_typeVariable() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A<T> implements FutureOr<T> {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 43, 11),
+    ]);
+  }
+
+  test_class_int() async {
+    await assertErrorsInCode('''
+class A implements int {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
+    ]);
+  }
+
+  test_class_Null() async {
+    await assertErrorsInCode('''
+class A implements Null {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
+    ]);
+  }
+
+  test_class_num() async {
+    await assertErrorsInCode('''
+class A implements num {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
+    ]);
+  }
+
+  test_class_String() async {
+    await assertErrorsInCode('''
+class A implements String {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+    ]);
+  }
+
+  test_class_String_num() async {
+    await assertErrorsInCode('''
+class A implements String, num {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 27, 3),
+    ]);
+  }
+
+  test_classTypeAlias_bool() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements bool;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
+    ]);
+  }
+
+  test_classTypeAlias_double() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements double;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+    ]);
+  }
+
+  test_classTypeAlias_FutureOr() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+class A {}
+class M {}
+class C = A with M implements FutureOr;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 73, 8),
+    ]);
+  }
+
+  test_classTypeAlias_int() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements int;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
+    ]);
+  }
+
+  test_classTypeAlias_Null() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements Null;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
+    ]);
+  }
+
+  test_classTypeAlias_num() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements num;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
+    ]);
+  }
+
+  test_classTypeAlias_String() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements String;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+    ]);
+  }
+
+  test_classTypeAlias_String_num() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class C = A with M implements String, num;
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 60, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
index f8fe9c5..c04d1b0 100644
--- a/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
@@ -190,6 +190,12 @@
 ''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 9)]);
   }
 
+  test_setter_topLevel() async {
+    await assertNoErrorsInCode(r'''
+set f(int x) => print(x);
+''');
+  }
+
   test_topLevelArrowFunction() async {
     await assertErrorsInCode(r'''
 f() => 7;
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_template_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_template_member_test.dart
index 397fc3f..35f8b17 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_template_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_template_member_test.dart
@@ -34,7 +34,32 @@
 ''');
   }
 
-  test_constructor() async {
+  test_unnamedConstructor() async {
+    addAngularMetaPackage();
+    newFile('/lib1.dart', content: r'''
+import 'package:angular_meta/angular_meta.dart';
+class A {
+  int _x;
+
+  @visibleForTemplate
+  A(this._x);
+}
+''');
+    newFile('/lib2.dart', content: r'''
+import 'lib1.dart';
+
+void main() {
+  new A(0);
+}
+''');
+
+    await _resolveTestFile('/lib1.dart');
+    await _resolveTestFile('/lib2.dart');
+    assertTestErrorsWithCodes(
+        [HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER]);
+  }
+
+  test_namedConstructor() async {
     addAngularMetaPackage();
     newFile('/lib1.dart', content: r'''
 import 'package:angular_meta/angular_meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
index d61d928..97e5d82 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
@@ -25,7 +25,31 @@
     ..contextFeatures = new FeatureSet.forTesting(
         sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
 
-  test_constructor() async {
+  test_unnamedConstructor() async {
+    addMetaPackage();
+    newFile('/lib1.dart', content: r'''
+import 'package:meta/meta.dart';
+class A {
+  int _x;
+
+  @visibleForTesting
+  A(this._x);
+}
+''');
+    newFile('/lib2.dart', content: r'''
+import 'lib1.dart';
+void main() {
+  new A(0);
+}
+''');
+
+    await _resolveTestFile('/lib1.dart');
+    await _resolveTestFile('/lib2.dart');
+    assertTestErrorsWithCodes(
+        [HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER]);
+  }
+
+  test_namedConstructor() async {
     addMetaPackage();
     newFile('/lib1.dart', content: r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_of_disallowed_class_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_of_disallowed_class_test.dart
new file mode 100644
index 0000000..b22ce50
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_of_disallowed_class_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MixinOfDisallowedClassTest);
+  });
+}
+
+@reflectiveTest
+class MixinOfDisallowedClassTest extends DriverResolutionTest {
+  test_class_bool() async {
+    await assertErrorsInCode('''
+class A extends Object with bool {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
+  }
+
+  test_class_double() async {
+    await assertErrorsInCode('''
+class A extends Object with double {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
+  }
+
+  test_class_FutureOr() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A extends Object with FutureOr {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 49, 8),
+    ]);
+  }
+
+  test_class_FutureOr_typeArgument() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A extends Object with FutureOr<int> {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 49, 13),
+    ]);
+  }
+
+  test_class_FutureOr_typeVariable() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+class A<T> extends Object with FutureOr<T> {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 52, 11),
+    ]);
+  }
+
+  test_class_int() async {
+    await assertErrorsInCode('''
+class A extends Object with int {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
+  }
+
+  test_class_Null() async {
+    await assertErrorsInCode('''
+class A extends Object with Null {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
+  }
+
+  test_class_num() async {
+    await assertErrorsInCode('''
+class A extends Object with num {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
+  }
+
+  test_class_String() async {
+    await assertErrorsInCode('''
+class A extends Object with String {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
+  }
+
+  test_classTypeAlias_bool() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with bool;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
+  }
+
+  test_classTypeAlias_double() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with double;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
+  }
+
+  test_classTypeAlias_FutureOr() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+class A {}
+class C = A with FutureOr;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 49, 8),
+    ]);
+  }
+
+  test_classTypeAlias_int() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with int;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
+  }
+
+  test_classTypeAlias_Null() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with Null;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
+  }
+
+  test_classTypeAlias_num() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with num;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
+  }
+
+  test_classTypeAlias_String() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with String;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
+  }
+
+  test_classTypeAlias_String_num() async {
+    await assertErrorsInCode(r'''
+class A {}
+class C = A with String, num;
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 36, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index f7fe172..d003c07 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -51,6 +51,7 @@
     as default_list_constructor_mismatch;
 import 'default_value_on_required_parameter_test.dart'
     as default_value_on_required_paramter;
+import 'deferred_import_of_extension_test.dart' as deferred_import_of_extension;
 import 'deprecated_extends_function_test.dart' as deprecated_extends_function;
 import 'deprecated_function_class_declaration_test.dart'
     as deprecated_function_class_declaration;
@@ -67,6 +68,7 @@
 import 'export_suplicated_library_named_test.dart'
     as export_suplicated_library_named;
 import 'expression_in_map_test.dart' as expression_in_map;
+import 'extends_disallowed_class_test.dart' as extends_disallowed_class;
 import 'extends_non_class_test.dart' as extends_non_class;
 import 'extension_as_expression_test.dart' as extension_as_expression;
 import 'extension_conflicting_static_and_instance_test.dart'
@@ -106,6 +108,7 @@
 import 'generic_struct_subclass_test.dart' as generic_struct_subclass;
 import 'if_element_condition_from_deferred_library_test.dart'
     as if_element_condition_from_deferred_library;
+import 'implements_disallowed_class_test.dart' as implements_disallowed_class;
 import 'implements_non_class_test.dart' as implements_non_class;
 import 'implicit_this_reference_in_initializer_test.dart'
     as implicit_this_reference_in_initializer;
@@ -191,6 +194,7 @@
 import 'missing_required_param_test.dart' as missing_required_param;
 import 'missing_return_test.dart' as missing_return;
 import 'mixed_return_types_test.dart' as mixed_return_types;
+import 'mixin_of_disallowed_class_test.dart' as mixin_of_disallowed_class;
 import 'mixin_of_non_class_test.dart' as mixin_of_non_class;
 import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
 import 'mixin_super_class_constraint_non_interface_test.dart'
@@ -397,6 +401,7 @@
     dead_code.main();
     default_list_constructor_mismatch.main();
     default_value_on_required_paramter.main();
+    deferred_import_of_extension.main();
     deprecated_extends_function.main();
     deprecated_function_class_declaration.main();
     deprecated_member_use.main();
@@ -411,6 +416,7 @@
     equal_keys_in_const_map.main();
     export_suplicated_library_named.main();
     expression_in_map.main();
+    extends_disallowed_class.main();
     extends_non_class.main();
     extension_as_expression.main();
     extension_conflicting_static_and_instance.main();
@@ -434,6 +440,7 @@
     final_not_initialized.main();
     generic_struct_subclass.main();
     if_element_condition_from_deferred_library.main();
+    implements_disallowed_class.main();
     implements_non_class.main();
     implicit_this_reference_in_initializer.main();
     import_deferred_library_with_load_function.main();
@@ -491,6 +498,7 @@
     missing_required_param.main();
     missing_return.main();
     mixed_return_types.main();
+    mixin_of_disallowed_class.main();
     mixin_of_non_class.main();
     mixin_on_sealed_class.main();
     mixin_super_class_constraint_non_interface.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
index 4dffd2a..a80bc83 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
@@ -70,6 +70,25 @@
     ]);
   }
 
+  test_override_undefined_hasGetterAndNonExtensionSetter() async {
+    await assertErrorsInCode('''
+class C {
+  int get id => 0;
+  void set id(int v) {}
+}
+
+extension Ext on C {
+  int get id => 1;
+}
+
+f(C c) {
+  Ext(c).id++;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER, 117, 2),
+    ]);
+  }
+
   test_static_undefined() async {
     await assertErrorsInCode('''
 extension E on int {}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 1ab09c0..8ecf7ea 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -285,6 +285,7 @@
     writeIf(e.isExternal, 'external ');
     writeIf(e.isConst, 'const ');
     writeIf(e.isFactory, 'factory ');
+    expect(e.isAbstract, isFalse);
 
     buffer.write(e.enclosingElement.name);
     if (e.name.isNotEmpty) {
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index faa8571..ed41fb1 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -1689,7 +1689,7 @@
     } else if (element is Member) {
       _sink.writeln(_nameOfMemberClass(element));
       _withIndent(() {
-        _writeElement('base', element.baseElement);
+        _writeElement('base', element.declaration);
         _writelnWithIndent('substitution: ${element.substitution.map}');
       });
     } else {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 618e653..f9edcbf 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
@@ -31,10 +32,21 @@
 class ResynthesizeAst2Test extends ResynthesizeTestStrategyTwoPhase
     with ResynthesizeTestCases {
   /// The shared SDK bundle, computed once and shared among test invocations.
-  static LinkedNodeBundle _sdkBundle;
+  static LinkedNodeBundle _sdkBundleNnbd;
+
+  /// The shared SDK bundle, computed once and shared among test invocations.
+  static LinkedNodeBundle _sdkBundleLegacy;
 
   LinkedNodeBundle get sdkBundle {
-    if (_sdkBundle != null) return _sdkBundle;
+    if (featureSet.isEnabled(Feature.non_nullable)) {
+      if (_sdkBundleNnbd != null) {
+        return _sdkBundleNnbd;
+      }
+    } else {
+      if (_sdkBundleLegacy != null) {
+        return _sdkBundleLegacy;
+      }
+    }
 
     var inputLibraries = <LinkInputLibrary>[];
     for (var sdkLibrary in sdk.sdkLibraries) {
@@ -64,7 +76,12 @@
     var sdkLinkResult = link(elementFactory, inputLibraries);
 
     var bytes = sdkLinkResult.bundle.toBuffer();
-    return _sdkBundle = LinkedNodeBundle.fromBuffer(bytes);
+    var sdkBundle = LinkedNodeBundle.fromBuffer(bytes);
+    if (featureSet.isEnabled(Feature.non_nullable)) {
+      return _sdkBundleNnbd = sdkBundle;
+    } else {
+      return _sdkBundleLegacy = sdkBundle;
+    }
   }
 
   @override
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 4f81d47..41ac8c8 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -7512,6 +7512,75 @@
 ''');
   }
 
+  test_instanceInference_operator_equal_legacy() async {
+    var library = await checkLibrary(r'''
+class A1 {
+  bool operator==(other) => false;
+}
+class A2 {
+  bool operator==(int other) => false;
+}
+class B1 extends A1 {
+  bool operator==(other) => false;
+}
+class B2 extends A2 {
+  bool operator==(other) => false;
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class A1 {
+  bool* ==(dynamic other) {}
+}
+class A2 {
+  bool* ==(int* other) {}
+}
+class B1 extends A1* {
+  bool* ==(dynamic other) {}
+}
+class B2 extends A2* {
+  bool* ==(int* other) {}
+}
+''',
+        annotateNullability: true);
+  }
+
+  test_instanceInference_operator_equal_nnbd() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+class A1 {
+  bool operator==(other) => false;
+}
+class A2 {
+  bool operator==(int other) => false;
+}
+class B1 extends A1 {
+  bool operator==(other) => false;
+}
+class B2 extends A2 {
+  bool operator==(other) => false;
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class A1 {
+  bool ==(Object other) {}
+}
+class A2 {
+  bool ==(int other) {}
+}
+class B1 extends A1 {
+  bool ==(Object other) {}
+}
+class B2 extends A2 {
+  bool ==(int other) {}
+}
+''',
+        annotateNullability: true);
+  }
+
   test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
     var library = await checkLibrary('''
 class C<S extends num, T extends C<S, T>> {}
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 2ea4044..81f7eaa 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart' hide Annotation;
 import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -141,7 +142,12 @@
   var errors =
       result.errors.where((e) => e.severity == Severity.error).toList();
   if (errors.isNotEmpty) {
-    onFailure('Errors found:\n  ${errors.join('\n  ')}');
+    String _formatError(AnalysisError e) {
+      var locationInfo = result.unit.lineInfo.getLocation(e.offset);
+      return '$locationInfo: ${e.errorCode}: ${e.message}';
+    }
+
+    onFailure('Errors found:\n  ${errors.map(_formatError).join('\n  ')}');
     return true;
   }
   Map<Uri, Map<Id, ActualData<T>>> actualMaps = <Uri, Map<Id, ActualData<T>>>{};
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 5d333e2..cdbb435 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -3,12 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart'
-    show LocatedMessage, Message;
+    show LocatedMessage, Message, templateInternalProblemUnsupported;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
-import 'package:front_end/src/fasta/problems.dart'
-    show internalProblem, unsupported;
-import 'package:front_end/src/fasta/source/stack_listener.dart';
 
 /// "Mini AST" representation of a declaration which can accept annotations.
 class AnnotatedNode {
@@ -189,6 +187,11 @@
   Uri get uri => null;
 
   @override
+  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+    throw UnsupportedError(message.message);
+  }
+
+  @override
   void addProblem(Message message, int charOffset, int length,
       {bool wasHandled: false, List<LocatedMessage> context}) {
     internalProblem(message, charOffset, uri);
@@ -264,7 +267,10 @@
   void endConditionalUris(int count) {
     debugEvent("ConditionalUris");
     if (count != 0) {
-      unsupported("Conditional URIs", -1, null);
+      internalProblem(
+          templateInternalProblemUnsupported.withArguments("Conditional URIs"),
+          -1,
+          null);
     }
   }
 
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index e6a08d1..ff7b464 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -262,9 +262,7 @@
 
 /// This [InstrumentationService] prints out information comments to [outSink]
 /// and error messages to [errorSink].
-class StdInstrumentation extends InstrumentationService {
-  StdInstrumentation() : super(null);
-
+class StdInstrumentation extends NoopInstrumentationService {
   @override
   void logError(String message) {
     errorSink.writeln(message);
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 02197e3..59174f7 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -54,12 +54,8 @@
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
 import 'package:package_config/src/packages_impl.dart' show MapPackages;
 import 'package:path/path.dart' as path;
-import 'package:telemetry/crash_reporting.dart';
-import 'package:telemetry/telemetry.dart' as telemetry;
 import 'package:yaml/yaml.dart';
 
-const _analyticsID = 'UA-26406144-28';
-
 /// Shared IO sink for standard error reporting.
 @visibleForTesting
 StringSink errorSink = io.stderr;
@@ -68,30 +64,12 @@
 @visibleForTesting
 StringSink outSink = io.stdout;
 
-telemetry.Analytics _analytics;
-
-/// The analytics instance for analyzer-cli.
-telemetry.Analytics get analytics => (_analytics ??=
-    telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli'));
-
 /// Test this option map to see if it specifies lint rules.
 bool containsLintRuleEntry(YamlMap options) {
   YamlNode linterNode = getValue(options, 'linter');
   return linterNode is YamlMap && getValue(linterNode, 'rules') != null;
 }
 
-/// Make sure that we create an analytics instance that doesn't send for this
-/// session.
-void disableAnalyticsForSession() {
-  _analytics = telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli',
-      disableForSession: true);
-}
-
-@visibleForTesting
-void setAnalytics(telemetry.Analytics replacementAnalytics) {
-  _analytics = replacementAnalytics;
-}
-
 class Driver with HasContextMixin implements CommandLineStarter {
   static final PerformanceTag _analyzeAllTag =
       new PerformanceTag("Driver._analyzeAll");
@@ -127,24 +105,13 @@
   /// Collected analysis statistics.
   final AnalysisStats stats = new AnalysisStats();
 
-  CrashReportSender _crashReportSender;
-
   /// The [PathFilter] for excluded files with wildcards, etc.
   PathFilter pathFilter;
 
   /// Create a new Driver instance.
   ///
   /// [isTesting] is true if we're running in a test environment.
-  Driver({bool isTesting: false}) {
-    if (isTesting) {
-      disableAnalyticsForSession();
-    }
-  }
-
-  /// The crash reporting instance for analyzer-cli.
-  /// TODO(devoncarew): Replace with the real crash product ID.
-  CrashReportSender get crashReportSender => (_crashReportSender ??=
-      new CrashReportSender('Dart_analyzer_cli', analytics));
+  Driver({bool isTesting: false});
 
   /**
    * Converts the given [filePath] into absolute and normalized.
@@ -170,15 +137,6 @@
     // Parse commandline options.
     CommandLineOptions options = CommandLineOptions.parse(args);
 
-    if (options.batchMode || options.buildMode) {
-      disableAnalyticsForSession();
-    }
-
-    // Ping analytics with our initial call.
-    analytics.sendScreenView('home');
-
-    var timer = analytics.startTimer('analyze');
-
     // Do analysis.
     if (options.buildMode) {
       ErrorSeverity severity = await _buildModeAnalyze(options, sendPort);
@@ -222,21 +180,11 @@
       _analyzedFileCount += analysisDriver.knownFiles.length;
     }
 
-    // Send how long analysis took.
-    timer.finish();
-
-    // Send how many files were analyzed.
-    analytics.sendEvent('analyze', 'fileCount', value: _analyzedFileCount);
-
     if (options.perfReport != null) {
       String json = makePerfReport(
           startTime, currentTimeMillis, options, _analyzedFileCount, stats);
       new io.File(options.perfReport).writeAsStringSync(json);
     }
-
-    // Wait a brief time for any analytics calls to finish.
-    await analytics.waitForLastPing(timeout: new Duration(milliseconds: 200));
-    analytics.close();
   }
 
   Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async {
@@ -245,11 +193,6 @@
     PerformanceTag previous = _analyzeAllTag.makeCurrent();
     try {
       return await _analyzeAllImpl(options);
-    } catch (e, st) {
-      // Catch and ignore any exceptions when reporting exceptions (network
-      // errors or other).
-      crashReportSender.sendReport(e, stackTrace: st).catchError((_) {});
-      rethrow;
     } finally {
       previous.makeCurrent();
     }
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 4aa34fc..afb1457 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer_cli/src/ansi.dart' as ansi;
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:args/args.dart';
-import 'package:telemetry/telemetry.dart' as telemetry;
 
 const _binaryName = 'dartanalyzer';
 
@@ -326,10 +325,6 @@
           help: 'Verbose output.',
           negatable: false);
 
-    parser.addFlag('analytics',
-        help: 'Enable or disable sending analytics information to Google.',
-        hide: !telemetry.SHOW_ANALYTICS_UI);
-
     // Build mode options.
     if (!hide) {
       parser.addSeparator('Build mode flags:');
@@ -503,27 +498,16 @@
 
       // Help requests.
       if (cast(results['help'])) {
-        _showUsage(parser, analytics, fromHelp: true);
+        _showUsage(parser, fromHelp: true);
         exitHandler(0);
         return null; // Only reachable in testing.
       }
 
-      // Enable / disable analytics.
-      if (telemetry.SHOW_ANALYTICS_UI) {
-        if (results.wasParsed('analytics')) {
-          analytics.enabled = cast(results['analytics']);
-          outSink.writeln(
-              telemetry.createAnalyticsStatusMessage(analytics.enabled));
-          exitHandler(0);
-          return null; // Only reachable in testing.
-        }
-      }
-
       // Batch mode and input files.
       if (cast(results['batch'])) {
         if (results.rest.isNotEmpty) {
           errorSink.writeln('No source files expected in the batch mode.');
-          _showUsage(parser, analytics);
+          _showUsage(parser);
           exitHandler(15);
           return null; // Only reachable in testing.
         }
@@ -531,7 +515,7 @@
         if (results.rest.isNotEmpty) {
           errorSink.writeln(
               'No source files expected in the persistent worker mode.');
-          _showUsage(parser, analytics);
+          _showUsage(parser);
           exitHandler(15);
           return null; // Only reachable in testing.
         }
@@ -541,7 +525,7 @@
         return null; // Only reachable in testing.
       } else {
         if (results.rest.isEmpty && !cast<bool>(results['build-mode'])) {
-          _showUsage(parser, analytics, fromHelp: true);
+          _showUsage(parser, fromHelp: true);
           exitHandler(15);
           return null; // Only reachable in testing.
         }
@@ -564,7 +548,7 @@
           errorSink.writeln('$kind: ${validationResult.message}');
         }
         if (errorFound) {
-          _showUsage(parser, null);
+          _showUsage(parser);
           exitHandler(15);
           return null; // Only reachable in testing.
         }
@@ -573,47 +557,19 @@
       return new CommandLineOptions._fromArgs(results);
     } on FormatException catch (e) {
       errorSink.writeln(e.message);
-      _showUsage(parser, null);
+      _showUsage(parser);
       exitHandler(15);
       return null; // Only reachable in testing.
     }
   }
 
-  static _showUsage(ArgParser parser, telemetry.Analytics analytics,
-      {bool fromHelp: false}) {
-    void printAnalyticsInfo() {
-      if (!telemetry.SHOW_ANALYTICS_UI) {
-        return;
-      }
-
-      if (fromHelp) {
-        errorSink.writeln('');
-        errorSink.writeln(telemetry.analyticsNotice);
-      }
-
-      if (analytics != null) {
-        errorSink.writeln('');
-        errorSink.writeln(telemetry.createAnalyticsStatusMessage(
-            analytics.enabled,
-            command: 'analytics'));
-      }
-    }
-
+  static _showUsage(ArgParser parser, {bool fromHelp: false}) {
     errorSink.writeln(
         'Usage: $_binaryName [options...] <directory or list of files>');
 
-    // If it's our first run, we display the analytics info more prominently.
-    if (analytics != null && analytics.firstRun) {
-      printAnalyticsInfo();
-    }
-
     errorSink.writeln('');
     errorSink.writeln(parser.usage);
 
-    if (analytics != null && !analytics.firstRun) {
-      printAnalyticsInfo();
-    }
-
     errorSink.writeln('');
     errorSink.writeln('''
 Run "dartanalyzer -h -v" for verbose help output, including less commonly used options.
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 2baf586..f7d53f2 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -9,7 +9,6 @@
   linter: ^0.1.16
   package_config: '>=0.1.5 <2.0.0'
   protobuf: ^0.13.0
-  telemetry: ^0.0.1
   yaml: ^2.1.2
 dev_dependencies:
   test_reflective_loader: ^0.1.8
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 489ff5e..3356456 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -9,10 +9,8 @@
     show overrideKnownFeatures;
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/options.dart';
-import 'package:telemetry/telemetry.dart' as telemetry;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:usage/usage.dart';
 
 main() {
   group('CommandLineOptions', () {
@@ -261,28 +259,6 @@
         expect(failureMessage, equals('Invalid Dart SDK path: &&&&&'));
       });
 
-      if (telemetry.SHOW_ANALYTICS_UI) {
-        test('--analytics', () {
-          AnalyticsMock mock = new AnalyticsMock()..enabled = false;
-          setAnalytics(mock);
-          CommandLineOptions.parse(['--analytics']);
-          expect(mock.enabled, true);
-          expect(lastExitHandlerCode, 0);
-          expect(
-              outStringBuffer.toString(), contains('Analytics are currently'));
-        });
-
-        test('--no-analytics', () {
-          AnalyticsMock mock = new AnalyticsMock()..enabled = false;
-          setAnalytics(mock);
-          CommandLineOptions.parse(['--no-analytics']);
-          expect(mock.enabled, false);
-          expect(lastExitHandlerCode, 0);
-          expect(
-              outStringBuffer.toString(), contains('Analytics are currently'));
-        });
-      }
-
       test('--use-fasta-parser', () {
         CommandLineOptions options =
             CommandLineOptions.parse(['--use-fasta-parser', 'foo.dart']);
diff --git a/pkg/analyzer_plugin/README.md b/pkg/analyzer_plugin/README.md
index 42cf20a..0644f0b 100644
--- a/pkg/analyzer_plugin/README.md
+++ b/pkg/analyzer_plugin/README.md
@@ -31,4 +31,4 @@
 [LICENSE]: https://github.com/dart-lang/sdk/blob/master/pkg/analyzer/LICENSE
 [list]: https://groups.google.com/a/dartlang.org/forum/#!forum/analyzer-discuss
 [pluginapi]: https://htmlpreview.github.io/?https://github.com/dart-lang/sdk/blob/master/pkg/analyzer_plugin/doc/api.html
-[tutorial]: doc/tutorial/tutorial.md
+[tutorial]: https://github.com/dart-lang/sdk/blob/master/pkg/analyzer_plugin/doc/tutorial/tutorial.md
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 386f4ed..4f135b3 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -2289,6 +2289,9 @@
   /// where the type arguments are the type variables of [cls].
   InterfaceType getThisType(ClassEntity cls);
 
+  /// Returns the instantiation of [cls] to bounds.
+  InterfaceType getClassInstantiationToBounds(ClassEntity cls);
+
   /// Returns `true` if [cls] is generic.
   bool isGenericClass(ClassEntity cls);
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 186623f..1c392c8 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -1511,6 +1511,20 @@
     return outputUnitTo._imports.containsAll(outputUnitFrom._imports);
   }
 
+  /// Returns `true` if class [to] is reachable from element [from] without
+  /// crossing a deferred import.
+  ///
+  /// For example, if we have two deferred libraries `A` and `B` that both
+  /// import a library `C`, then even though elements from `A` and `C` end up in
+  /// different output units, there is a non-deferred path between `A` and `C`.
+  bool hasOnlyNonDeferredImportPathsToClass(MemberEntity from, ClassEntity to) {
+    OutputUnit outputUnitFrom = outputUnitForMember(from);
+    OutputUnit outputUnitTo = outputUnitForClass(to);
+    if (outputUnitTo == mainOutputUnit) return true;
+    if (outputUnitFrom == mainOutputUnit) return false;
+    return outputUnitTo._imports.containsAll(outputUnitFrom._imports);
+  }
+
   /// Registers that a constant is used in the same deferred output unit as
   /// [field].
   void registerConstantDeferredUse(DeferredGlobalConstantValue constant) {
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 5445a80..ee278b1 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -35,6 +35,9 @@
   /// is the function type `(String) -> int`.
   DartType get unaliased => this;
 
+  /// Is `true` if this type is a top type.
+  bool get isTop => false;
+
   /// Is `true` if this type has no non-dynamic type arguments.
   bool get treatAsRaw => true;
 
@@ -181,6 +184,9 @@
       : assert(typeArguments.every((e) => e != null));
 
   @override
+  bool get isTop => isObject;
+
+  @override
   bool get isInterfaceType => true;
 
   @override
@@ -249,6 +255,9 @@
   TypedefType(this.element, this.typeArguments, this.unaliased);
 
   @override
+  bool get isTop => unaliased.isTop;
+
+  @override
   bool get isTypedef => true;
 
   @override
@@ -401,6 +410,9 @@
   factory VoidType() => const VoidType._();
 
   @override
+  bool get isTop => true;
+
+  @override
   bool get isVoid => true;
 
   @override
@@ -422,6 +434,9 @@
   factory DynamicType() => const DynamicType._();
 
   @override
+  bool get isTop => true;
+
+  @override
   bool get isDynamic => true;
 
   @override
@@ -446,6 +461,9 @@
   factory ErasedType() => const ErasedType._();
 
   @override
+  bool get isTop => true;
+
+  @override
   bool get treatAsDynamic => true;
 
   @override
@@ -480,6 +498,9 @@
   factory AnyType() => const AnyType._();
 
   @override
+  bool get isTop => true;
+
+  @override
   bool get isAny => true;
 
   @override
@@ -624,6 +645,9 @@
   FutureOrType(this.typeArgument);
 
   @override
+  bool get isTop => typeArgument.isTop;
+
+  @override
   bool get isFutureOr => true;
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index bf214c1..a4accab 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -223,6 +223,17 @@
   /// [NativeBehavior].
   TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior);
 
+  /// For a given selector, return a shared dynamic call site that will be used
+  /// to combine the results of multiple dynamic calls in the program via
+  /// [IndirectDynamicCallSiteTypeInformation].
+  ///
+  /// This is used only for scalability reasons: if there are too many targets
+  /// and call sites, we may have a quadratic number of edges in the graph, so
+  /// we add a level of indirection to merge the information and keep the graph
+  /// smaller.
+  DynamicCallSiteTypeInformation typeOfSharedDynamicCall(
+      Selector selector, CallStructure structure);
+
   bool returnsListElementType(Selector selector, AbstractValue mask);
 
   bool returnsMapValueType(Selector selector, AbstractValue mask);
@@ -397,11 +408,14 @@
   void updateSelectorInMember(MemberEntity owner, CallType callType,
       ir.Node node, Selector selector, AbstractValue mask) {
     KernelGlobalTypeInferenceElementData data = dataOfMember(owner);
-    assert(validCallType(callType, node));
+    assert(validCallType(callType, node, selector));
     switch (callType) {
       case CallType.access:
         data.setTypeMask(node, mask);
         break;
+      case CallType.indirectAccess:
+        // indirect access is not diretly recorded in the result data.
+        break;
       case CallType.forIn:
         if (selector == Selectors.iterator) {
           data.setIteratorTypeMask(node, mask);
@@ -1142,19 +1156,40 @@
       updateSideEffects(sideEffectsBuilder, selector, callee);
     });
 
-    CallSiteTypeInformation info = new DynamicCallSiteTypeInformation(
-        abstractValueDomain,
-        types.currentMember,
-        callType,
-        node,
-        caller,
-        selector,
-        mask,
-        receiverType,
-        arguments,
-        inLoop,
-        isConditional);
+    CallSiteTypeInformation info;
 
+    // We force using indirection for `==` because it is a very common dynamic
+    // call site on many apps.
+    // TODO(sigmund): it would be even better if we could automatically detect
+    // when dynamic calls are growing too big and add the indirection at that
+    // point.
+    if (selector.name == '==') {
+      info = new IndirectDynamicCallSiteTypeInformation(
+          abstractValueDomain,
+          types.currentMember,
+          node,
+          typeOfSharedDynamicCall(selector, CallStructure.ONE_ARG),
+          caller,
+          selector,
+          mask,
+          receiverType,
+          arguments,
+          inLoop,
+          isConditional);
+    } else {
+      info = new DynamicCallSiteTypeInformation(
+          abstractValueDomain,
+          types.currentMember,
+          callType,
+          node,
+          caller,
+          selector,
+          mask,
+          receiverType,
+          arguments,
+          inLoop,
+          isConditional);
+    }
     info.addToGraph(this);
     types.allocatedCalls.add(info);
     return info;
@@ -1282,6 +1317,48 @@
     }
   }
 
+  /// Indirect calls share the same dynamic call site information node. This
+  /// cache holds that shared dynamic call node for a given selector.
+  Map<Selector, DynamicCallSiteTypeInformation> _sharedCalls = {};
+
+  @override
+  DynamicCallSiteTypeInformation typeOfSharedDynamicCall(
+      Selector selector, CallStructure structure) {
+    DynamicCallSiteTypeInformation info = _sharedCalls[selector];
+    if (info != null) return info;
+
+    TypeInformation receiverType =
+        new IndirectParameterTypeInformation(abstractValueDomain, 'receiver');
+    List<TypeInformation> positional = [];
+    for (int i = 0; i < structure.positionalArgumentCount; i++) {
+      positional
+          .add(new IndirectParameterTypeInformation(abstractValueDomain, '$i'));
+    }
+    Map<String, TypeInformation> named = {};
+    if (structure.namedArgumentCount > 0) {
+      for (var name in structure.namedArguments) {
+        named[name] =
+            new IndirectParameterTypeInformation(abstractValueDomain, name);
+      }
+    }
+
+    info = _sharedCalls[selector] = new DynamicCallSiteTypeInformation(
+        abstractValueDomain,
+        null,
+        CallType.indirectAccess,
+        null,
+        null,
+        selector,
+        null,
+        receiverType,
+        ArgumentsTypes(positional, named),
+        false,
+        false);
+    info.addToGraph(this);
+    types.allocatedCalls.add(info);
+    return info;
+  }
+
   @override
   bool canFieldBeUsedForGlobalOptimizations(FieldEntity element) {
     if (closedWorld.backendUsage.isFieldUsedByBackend(element)) {
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 987cb11..4d4a4bd 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -270,6 +270,14 @@
     }
   }
 
+  @override
+  visitIndirectDynamicCallSiteTypeInformation(
+      IndirectDynamicCallSiteTypeInformation info) {
+    if (info.dynamicCall == currentUser) {
+      addNewEscapeInformation(info);
+    }
+  }
+
   void analyzeStoredIntoList(ListTypeInformation list) {
     inferrer.analyzeListAndEnqueue(list);
     if (list.bailedOut) {
@@ -547,4 +555,10 @@
     }
     addNewEscapeInformation(info);
   }
+
+  @override
+  void visitIndirectParameterTypeInformation(
+      IndirectParameterTypeInformation info) {
+    addNewEscapeInformation(info);
+  }
 }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index 70d3fa0..a4ed3e3 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -411,6 +411,12 @@
   }
 
   @override
+  void visitIndirectDynamicCallSiteTypeInformation(
+      IndirectDynamicCallSiteTypeInformation info) {
+    handleCall(info, 'IndirectDynamicCallSite', {});
+  }
+
+  @override
   void visitDynamicCallSiteTypeInformation(
       DynamicCallSiteTypeInformation info) {
     handleCall(info, 'DynamicCallSite', {'obj': info.receiver});
@@ -427,6 +433,12 @@
   }
 
   @override
+  void visitIndirectParameterTypeInformation(
+      IndirectParameterTypeInformation info) {
+    addNode(info, 'IndirectParameter ${info.debugName}');
+  }
+
+  @override
   void visitClosureTypeInformation(ClosureTypeInformation info) {
     String text = shorten('${info.debugName}');
     addNode(info, 'Closure\n$text');
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 3a41951..a1e7c15 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -116,8 +116,7 @@
           returnType != null &&
               abstractValueDomain.isEmpty(returnType).isDefinitelyTrue;
 
-      bool isCalledOnce =
-          typeInformation.isCalledOnce(); //isMemberCalledOnce(member);
+      bool isCalledOnce = typeInformation.isCalledOnce();
 
       memberResults[member] = new GlobalTypeInferenceMemberResultImpl(
           data, returnType, type,
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index f3a949d..f674734 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -377,6 +377,10 @@
   // cleanup has been called.
   bool _isCalledOnce = null;
 
+  /// Whether this member is invoked via indirect dynamic calls. In that case
+  /// the exact number of call sites cannot be computed precisely.
+  bool _calledIndirectly = false;
+
   /// This map contains the callers of [element]. It stores all unique call
   /// sites to enable counting the global number of call sites of [element].
   ///
@@ -427,6 +431,7 @@
   }
 
   bool _computeIsCalledOnce() {
+    if (_calledIndirectly) return false;
     if (_callers == null) return false;
     int count = 0;
     for (var set in _callers.values) {
@@ -872,15 +877,40 @@
   }
 }
 
+/// A synthetic parameter used to model the entry points to a
+/// [IndirectDynamicCallSiteTypeInformation].
+class IndirectParameterTypeInformation extends TypeInformation {
+  final String debugName;
+
+  IndirectParameterTypeInformation(
+      AbstractValueDomain abstractValueDomain, this.debugName)
+      : super(abstractValueDomain.emptyType, null);
+
+  @override
+  AbstractValue computeType(InferrerEngine inferrer) =>
+      inferrer.types.computeTypeMask(assignments);
+
+  @override
+  accept(TypeInformationVisitor visitor) {
+    return visitor.visitIndirectParameterTypeInformation(this);
+  }
+
+  @override
+  String toString() => 'IndirectParameter $debugName $type';
+}
+
 enum CallType {
   access,
+  indirectAccess,
   forIn,
 }
 
-bool validCallType(CallType callType, Object call) {
+bool validCallType(CallType callType, Object call, Selector selector) {
   switch (callType) {
     case CallType.access:
       return call is ir.Node;
+    case CallType.indirectAccess:
+      return call == null && selector.name == '==';
     case CallType.forIn:
       return call is ir.ForInStatement;
   }
@@ -914,7 +944,7 @@
       this.arguments,
       this.inLoop)
       : super.noAssignments(abstractValueDomain.emptyType, context) {
-    assert(_call is ir.Node);
+    assert(_call is ir.Node || (_call == null && selector.name == '=='));
   }
 
   @override
@@ -1011,6 +1041,109 @@
   }
 }
 
+/// A call modeled with a level of indirection.
+///
+/// This kind of call is artificial and only exists to address scalability
+/// limitations of the inference algorithm. Any virtual, interface, or dynamic
+/// call is normally modeled via [DynamicCallSiteTypeInformation]. The main
+/// scalability concern of those calls is that we may get a quadratic number of
+/// edges to model all the argument and return values (an edge per dynamic call
+/// and target pair). Adding a level of indirection helps in that all these
+/// calls are funneled through a single [DynamicCallSiteTypeInformation] node,
+/// this in turn reduces the edges to be linear (an edge per indiret call to the
+/// dynamic call node, and an edge from the call to each target).
+class IndirectDynamicCallSiteTypeInformation extends CallSiteTypeInformation {
+  final DynamicCallSiteTypeInformation dynamicCall;
+  final bool isConditional;
+  final TypeInformation receiver;
+
+  IndirectDynamicCallSiteTypeInformation(
+      AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context,
+      Object call,
+      this.dynamicCall,
+      MemberEntity enclosing,
+      Selector selector,
+      AbstractValue mask,
+      this.receiver,
+      ArgumentsTypes arguments,
+      bool inLoop,
+      this.isConditional)
+      : super(abstractValueDomain, context, call, enclosing, selector, mask,
+            arguments, inLoop);
+
+  @override
+  void addToGraph(InferrerEngine inferrer) {
+    receiver.addUser(this);
+    dynamicCall.receiver.addAssignment(receiver);
+    List<TypeInformation> positional = arguments.positional;
+    for (int i = 0; i < positional.length; i++) {
+      positional[i].addUser(this);
+      dynamicCall.arguments.positional[i].addAssignment(positional[i]);
+    }
+    arguments.named.forEach((name, namedInfo) {
+      dynamicCall.arguments.named[name].addAssignment(namedInfo);
+    });
+    dynamicCall.addUser(this);
+  }
+
+  @override
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValue typeMask = _computeTypedSelector(inferrer);
+    inferrer.updateSelectorInMember(
+        caller, CallType.access, _call, selector, typeMask);
+
+    AbstractValue result = dynamicCall.computeType(inferrer);
+    AbstractValueDomain abstractValueDomain =
+        inferrer.closedWorld.abstractValueDomain;
+    if (isConditional &&
+        abstractValueDomain.isNull(receiver.type).isPotentiallyTrue) {
+      // Conditional calls like `a?.b` may be null if the receiver is null.
+      result = abstractValueDomain.includeNull(result);
+    }
+    return result;
+  }
+
+  AbstractValue _computeTypedSelector(InferrerEngine inferrer) {
+    AbstractValue receiverType = receiver.type;
+    if (mask == receiverType) return mask;
+    return receiverType == inferrer.abstractValueDomain.dynamicType
+        ? null
+        : receiverType;
+  }
+
+  @override
+  void giveUp(InferrerEngine inferrer, {bool clearAssignments: true}) {
+    if (!abandonInferencing) {
+      inferrer.updateSelectorInMember(
+          caller, CallType.access, _call, selector, mask);
+    }
+    super.giveUp(inferrer, clearAssignments: clearAssignments);
+  }
+
+  @override
+  Iterable<MemberEntity> get callees => dynamicCall.callees;
+
+  @override
+  accept(TypeInformationVisitor visitor) {
+    return visitor.visitIndirectDynamicCallSiteTypeInformation(this);
+  }
+
+  @override
+  bool hasStableType(InferrerEngine inferrer) =>
+      dynamicCall.hasStableType(inferrer);
+
+  @override
+  void removeAndClearReferences(InferrerEngine inferrer) {
+    dynamicCall.removeUser(this);
+    receiver.removeUser(this);
+    if (arguments != null) {
+      arguments.forEach((info) => info.removeUser(this));
+    }
+    super.removeAndClearReferences(inferrer);
+  }
+}
+
 class DynamicCallSiteTypeInformation<T> extends CallSiteTypeInformation {
   final CallType _callType;
   final TypeInformation receiver;
@@ -1034,7 +1167,21 @@
       this.isConditional)
       : super(abstractValueDomain, context, call, enclosing, selector, mask,
             arguments, inLoop) {
-    assert(validCallType(_callType, _call));
+    assert(validCallType(_callType, _call, selector));
+  }
+
+  void _addCall(MemberTypeInformation callee) {
+    if (_callType == CallType.indirectAccess) {
+      callee._calledIndirectly = true;
+    } else {
+      callee.addCall(caller, _call);
+    }
+  }
+
+  void _removeCall(MemberTypeInformation callee) {
+    if (_callType != CallType.indirectAccess) {
+      callee.removeCall(caller, _call);
+    }
   }
 
   @override
@@ -1051,7 +1198,7 @@
     for (MemberEntity element in _concreteTargets) {
       MemberTypeInformation callee =
           inferrer.types.getInferredTypeOfMember(element);
-      callee.addCall(caller, _call);
+      _addCall(callee);
       callee.addUser(this);
       inferrer.updateParameterAssignments(
           this, element, arguments, selector, typeMask,
@@ -1072,7 +1219,6 @@
 
   AbstractValue computeTypedSelector(InferrerEngine inferrer) {
     AbstractValue receiverType = receiver.type;
-
     if (mask != receiverType) {
       return receiverType == inferrer.abstractValueDomain.dynamicType
           ? null
@@ -1216,7 +1362,7 @@
           .forEach((MemberEntity element) {
         MemberTypeInformation callee =
             inferrer.types.getInferredTypeOfMember(element);
-        callee.addCall(caller, _call);
+        _addCall(callee);
         callee.addUser(this);
         inferrer.updateParameterAssignments(
             this, element, arguments, selector, typeMask,
@@ -1229,7 +1375,7 @@
           .forEach((MemberEntity element) {
         MemberTypeInformation callee =
             inferrer.types.getInferredTypeOfMember(element);
-        callee.removeCall(caller, _call);
+        _removeCall(callee);
         callee.removeUser(this);
         inferrer.updateParameterAssignments(
             this, element, arguments, selector, typeMask,
@@ -2111,8 +2257,12 @@
   T visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info);
   T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info);
   T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info);
+  T visitIndirectDynamicCallSiteTypeInformation(
+      IndirectDynamicCallSiteTypeInformation info);
   T visitMemberTypeInformation(MemberTypeInformation info);
   T visitParameterTypeInformation(ParameterTypeInformation info);
+  T visitIndirectParameterTypeInformation(
+      IndirectParameterTypeInformation info);
   T visitClosureTypeInformation(ClosureTypeInformation info);
   T visitAwaitTypeInformation(AwaitTypeInformation info);
   T visitYieldTypeInformation(YieldTypeInformation info);
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 3c39f11..0954db8 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -503,7 +503,8 @@
       // instantiated as int and String.
       registerNew(
           node.target,
-          new ir.InterfaceType(node.target.enclosingClass, typeArguments),
+          new ir.InterfaceType(
+              node.target.enclosingClass, ir.Nullability.legacy, typeArguments),
           positionArguments,
           namedArguments,
           node.arguments.types,
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index ea3559b..82402b7 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -311,7 +311,7 @@
   InitializerComplexity visitTypeParameter(ir.TypeParameter typeParameter) {
     ir.TreeNode context = _executableContext;
     TypeVariableTypeWithContext typeVariable = new TypeVariableTypeWithContext(
-        new ir.TypeParameterType(typeParameter),
+        new ir.TypeParameterType(typeParameter, ir.Nullability.legacy),
         // If this typeParameter is part of a typedef then its parent is
         // null because it has no context. Just pass in null for the
         // context in that case.
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index d686190..b54d98c 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -1218,6 +1218,7 @@
       if (streamType != null) {
         iteratorType = new ir.InterfaceType(
             typeEnvironment.coreTypes.streamIteratorClass,
+            ir.Nullability.legacy,
             streamType.typeArguments);
       }
     } else {
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index c544cb0..f8f4999 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -22,7 +22,7 @@
 /// has precision of a this-expression.
 class ThisInterfaceType extends ir.InterfaceType {
   ThisInterfaceType(ir.Class classNode, [List<ir.DartType> typeArguments])
-      : super(classNode, typeArguments);
+      : super(classNode, ir.Nullability.legacy, typeArguments);
 
   factory ThisInterfaceType.from(ir.InterfaceType type) => type != null
       ? new ThisInterfaceType(type.classNode, type.typeArguments)
@@ -36,7 +36,7 @@
 /// is exact, i.e. the runtime type is not a subtype or subclass of the type.
 class ExactInterfaceType extends ir.InterfaceType {
   ExactInterfaceType(ir.Class classNode, [List<ir.DartType> typeArguments])
-      : super(classNode, typeArguments);
+      : super(classNode, ir.Nullability.legacy, typeArguments);
 
   factory ExactInterfaceType.from(ir.InterfaceType type) => type != null
       ? new ExactInterfaceType(type.classNode, type.typeArguments)
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index c797e3b..fd7df4d 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2571,6 +2571,8 @@
         return asName(fixedNames.deferredAction);
       case JsGetName.OPERATOR_AS_PREFIX:
         return asName(fixedNames.operatorAsPrefix);
+      case JsGetName.OPERATOR_IS_PREFIX:
+        return asName(fixedNames.operatorIsPrefix);
       case JsGetName.SIGNATURE_NAME:
         return asName(fixedNames.operatorSignature);
       case JsGetName.RTI_NAME:
diff --git a/pkg/compiler/lib/src/js_backend/specialized_checks.dart b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
index 4aacd02..afb4661 100644
--- a/pkg/compiler/lib/src/js_backend/specialized_checks.dart
+++ b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
@@ -2,11 +2,88 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../common_elements.dart' show JCommonElements;
+import '../common_elements.dart' show ElementEnvironment, JCommonElements;
+import '../deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../js_backend/interceptor_data.dart' show InterceptorData;
+import '../ssa/nodes.dart' show HGraph;
+import '../universe/class_hierarchy.dart' show ClassHierarchy;
+import '../world.dart' show JClosedWorld;
+
+enum IsTestSpecialization {
+  null_,
+  string,
+  bool,
+  num,
+  int,
+  arrayTop,
+  instanceof,
+}
 
 class SpecializedChecks {
+  static IsTestSpecialization findIsTestSpecialization(
+      DartType dartType, HGraph graph, JClosedWorld closedWorld) {
+    if (dartType is InterfaceType) {
+      ClassEntity element = dartType.element;
+      JCommonElements commonElements = closedWorld.commonElements;
+
+      if (element == commonElements.nullClass ||
+          element == commonElements.jsNullClass) {
+        return IsTestSpecialization.null_;
+      }
+
+      if (element == commonElements.jsStringClass ||
+          element == commonElements.stringClass) {
+        return IsTestSpecialization.string;
+      }
+
+      if (element == commonElements.jsBoolClass ||
+          element == commonElements.boolClass) {
+        return IsTestSpecialization.bool;
+      }
+
+      if (element == commonElements.jsDoubleClass ||
+          element == commonElements.doubleClass ||
+          element == commonElements.jsNumberClass ||
+          element == commonElements.numClass) {
+        return IsTestSpecialization.num;
+      }
+
+      if (element == commonElements.jsIntClass ||
+          element == commonElements.intClass ||
+          element == commonElements.jsUInt32Class ||
+          element == commonElements.jsUInt31Class ||
+          element == commonElements.jsPositiveIntClass) {
+        return IsTestSpecialization.int;
+      }
+
+      DartTypes dartTypes = closedWorld.dartTypes;
+      ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+      if (!dartTypes.isSubtype(
+          elementEnvironment.getClassInstantiationToBounds(element),
+          dartType)) {
+        return null;
+      }
+
+      if (element == commonElements.jsArrayClass) {
+        return IsTestSpecialization.arrayTop;
+      }
+
+      ClassHierarchy classHierarchy = closedWorld.classHierarchy;
+      InterceptorData interceptorData = closedWorld.interceptorData;
+      OutputUnitData outputUnitData = closedWorld.outputUnitData;
+
+      if (classHierarchy.hasOnlySubclasses(element) &&
+          !interceptorData.isInterceptedClass(element) &&
+          outputUnitData.hasOnlyNonDeferredImportPathsToClass(
+              graph.element, element)) {
+        return IsTestSpecialization.instanceof;
+      }
+    }
+    return null;
+  }
+
   static MemberEntity findAsCheck(
       DartType dartType, bool isTypeError, JCommonElements commonElements) {
     if (dartType is InterfaceType) {
diff --git a/pkg/compiler/lib/src/js_backend/type_reference.dart b/pkg/compiler/lib/src/js_backend/type_reference.dart
index 2b7f88e..068fe60 100644
--- a/pkg/compiler/lib/src/js_backend/type_reference.dart
+++ b/pkg/compiler/lib/src/js_backend/type_reference.dart
@@ -65,7 +65,6 @@
     show $0, $9, $A, $Z, $_, $a, $z;
 
 import '../common_elements.dart' show CommonElements;
-import '../elements/entities.dart' show FunctionEntity;
 import '../elements/types.dart';
 import '../js/js.dart' as js;
 import '../js_emitter/code_emitter_task.dart' show Emitter;
@@ -261,19 +260,20 @@
   }
 
   void _updateReferences() {
-    js.Expression loadTypeCall(TypeRecipe recipe) {
-      FunctionEntity helperElement = _commonElements.findType;
+    js.Expression helperAccess =
+        _emitter.staticFunctionAccess(_commonElements.findType);
+
+    js.Expression loadTypeCall(TypeRecipe recipe, String helperLocal) {
       js.Expression recipeExpression =
           _recipeEncoder.encodeGroundRecipe(_emitter, recipe);
-      js.Expression helper = _emitter.staticFunctionAccess(helperElement);
-      return js.js(r'#(#)', [helper, recipeExpression]);
+      return js.js(r'#(#)', [helperLocal ?? helperAccess, recipeExpression]);
     }
 
     // Emit generate-at-use references.
     for (_ReferenceSet referenceSet in _referencesByRecipe.values) {
       if (referenceSet.generateAtUse) {
         TypeRecipe recipe = referenceSet.recipe;
-        js.Expression reference = loadTypeCall(recipe);
+        js.Expression reference = loadTypeCall(recipe, null);
         for (TypeReference ref in referenceSet._references) {
           ref.value = reference;
         }
@@ -287,23 +287,43 @@
     // are grouped together.
     referenceSetsUsingProperties.sort((a, b) => a.name.compareTo(b.name));
 
+    // We can generate a literal with calls to H.findType (minified to typically
+    // e.g. H.xy) or cache H.findType in a local in a scope created by an IIFE.
+    // Doing so saves 2-3 bytes per entry, but with an overhead of 30+ bytes for
+    // the IIFE.  So it is smaller to use the IIFE only for over 10 or so types.
+    const minUseIIFE = 10;
+    String helperLocal =
+        referenceSetsUsingProperties.length < minUseIIFE ? null : 'findType';
+
     List<js.Property> properties = [];
     for (_ReferenceSet referenceSet in referenceSetsUsingProperties) {
       TypeRecipe recipe = referenceSet.recipe;
       var propertyName = js.string(referenceSet.propertyName);
-      properties.add(js.Property(propertyName, loadTypeCall(recipe)));
+      properties
+          .add(js.Property(propertyName, loadTypeCall(recipe, helperLocal)));
       var access = js.js('#.#', [typesHolderLocalName, propertyName]);
       for (TypeReference ref in referenceSet._references) {
         ref.value = access;
       }
     }
-    var initializer = js.ObjectInitializer(properties, isOneLiner: false);
 
-    var function = js.js(r'function rtii(){return #}', initializer);
-    _resource.value = js.js(r'var # = #()', [
-      js.VariableDeclaration(typesHolderLocalName),
-      js.Parentheses(function)
-    ]);
+    if (properties.isEmpty) {
+      // We don't have a deferred statement sequence. "0;" is the smallest we
+      // can do with an expression statement.
+      // TODO(sra): Add deferred expression statement sequences.
+      _resource.value = js.js('0');
+    } else {
+      js.Expression initializer =
+          js.ObjectInitializer(properties, isOneLiner: false);
+      if (helperLocal != null) {
+        // A named IIFE helps attribute startup time in profiling.
+        var function = js.js(r'function rtii(){var # = #; return #}',
+            [js.VariableDeclaration(helperLocal), helperAccess, initializer]);
+        initializer = js.js('#()', js.Parentheses(function));
+      }
+      _resource.value = js.js(r'var # = #',
+          [js.VariableDeclaration(typesHolderLocalName), initializer]);
+    }
   }
 
   // This is a top-level local name in the generated JavaScript top-level
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 4c87632..61bb3c7 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -892,6 +892,9 @@
 
   @override
   InterfaceType get rawType => thisType;
+
+  @override
+  InterfaceType get instantiationToBounds => thisType;
 }
 
 /// A container for variables declared in a particular scope that are accessed
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 70d2510a..333b359 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -7,6 +7,8 @@
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/src/bounds_checks.dart' as ir;
+
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
@@ -83,6 +85,7 @@
   DartTypeConverter _typeConverter;
   JsConstantEnvironment _constantEnvironment;
   KernelDartTypes _types;
+  ir.CoreTypes _coreTypes;
   ir.TypeEnvironment _typeEnvironment;
   ir.ClassHierarchy _classHierarchy;
   ConstantValuefier _constantValuefier;
@@ -728,6 +731,20 @@
     }
   }
 
+  void _ensureClassInstantiationToBounds(ClassEntity cls, JClassData data) {
+    assert(checkFamily(cls));
+    if (data is JClassDataImpl && data.instantiationToBounds == null) {
+      ir.Class node = data.cls;
+      if (node.typeParameters.isEmpty) {
+        _ensureThisAndRawType(cls, data);
+        data.instantiationToBounds = data.thisType;
+      } else {
+        data.instantiationToBounds = getInterfaceType(ir.instantiateToBounds(
+            coreTypes.legacyRawType(node), coreTypes.objectClass));
+      }
+    }
+  }
+
   @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
@@ -943,8 +960,8 @@
     if (node.typeParameters.isNotEmpty) {
       List<DartType> typeParameters = <DartType>[];
       for (ir.TypeParameter typeParameter in node.typeParameters) {
-        typeParameters
-            .add(getDartType(new ir.TypeParameterType(typeParameter)));
+        typeParameters.add(getDartType(
+            new ir.TypeParameterType(typeParameter, ir.Nullability.legacy)));
       }
       typeVariables = new List<FunctionTypeVariable>.generate(
           node.typeParameters.length,
@@ -1021,6 +1038,13 @@
     return data.rawType;
   }
 
+  InterfaceType _getClassInstantiationToBounds(IndexedClass cls) {
+    assert(checkFamily(cls));
+    JClassData data = classes.getData(cls);
+    _ensureClassInstantiationToBounds(cls, data);
+    return data.instantiationToBounds;
+  }
+
   FunctionType _getFunctionType(IndexedFunction function) {
     assert(checkFamily(function));
     FunctionData data = members.getData(function);
@@ -1178,20 +1202,14 @@
     return data.imports[node];
   }
 
-  ir.TypeEnvironment get typeEnvironment {
-    if (_typeEnvironment == null) {
-      _typeEnvironment ??= new ir.TypeEnvironment(
-          new ir.CoreTypes(programEnv.mainComponent), classHierarchy);
-    }
-    return _typeEnvironment;
-  }
+  ir.CoreTypes get coreTypes =>
+      _coreTypes ??= ir.CoreTypes(programEnv.mainComponent);
 
-  ir.ClassHierarchy get classHierarchy {
-    if (_classHierarchy == null) {
-      _classHierarchy ??= new ir.ClassHierarchy(programEnv.mainComponent);
-    }
-    return _classHierarchy;
-  }
+  ir.TypeEnvironment get typeEnvironment =>
+      _typeEnvironment ??= ir.TypeEnvironment(coreTypes, classHierarchy);
+
+  ir.ClassHierarchy get classHierarchy =>
+      _classHierarchy ??= ir.ClassHierarchy(programEnv.mainComponent);
 
   @override
   StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
@@ -2212,6 +2230,10 @@
   }
 
   @override
+  InterfaceType getClassInstantiationToBounds(ClassEntity cls) =>
+      elementMap._getClassInstantiationToBounds(cls);
+
+  @override
   bool isGenericClass(ClassEntity cls) {
     return getThisType(cls).typeArguments.isNotEmpty;
   }
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 527a27b..1b92036 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -442,6 +442,7 @@
   InterfaceType get thisType;
   InterfaceType get jsInteropType;
   InterfaceType get rawType;
+  InterfaceType get instantiationToBounds;
   InterfaceType get supertype;
   InterfaceType get mixedInType;
   List<InterfaceType> get interfaces;
@@ -471,6 +472,8 @@
   @override
   InterfaceType rawType;
   @override
+  InterfaceType instantiationToBounds;
+  @override
   InterfaceType supertype;
   @override
   InterfaceType mixedInType;
@@ -609,8 +612,8 @@
         } else {
           _typeVariables = functionNode.typeParameters
               .map<TypeVariableType>((ir.TypeParameter typeParameter) {
-            return elementMap
-                .getDartType(new ir.TypeParameterType(typeParameter));
+            return elementMap.getDartType(
+                new ir.TypeParameterType(typeParameter, ir.Nullability.legacy));
           }).toList();
         }
       }
@@ -759,7 +762,8 @@
   List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
     return typeParameters
         .map<TypeVariableType>((ir.TypeParameter typeParameter) {
-      return elementMap.getDartType(new ir.TypeParameterType(typeParameter));
+      return elementMap.getDartType(
+          new ir.TypeParameterType(typeParameter, ir.Nullability.legacy));
     }).toList();
   }
 
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 9285a64..f0a3770 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
@@ -30,6 +31,9 @@
   /// Access to the [DartTypes] object.
   DartTypes get types;
 
+  /// Returns the core types for the underlying kernel model.
+  ir.CoreTypes get coreTypes;
+
   /// Returns the type environment for the underlying kernel model.
   ir.TypeEnvironment get typeEnvironment;
 
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 66e263e..cb01960 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -9,6 +9,7 @@
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/src/bounds_checks.dart' as ir;
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
@@ -74,6 +75,7 @@
   DartTypeConverter _typeConverter;
   KernelConstantEnvironment _constantEnvironment;
   KernelDartTypes _types;
+  ir.CoreTypes _coreTypes;
   ir.TypeEnvironment _typeEnvironment;
   ir.ClassHierarchy _classHierarchy;
   Dart2jsConstantEvaluator _constantEvaluator;
@@ -299,6 +301,20 @@
     }
   }
 
+  void _ensureClassInstantiationToBounds(ClassEntity cls, KClassData data) {
+    assert(checkFamily(cls));
+    if (data is KClassDataImpl && data.instantiationToBounds == null) {
+      ir.Class node = data.node;
+      if (node.typeParameters.isEmpty) {
+        _ensureThisAndRawType(cls, data);
+        data.instantiationToBounds = data.thisType;
+      } else {
+        data.instantiationToBounds = getInterfaceType(ir.instantiateToBounds(
+            coreTypes.legacyRawType(node), coreTypes.objectClass));
+      }
+    }
+  }
+
   @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
@@ -517,8 +533,8 @@
     if (node.typeParameters.isNotEmpty) {
       List<DartType> typeParameters = <DartType>[];
       for (ir.TypeParameter typeParameter in node.typeParameters) {
-        typeParameters
-            .add(getDartType(new ir.TypeParameterType(typeParameter)));
+        typeParameters.add(getDartType(
+            new ir.TypeParameterType(typeParameter, ir.Nullability.legacy)));
       }
       typeVariables = new List<FunctionTypeVariable>.generate(
           node.typeParameters.length,
@@ -595,6 +611,13 @@
     return data.rawType;
   }
 
+  InterfaceType _getClassInstantiationToBounds(IndexedClass cls) {
+    assert(checkFamily(cls));
+    KClassData data = classes.getData(cls);
+    _ensureClassInstantiationToBounds(cls, data);
+    return data.instantiationToBounds;
+  }
+
   DartType _getFieldType(IndexedField field) {
     assert(checkFamily(field));
     KFieldData data = members.getData(field);
@@ -767,15 +790,15 @@
   }
 
   @override
-  ir.TypeEnvironment get typeEnvironment {
-    return _typeEnvironment ??= new ir.TypeEnvironment(
-        new ir.CoreTypes(env.mainComponent), classHierarchy);
-  }
+  ir.CoreTypes get coreTypes => _coreTypes ??= ir.CoreTypes(env.mainComponent);
 
   @override
-  ir.ClassHierarchy get classHierarchy {
-    return _classHierarchy ??= new ir.ClassHierarchy(env.mainComponent);
-  }
+  ir.TypeEnvironment get typeEnvironment =>
+      _typeEnvironment ??= ir.TypeEnvironment(coreTypes, classHierarchy);
+
+  @override
+  ir.ClassHierarchy get classHierarchy =>
+      _classHierarchy ??= ir.ClassHierarchy(env.mainComponent);
 
   Dart2jsConstantEvaluator get constantEvaluator {
     return _constantEvaluator ??= new Dart2jsConstantEvaluator(typeEnvironment,
@@ -1678,6 +1701,10 @@
   }
 
   @override
+  InterfaceType getClassInstantiationToBounds(ClassEntity cls) =>
+      elementMap._getClassInstantiationToBounds(cls);
+
+  @override
   bool isGenericClass(ClassEntity cls) {
     return getThisType(cls).typeArguments.isNotEmpty;
   }
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 8dd1973..077aa0a 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -614,6 +614,7 @@
   InterfaceType get thisType;
   InterfaceType get jsInteropType;
   InterfaceType get rawType;
+  InterfaceType get instantiationToBounds;
   InterfaceType get supertype;
   InterfaceType get mixedInType;
   List<InterfaceType> get interfaces;
@@ -643,6 +644,8 @@
   @override
   InterfaceType rawType;
   @override
+  InterfaceType instantiationToBounds;
+  @override
   InterfaceType supertype;
   @override
   InterfaceType mixedInType;
@@ -744,8 +747,8 @@
         } else {
           _typeVariables = functionNode.typeParameters
               .map<TypeVariableType>((ir.TypeParameter typeParameter) {
-            return elementMap
-                .getDartType(new ir.TypeParameterType(typeParameter));
+            return elementMap.getDartType(
+                new ir.TypeParameterType(typeParameter, ir.Nullability.legacy));
           }).toList();
         }
       }
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 63ac858..c98787d 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -271,13 +271,14 @@
       case DartTypeNodeKind.typeParameterType:
         ir.TypeParameter typeParameter = readTypeParameterNode();
         ir.DartType promotedBound = _readDartTypeNode(functionTypeVariables);
-        return new ir.TypeParameterType(typeParameter, promotedBound);
+        return new ir.TypeParameterType(
+            typeParameter, ir.Nullability.legacy, promotedBound);
       case DartTypeNodeKind.functionTypeVariable:
         int index = readInt();
         assert(0 <= index && index < functionTypeVariables.length);
         ir.DartType promotedBound = _readDartTypeNode(functionTypeVariables);
         return new ir.TypeParameterType(
-            functionTypeVariables[index], promotedBound);
+            functionTypeVariables[index], ir.Nullability.legacy, promotedBound);
       case DartTypeNodeKind.functionType:
         begin(functionTypeNodeTag);
         int typeParameterCount = readInt();
@@ -308,7 +309,8 @@
         }
         ir.TypedefType typedefType = _readDartTypeNode(functionTypeVariables);
         end(functionTypeNodeTag);
-        return new ir.FunctionType(positionalParameters, returnType,
+        return new ir.FunctionType(
+            positionalParameters, returnType, ir.Nullability.legacy,
             namedParameters: namedParameters,
             typeParameters: typeParameters,
             requiredParameterCount: requiredParameterCount,
@@ -318,7 +320,7 @@
         ir.Class cls = readClassNode();
         List<ir.DartType> typeArguments =
             _readDartTypeNodes(functionTypeVariables);
-        return new ir.InterfaceType(cls, typeArguments);
+        return new ir.InterfaceType(cls, ir.Nullability.legacy, typeArguments);
       case DartTypeNodeKind.thisInterfaceType:
         ir.Class cls = readClassNode();
         List<ir.DartType> typeArguments =
@@ -333,7 +335,8 @@
         ir.Typedef typedef = readTypedefNode();
         List<ir.DartType> typeArguments =
             _readDartTypeNodes(functionTypeVariables);
-        return new ir.TypedefType(typedef, typeArguments);
+        return new ir.TypedefType(
+            typedef, ir.Nullability.legacy, typeArguments);
       case DartTypeNodeKind.dynamicType:
         return const ir.DynamicType();
     }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 00f98df..0688ba9 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1484,7 +1484,8 @@
       ir.FunctionNode function = getFunctionNode(_elementMap, method);
       for (ir.TypeParameter typeParameter in function.typeParameters) {
         Local local = _localsMap.getLocalTypeVariable(
-            new ir.TypeParameterType(typeParameter), _elementMap);
+            new ir.TypeParameterType(typeParameter, ir.Nullability.legacy),
+            _elementMap);
         HInstruction newParameter = localsHandler.directLocals[local];
         DartType bound = _getDartTypeIfValid(typeParameter.bound);
         if (!bound.isDynamic &&
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 7779388..ee72ee8 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -29,6 +29,7 @@
 import '../js_backend/runtime_types_codegen.dart';
 import '../js_backend/runtime_types_new.dart'
     show RecipeEncoder, RecipeEncoding, indexTypeVariable;
+import '../js_backend/specialized_checks.dart' show IsTestSpecialization;
 import '../js_backend/type_reference.dart' show TypeReference;
 import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
 import '../js_model/elements.dart' show JGeneratorBody;
@@ -2435,6 +2436,8 @@
         emitIs(input, '!==', sourceInformation);
       } else if (input is HIsViaInterceptor) {
         emitIsViaInterceptor(input, sourceInformation, negative: true);
+      } else if (input is HIsTestSimple) {
+        _emitIsTestSimple(input, negative: true);
       } else if (input is HNot) {
         use(input.inputs[0]);
       } else if (input is HIdentity) {
@@ -3367,6 +3370,66 @@
   }
 
   @override
+  visitIsTestSimple(HIsTestSimple node) {
+    _emitIsTestSimple(node);
+  }
+
+  _emitIsTestSimple(HIsTestSimple node, {bool negative: false}) {
+    use(node.checkedInput);
+    js.Expression value = pop();
+    String relation = negative ? '!=' : '==';
+
+    js.Expression handleNegative(js.Expression test) =>
+        negative ? js.Prefix('!', test) : test;
+
+    js.Expression typeof(String type) =>
+        js.Binary(relation, js.Prefix('typeof', value), js.string(type));
+
+    js.Expression isTest(MemberEntity helper) {
+      _registry.registerStaticUse(
+          StaticUse.staticInvoke(helper, CallStructure.ONE_ARG));
+      js.Expression test =
+          js.Call(_emitter.staticFunctionAccess(helper), [value]);
+      return handleNegative(test);
+    }
+
+    js.Expression test;
+    switch (node.specialization) {
+      case IsTestSpecialization.null_:
+        // This case should be lowered to [HIdentity] during optimization.
+        test = js.Binary(relation, value, js.LiteralNull());
+        break;
+
+      case IsTestSpecialization.string:
+        test = typeof("string");
+        break;
+
+      case IsTestSpecialization.bool:
+        test = isTest(_commonElements.specializedIsBool);
+        break;
+
+      case IsTestSpecialization.num:
+        test = typeof("number");
+        break;
+
+      case IsTestSpecialization.int:
+        test = isTest(_commonElements.specializedIsInt);
+        break;
+
+      case IsTestSpecialization.arrayTop:
+        test = handleNegative(js.js('Array.isArray(#)', [value]));
+        break;
+
+      case IsTestSpecialization.instanceof:
+        InterfaceType type = node.dartType;
+        _registry.registerTypeUse(TypeUse.instanceConstructor(type));
+        test = handleNegative(js.js('# instanceof #',
+            [value, _emitter.constructorAccess(type.element)]));
+    }
+    push(test.withSourceInformation(node.sourceInformation));
+  }
+
+  @override
   visitAsCheck(HAsCheck node) {
     use(node.typeInput);
     js.Expression first = pop();
@@ -3429,7 +3492,7 @@
     }
 
     // Try to use the 'rti' field, or a specialization of 'instanceType'.
-    AbstractValue receiverMask = input.instructionType;
+    AbstractValue receiverMask = node.codegenInputType;
 
     AbstractBool isArray = _abstractValueDomain.isInstanceOf(
         receiverMask, _commonElements.jsArrayClass);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index d028d7a..a3c4af4 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -366,36 +366,36 @@
   }
 }
 
-/// Remove [HTypeKnown] instructions from the graph, to make codegen
-/// analysis easier.
+/// Remove [HTypeKnown] instructions from the graph, to make codegen analysis
+/// easier.
 class SsaTypeKnownRemover extends HBaseVisitor with CodegenPhase {
   @override
   void visitGraph(HGraph graph) {
-    visitDominatorTree(graph);
+    // Visit bottom-up to visit uses before instructions and capture refined
+    // input types.
+    visitPostDominatorTree(graph);
   }
 
   @override
   void visitBasicBlock(HBasicBlock block) {
-    HInstruction instruction = block.first;
+    HInstruction instruction = block.last;
     while (instruction != null) {
-      HInstruction next = instruction.next;
+      HInstruction previous = instruction.previous;
       instruction.accept(this);
-      instruction = next;
+      instruction = previous;
     }
   }
 
   @override
   void visitTypeKnown(HTypeKnown instruction) {
-    for (HInstruction user in instruction.usedBy) {
-      if (user is HTypeConversion) {
-        user.inputType = instruction.instructionType;
-      } else if (user is HPrimitiveCheck) {
-        user.inputType = instruction.instructionType;
-      }
-    }
     instruction.block.rewrite(instruction, instruction.checkedInput);
     instruction.block.remove(instruction);
   }
+
+  @override
+  void visitInstanceEnvironment(HInstanceEnvironment instruction) {
+    instruction.codegenInputType = instruction.inputs.single.instructionType;
+  }
 }
 
 /// Remove [HPrimitiveCheck] instructions from the graph in '--trust-primitives'
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 783485b..90297a2 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -6,6 +6,7 @@
 
 import '../closure.dart';
 import '../common.dart';
+import '../common_elements.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
 import '../elements/entities.dart';
@@ -14,6 +15,7 @@
 import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
+import '../js_backend/specialized_checks.dart' show IsTestSpecialization;
 import '../js_model/type_recipe.dart'
     show TypeEnvironmentStructure, TypeRecipe, TypeExpressionRecipe;
 import '../native/behavior.dart';
@@ -108,6 +110,7 @@
 
   // Instructions for 'dart:_rti'.
   R visitIsTest(HIsTest node);
+  R visitIsTestSimple(HIsTestSimple node);
   R visitAsCheck(HAsCheck node);
   R visitAsCheckSimple(HAsCheckSimple node);
   R visitSubtypeCheck(HSubtypeCheck node);
@@ -215,8 +218,7 @@
 }
 
 class HGraph {
-  // TODO(johnniwinther): Maybe this should be [MemberLike].
-  Entity element; // Used for debug printing.
+  MemberEntity element; // Used for debug printing.
   HBasicBlock entry;
   HBasicBlock exit;
   HThis thisInstruction;
@@ -604,6 +606,8 @@
   @override
   visitIsTest(HIsTest node) => visitInstruction(node);
   @override
+  visitIsTestSimple(HIsTestSimple node) => visitInstruction(node);
+  @override
   visitAsCheck(HAsCheck node) => visitCheck(node);
   @override
   visitAsCheckSimple(HAsCheckSimple node) => visitCheck(node);
@@ -1096,13 +1100,14 @@
   static const int PRIMITIVE_CHECK_TYPECODE = 46;
 
   static const int IS_TEST_TYPECODE = 47;
-  static const int AS_CHECK_TYPECODE = 48;
-  static const int AS_CHECK_SIMPLE_TYPECODE = 49;
-  static const int SUBTYPE_CHECK_TYPECODE = 50;
-  static const int LOAD_TYPE_TYPECODE = 51;
-  static const int INSTANCE_ENVIRONMENT_TYPECODE = 52;
-  static const int TYPE_EVAL_TYPECODE = 53;
-  static const int TYPE_BIND_TYPECODE = 54;
+  static const int IS_TEST_SIMPLE_TYPECODE = 48;
+  static const int AS_CHECK_TYPECODE = 49;
+  static const int AS_CHECK_SIMPLE_TYPECODE = 50;
+  static const int SUBTYPE_CHECK_TYPECODE = 51;
+  static const int LOAD_TYPE_TYPECODE = 52;
+  static const int INSTANCE_ENVIRONMENT_TYPECODE = 53;
+  static const int TYPE_EVAL_TYPECODE = 54;
+  static const int TYPE_BIND_TYPECODE = 55;
 
   HInstruction(this.inputs, this.instructionType)
       : id = idCounter++,
@@ -3544,8 +3549,6 @@
   final int kind;
 
   AbstractValue checkedType; // Not final because we refine it.
-  AbstractValue
-      inputType; // Holds input type for codegen after HTypeKnown removal.
 
   HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
       HInstruction input, SourceInformation sourceInformation)
@@ -3677,8 +3680,6 @@
   final Selector receiverTypeCheckSelector;
 
   AbstractValue checkedType; // Not final because we refine it.
-  AbstractValue
-      inputType; // Holds input type for codegen after HTypeKnown removal.
 
   HPrimitiveCheck(this.typeExpression, this.kind, AbstractValue type,
       HInstruction input, SourceInformation sourceInformation,
@@ -4367,6 +4368,9 @@
   HInstruction get typeInput => inputs[0];
   HInstruction get checkedInput => inputs[1];
 
+  AbstractBool evaluate(JClosedWorld closedWorld) =>
+      _isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);
+
   @override
   accept(HVisitor visitor) => visitor.visitIsTest(this);
 
@@ -4383,6 +4387,109 @@
   String toString() => 'HIsTest()';
 }
 
+/// Simple is-test for a known type that can be achieved without reference to an
+/// Rti describing the type.
+class HIsTestSimple extends HInstruction {
+  final DartType dartType;
+  final AbstractValueWithPrecision checkedAbstractValue;
+  final IsTestSpecialization specialization;
+
+  HIsTestSimple(this.dartType, this.checkedAbstractValue, this.specialization,
+      HInstruction checked, AbstractValue type)
+      : super([checked], type) {
+    setUseGvn();
+  }
+
+  HInstruction get checkedInput => inputs[0];
+
+  AbstractBool evaluate(JClosedWorld closedWorld) =>
+      _isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);
+
+  @override
+  accept(HVisitor visitor) => visitor.visitIsTestSimple(this);
+
+  @override
+  int typeCode() => HInstruction.IS_TEST_SIMPLE_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HIsTestSimple;
+
+  @override
+  bool dataEquals(HIsTestSimple other) => dartType == other.dartType;
+
+  @override
+  String toString() => 'HIsTestSimple()';
+}
+
+AbstractBool _isTestResult(HInstruction expression, DartType dartType,
+    AbstractValueWithPrecision checkedAbstractValue, JClosedWorld closedWorld) {
+  AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+  AbstractValue subsetType = expression.instructionType;
+  AbstractValue supersetType = checkedAbstractValue.abstractValue;
+  if (checkedAbstractValue.isPrecise &&
+      abstractValueDomain.isIn(subsetType, supersetType).isDefinitelyTrue) {
+    return AbstractBool.True;
+  }
+
+  // TODO(39287): Let the abstract value domain fully handle this.
+  // Currently, the abstract value domain cannot (soundly) state that an is-test
+  // is definitely false, so we reuse some of the case-by-case logic from the
+  // old [HIs] optimization.
+  if (dartType.isTop) return AbstractBool.True;
+  if (dartType is! InterfaceType) return AbstractBool.Maybe;
+  InterfaceType type = dartType;
+  ClassEntity element = type.element;
+  if (type.typeArguments.isNotEmpty) return AbstractBool.Maybe;
+  JCommonElements commonElements = closedWorld.commonElements;
+  if (expression.isInteger(abstractValueDomain).isDefinitelyTrue) {
+    if (element == commonElements.intClass ||
+        element == commonElements.numClass ||
+        commonElements.isNumberOrStringSupertype(element)) {
+      return AbstractBool.True;
+    }
+    if (element == commonElements.doubleClass) {
+      // We let the JS semantics decide for that check. Currently the code we
+      // emit will always return true.
+      return AbstractBool.Maybe;
+    }
+    return AbstractBool.False;
+  }
+  if (expression.isDouble(abstractValueDomain).isDefinitelyTrue) {
+    if (element == commonElements.doubleClass ||
+        element == commonElements.numClass ||
+        commonElements.isNumberOrStringSupertype(element)) {
+      return AbstractBool.True;
+    }
+    if (element == commonElements.intClass) {
+      // We let the JS semantics decide for that check. Currently the code we
+      // emit will return true for a double that can be represented as a 31-bit
+      // integer and for -0.0.
+      return AbstractBool.Maybe;
+    }
+    return AbstractBool.False;
+  }
+  if (expression.isNumber(abstractValueDomain).isDefinitelyTrue) {
+    if (element == commonElements.numClass) {
+      return AbstractBool.True;
+    }
+    // We cannot just return false, because the expression may be of type int or
+    // double.
+    return AbstractBool.Maybe;
+  }
+  if (expression.isPrimitiveNumber(abstractValueDomain).isPotentiallyTrue &&
+      element == commonElements.intClass) {
+    // We let the JS semantics decide for that check.
+    return AbstractBool.Maybe;
+  }
+  // We need the raw check because we don't have the notion of generics in the
+  // backend. For example, `this` in a class `A<T>` is currently always
+  // considered to have the raw type.
+  if (type.treatAsRaw) {
+    return abstractValueDomain.isInstanceOf(subsetType, element);
+  }
+  return AbstractBool.Maybe;
+}
+
 /// Type cast or type check using Rti form of type expression.
 class HAsCheck extends HCheck {
   final AbstractValueWithPrecision checkedType;
@@ -4482,7 +4589,7 @@
   @override
   String toString() {
     String error = isTypeError ? 'TypeError' : 'CastError';
-    return 'HAsCheck($error)';
+    return 'HAsCheckSimple($error)';
   }
 }
 
@@ -4554,6 +4661,8 @@
 /// instance. The reified environment is typically stored as the instance type,
 /// e.g. "UnmodifiableListView<int>".
 class HInstanceEnvironment extends HRtiInstruction {
+  AbstractValue codegenInputType; // Assigned in SsaTypeKnownRemover
+
   HInstanceEnvironment(HInstruction instance, AbstractValue type)
       : super([instance], type) {
     setUseGvn();
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index d28f385..2f69165 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -2027,7 +2027,7 @@
         return HAsCheckSimple(node.checkedInput, dartType, checkedType,
             node.isTypeError, specializedCheck, node.instructionType);
       }
-      if (dartType is DynamicType) {
+      if (dartType.isTop) {
         return node.checkedInput;
       }
     }
@@ -2042,22 +2042,59 @@
 
   @override
   HInstruction visitIsTest(HIsTest node) {
-    AbstractValueWithPrecision checkedAbstractValue = node.checkedAbstractValue;
-    HInstruction checkedInput = node.checkedInput;
-    AbstractValue inputType = checkedInput.instructionType;
-
-    AbstractBool isIn = _abstractValueDomain.isIn(
-        inputType, checkedAbstractValue.abstractValue);
-
-    if (isIn.isDefinitelyFalse) {
+    AbstractBool result = node.evaluate(_closedWorld);
+    if (result.isDefinitelyFalse) {
       return _graph.addConstantBool(false, _closedWorld);
     }
-    if (!checkedAbstractValue.isPrecise) return node;
-
-    if (isIn.isDefinitelyTrue) {
+    if (result.isDefinitelyTrue) {
       return _graph.addConstantBool(true, _closedWorld);
     }
 
+    HInstruction typeInput = node.typeInput;
+    if (typeInput is HLoadType) {
+      TypeExpressionRecipe recipe = typeInput.typeExpression;
+      DartType dartType = recipe.type;
+      if (dartType.isTop) {
+        return _graph.addConstantBool(true, _closedWorld);
+      }
+
+      IsTestSpecialization specialization =
+          SpecializedChecks.findIsTestSpecialization(
+              dartType, _graph, _closedWorld);
+
+      if (specialization == IsTestSpecialization.null_) {
+        return HIdentity(
+            node.checkedInput,
+            _graph.addConstantNull(_closedWorld),
+            null,
+            _abstractValueDomain.boolType);
+      }
+
+      if (specialization != null) {
+        AbstractValueWithPrecision checkedType =
+            _abstractValueDomain.createFromStaticType(dartType,
+                nullable: _abstractValueDomain
+                    .isNull(node.checkedAbstractValue.abstractValue)
+                    .isPotentiallyTrue);
+        return HIsTestSimple(dartType, checkedType, specialization,
+            node.checkedInput, _abstractValueDomain.boolType);
+      }
+    }
+
+    // TODO(fishythefish): Prune now-unneeded is-tests from the metadata.
+
+    return node;
+  }
+
+  @override
+  HInstruction visitIsTestSimple(HIsTestSimple node) {
+    AbstractBool result = node.evaluate(_closedWorld);
+    if (result.isDefinitelyFalse) {
+      return _graph.addConstantBool(false, _closedWorld);
+    }
+    if (result.isDefinitelyTrue) {
+      return _graph.addConstantBool(true, _closedWorld);
+    }
     return node;
   }
 
@@ -3166,6 +3203,27 @@
   }
 
   @override
+  void visitIsTestSimple(HIsTestSimple instruction) {
+    List<HBasicBlock> trueTargets = [];
+    List<HBasicBlock> falseTargets = [];
+
+    collectTargets(instruction, trueTargets, falseTargets);
+
+    if (trueTargets.isEmpty && falseTargets.isEmpty) return;
+
+    AbstractValue convertedType =
+        instruction.checkedAbstractValue.abstractValue;
+    HInstruction input = instruction.checkedInput;
+
+    for (HBasicBlock block in trueTargets) {
+      insertTypePropagationForDominatedUsers(block, input, convertedType);
+    }
+    // TODO(sra): Also strengthen uses for when the condition is precise and
+    // known false (e.g. int? x; ... if (x is! int) use(x)). Avoid strengthening
+    // to `null`.
+  }
+
+  @override
   void visitIdentity(HIdentity instruction) {
     // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch.
     HInstruction left = instruction.left;
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 72086bf..9108a15 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -681,6 +681,12 @@
   }
 
   @override
+  String visitIsTestSimple(HIsTestSimple node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "IsTestSimple: ${node.dartType} $inputs";
+  }
+
+  @override
   String visitAsCheck(HAsCheck node) {
     var inputs = node.inputs.map(temporaryId).join(', ');
     String error = node.isTypeError ? 'TypeError' : 'CastError';
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index ee93476..807a1ef 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -128,13 +128,21 @@
     if (options.pedanticFixes) {
       params.includePedanticFixes = true;
     }
-    String dir = options.outputDir;
-    if (dir != null) {
-      if (!path.isAbsolute(dir)) {
-        dir = path.absolute(dir);
+    String previewDir = options.previewDir;
+    if (previewDir != null) {
+      if (!path.isAbsolute(previewDir)) {
+        previewDir = path.absolute(previewDir);
       }
-      dir = path.canonicalize(dir);
-      params.outputDir = dir;
+      previewDir = path.canonicalize(previewDir);
+      params.outputDir = previewDir;
+    }
+    String previewPort = options.previewPort;
+    if (previewPort != null) {
+      try {
+        params.port = int.parse(previewPort);
+      } on FormatException {
+        logger.stderr('Invalid port number: ignored');
+      }
     }
     Map<String, dynamic> json =
         await server.send(EDIT_REQUEST_DARTFIX, params.toJson());
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index 32e9b91..9b645c0 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -9,13 +9,16 @@
 import 'package:dartfix/src/context.dart';
 import 'package:path/path.dart' as path;
 
+// TODO(brianwilkerson) Deprecate 'excludeFix' and replace it with 'exclude-fix'
 const excludeFixOption = 'excludeFix';
 const forceOption = 'force';
 const includeFixOption = 'fix';
-const outputDirOption = 'outputDir';
 const overwriteOption = 'overwrite';
 const pedanticOption = 'pedantic';
+const previewDirOption = 'preview-dir';
+const previewPortOption = 'preview-port';
 const requiredOption = 'required';
+const sdkOption = 'sdk';
 
 const _binaryName = 'dartfix';
 const _colorOption = 'color';
@@ -41,8 +44,9 @@
 
   final bool force;
   final bool showHelp;
-  final String outputDir;
   final bool overwrite;
+  final String previewDir;
+  final String previewPort;
   final bool useColor;
   final bool verbose;
 
@@ -50,11 +54,12 @@
       : force = results[forceOption] as bool,
         includeFixes = (results[includeFixOption] as List ?? []).cast<String>(),
         excludeFixes = (results[excludeFixOption] as List ?? []).cast<String>(),
-        outputDir = results[outputDirOption] as String,
         overwrite = results[overwriteOption] as bool,
         pedanticFixes = results[pedanticOption] as bool,
+        previewDir = results[previewDirOption] as String,
+        previewPort = results[previewPortOption] as String,
         requiredFixes = results[requiredOption] as bool,
-        sdkPath = _getSdkPath(),
+        sdkPath = results[sdkOption] as String ?? _getSdkPath(),
         serverSnapshot = results[_serverSnapshot] as String,
         showHelp = results[_helpOption] as bool || results.arguments.isEmpty,
         targets = results.rest,
@@ -98,6 +103,10 @@
           help: 'Display this help message.',
           defaultsTo: false,
           negatable: false)
+      ..addOption(sdkOption,
+          help: 'Path to the SDK to analyze against.',
+          valueHelp: 'path',
+          hide: true)
       ..addOption(_serverSnapshot,
           help: 'Path to the analysis server snapshot file.',
           valueHelp: 'path',
@@ -113,8 +122,10 @@
       //
       // Hidden options.
       //
-      ..addOption(outputDirOption,
-          help: 'Path to the output directory', hide: true);
+      ..addOption(previewDirOption,
+          help: 'Path to the preview directory', hide: true)
+      ..addOption(previewPortOption,
+          help: 'The port used by the preview tool', hide: true);
 
     context ??= Context();
 
diff --git a/pkg/dartfix/test/all.dart b/pkg/dartfix/test/all.dart
deleted file mode 100644
index f06cf57..0000000
--- a/pkg/dartfix/test/all.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-import 'src/client_version_test.dart' as client_version_test;
-import 'src/driver_exclude_test.dart' as driver_exclude_test;
-import 'src/driver_help_test.dart' as driver_list_test;
-import 'src/driver_include_test.dart' as driver_include_test;
-import 'src/driver_required_test.dart' as driver_required_test;
-import 'src/driver_test.dart' as driver_test;
-import 'src/options_test.dart' as options_test;
-
-main() {
-  client_version_test.main();
-  group('driver', driver_exclude_test.main);
-  group('driver', driver_include_test.main);
-  group('driver', driver_list_test.main);
-  group('driver', driver_required_test.main);
-  group('driver', driver_test.main);
-  group('options', options_test.main);
-}
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
index beb90d0..9848954 100644
--- a/pkg/dartfix/test/src/options_test.dart
+++ b/pkg/dartfix/test/src/options_test.dart
@@ -29,8 +29,9 @@
     bool showHelp = false,
     String normalOut,
     bool pedanticFixes = false,
+    String previewDir,
+    String previewPort,
     bool requiredFixes = false,
-    String outputDir,
     bool overwrite = false,
     String serverSnapshot,
     List<String> targetSuffixes,
@@ -55,8 +56,9 @@
     }
     expect(options.force, force);
     expect(options.pedanticFixes, pedanticFixes);
+    expect(options.previewDir, previewDir);
+    expect(options.previewPort, previewPort);
     expect(options.requiredFixes, requiredFixes);
-    expect(options.outputDir, outputDir);
     expect(options.overwrite, overwrite);
     expect(options.serverSnapshot, serverSnapshot);
     expect(options.showHelp, showHelp);
@@ -117,10 +119,6 @@
         errorOut: 'Expected directory, but found', exitCode: 21);
   });
 
-  test('outputDir', () {
-    parse(['--outputDir=bar', 'foo'], outputDir: 'bar');
-  });
-
   test('overwrite', () {
     parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
   });
@@ -129,6 +127,14 @@
     parse(['--pedantic', 'foo'], pedanticFixes: true);
   });
 
+  test('previewDir', () {
+    parse(['--preview-dir=bar', 'foo'], previewDir: 'bar');
+  });
+
+  test('previewPort', () {
+    parse(['--preview-port=8080', 'foo'], previewPort: '8080');
+  });
+
   test('required fixes', () {
     parse(['--required', 'foo'], requiredFixes: true);
   });
diff --git a/pkg/dartfix/test/test_all.dart b/pkg/dartfix/test/test_all.dart
new file mode 100644
index 0000000..5b2a0f6
--- /dev/null
+++ b/pkg/dartfix/test/test_all.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'src/client_version_test.dart' as client_version;
+import 'src/driver_example_test.dart' as driver_example;
+import 'src/driver_exclude_test.dart' as driver_exclude;
+import 'src/driver_help_test.dart' as driver_help;
+import 'src/driver_include_test.dart' as driver_include;
+import 'src/driver_pedantic_test.dart' as driver_pedantic;
+import 'src/driver_prefer_is_empty_test.dart' as driver_prefer_is_empty;
+import 'src/driver_required_test.dart' as driver_required;
+import 'src/driver_test.dart' as driver;
+import 'src/options_test.dart' as options_test;
+
+main() {
+  group('version', client_version.main);
+  group('driver', driver_example.main);
+  group('driver', driver_exclude.main);
+  group('driver', driver_help.main);
+  group('driver', driver_include.main);
+  group('driver', driver_pedantic.main);
+  group('driver', driver_prefer_is_empty.main);
+  group('driver', driver_required.main);
+  group('driver', driver.main);
+  group('options', options_test.main);
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 075aaae..75ce561 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -133,12 +133,12 @@
   final ClassElement functionClass;
   final ClassElement internalSymbolClass;
   final ClassElement privateSymbolClass;
-  final InterfaceType linkedHashMapImplType;
-  final InterfaceType identityHashMapImplType;
-  final InterfaceType linkedHashSetImplType;
-  final InterfaceType identityHashSetImplType;
-  final InterfaceType syncIterableType;
-  final InterfaceType asyncStarImplType;
+  final ClassElement linkedHashMapImplElement;
+  final ClassElement identityHashMapImplElement;
+  final ClassElement linkedHashSetImplElement;
+  final ClassElement identityHashSetImplElement;
+  final ClassElement syncIterableElement;
+  final ClassElement asyncStarImplElement;
 
   ConstFieldVisitor _constants;
 
@@ -218,18 +218,17 @@
         internalSymbolClass = driver.getClass('dart:_internal', 'Symbol'),
         privateSymbolClass =
             driver.getClass('dart:_js_helper', 'PrivateSymbol'),
-        linkedHashMapImplType = getLegacyRawClassType(
-            driver.getClass('dart:_js_helper', 'LinkedMap')),
-        identityHashMapImplType = getLegacyRawClassType(
-            driver.getClass('dart:_js_helper', 'IdentityMap')),
-        linkedHashSetImplType = getLegacyRawClassType(
-            driver.getClass('dart:collection', '_HashSet')),
-        identityHashSetImplType = getLegacyRawClassType(
-            driver.getClass('dart:collection', '_IdentityHashSet')),
-        syncIterableType = getLegacyRawClassType(
-            driver.getClass('dart:_js_helper', 'SyncIterable')),
-        asyncStarImplType = getLegacyRawClassType(
-            driver.getClass('dart:async', '_AsyncStarImpl')),
+        linkedHashMapImplElement =
+            driver.getClass('dart:_js_helper', 'LinkedMap'),
+        identityHashMapImplElement =
+            driver.getClass('dart:_js_helper', 'IdentityMap'),
+        linkedHashSetImplElement =
+            driver.getClass('dart:collection', '_HashSet'),
+        identityHashSetImplElement =
+            driver.getClass('dart:collection', '_IdentityHashSet'),
+        syncIterableElement =
+            driver.getClass('dart:_js_helper', 'SyncIterable'),
+        asyncStarImplElement = driver.getClass('dart:async', '_AsyncStarImpl'),
         dartJSLibrary = driver.getLibrary('dart:js') {
     jsTypeRep = JSTypeRep(rules, driver);
   }
@@ -881,131 +880,53 @@
       if (prop != null) markSubtypeOf(prop);
     }
 
-    if (classElem.library.isDartCore) {
-      if (classElem == objectClass) {
-        // Everything is an Object.
-        body.add(js.statement(
-            '#.is = function is_Object(o) { return true; }', [className]));
-        body.add(js.statement(
-            '#.as = function as_Object(o) { return o; }', [className]));
-        body.add(js.statement(
-            '#._check = function check_Object(o) { return o; }', [className]));
-        return null;
-      }
-      if (classElem == stringClass) {
-        body.add(js.statement(
-            '#.is = function is_String(o) { return typeof o == "string"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_String(o) {'
-            '  if (typeof o == "string" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_String(o) {'
-            '  if (typeof o == "string" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (classElem == functionClass) {
-        body.add(js.statement(
-            '#.is = function is_Function(o) { return typeof o == "function"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_Function(o) {'
-            '  if (typeof o == "function" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_Function(o) {'
-            '  if (typeof o == "function" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (classElem == intClass) {
-        body.add(js.statement(
-            '#.is = function is_int(o) {'
-            '  return typeof o == "number" && Math.floor(o) == o;'
-            '}',
-            className));
-        body.add(js.statement(
-            '#.as = function as_int(o) {'
-            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
-            '    return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_int(o) {'
-            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
-            '    return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (classElem == nullClass) {
-        body.add(js.statement(
-            '#.is = function is_Null(o) { return o == null; }', className));
-        body.add(js.statement(
-            '#.as = function as_Null(o) {'
-            '  if (o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_Null(o) {'
-            '  if (o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (classElem == numClass || classElem == doubleClass) {
-        body.add(js.statement(
-            '#.is = function is_num(o) { return typeof o == "number"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_num(o) {'
-            '  if (typeof o == "number" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_num(o) {'
-            '  if (typeof o == "number" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (classElem == boolClass) {
-        body.add(js.statement(
-            '#.is = function is_bool(o) { return o === true || o === false; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_bool(o) {'
-            '  if (o === true || o === false || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_bool(o) {'
-            '  if (o === true || o === false || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
+    if (classElem.library.isDartCore &&
+        (classElem == objectClass ||
+            classElem == stringClass ||
+            classElem == functionClass ||
+            classElem == intClass ||
+            classElem == nullClass ||
+            classElem == numClass ||
+            classElem == doubleClass ||
+            classElem == boolClass)) {
+      // Custom type tests for these types are in the patch files.
+      return null;
     }
-    if (classElem.library.isDartAsync) {
-      if (classElem == types.futureOrElement) {
+    if (classElem.library.isDartAsync && classElem == types.futureOrElement) {
+      // These methods are difficult to place in the runtime or patch files.
+      // * They need to be callable from the class but they can't be static
+      //   methods on the FutureOr class in Dart because they reference the
+      //   generic type parameter.
+      // * There isn't an obvious place in dart:_runtime were we could place a
+      //   method that adds these type tests (similar to addTypeTests()) because
+      //   in the bootstrap ordering the Future class hasn't been defined yet.
+      if (options.nonNullableEnabled) {
+        // TODO(nshahan) Update FutureOr type tests for NNBD.
+        var typeParamT =
+            getLegacyTypeParameterType(classElem.typeParameters[0]);
+        var typeT = _emitType(typeParamT);
+        var futureOfT = _emitType(types.futureType2(typeParamT));
+        body.add(js.statement('''
+            #.is = function is_FutureOr(o) {
+              return #.is(o) || #.is(o);
+            }
+            ''', [className, typeT, futureOfT]));
+        // TODO(jmesserly): remove the fallback to `dart.as`. It's only for the
+        // _ignoreTypeFailure logic.
+        body.add(js.statement('''
+            #.as = function as_FutureOr(o) {
+              if (o == null || #.is(o) || #.is(o)) return o;
+              return #.as(o, this, false);
+            }
+            ''', [className, typeT, futureOfT, runtimeModule]));
+        body.add(js.statement('''
+            #._check = function check_FutureOr(o) {
+              if (o == null || #.is(o) || #.is(o)) return o;
+              return #.as(o, this, true);
+            }
+            ''', [className, typeT, futureOfT, runtimeModule]));
+        return null;
+      } else {
         var typeParamT =
             getLegacyTypeParameterType(classElem.typeParameters[0]);
         var typeT = _emitType(typeParamT);
@@ -2272,6 +2193,7 @@
       element.returnType,
       element.typeParameters,
       parameters,
+      nullabilitySuffix: NullabilitySuffix.star,
     );
   }
 
@@ -2942,7 +2864,12 @@
       var gen = emitGeneratorFn(jsParams);
       if (jsParams.isNotEmpty) gen = js.call('() => #(#)', [gen, jsParams]);
 
-      var syncIterable = _emitType(syncIterableType.instantiate([returnType]));
+      var syncIterable = _emitType(
+        syncIterableElement.instantiate(
+          typeArguments: [returnType],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
+      );
       return js.call('new #.new(#)', [syncIterable, gen]);
     }
 
@@ -2957,7 +2884,10 @@
       var asyncStarParam = js_ast.TemporaryId('stream');
       var gen = emitGeneratorFn([asyncStarParam], asyncStarParam);
 
-      var asyncStarImpl = asyncStarImplType.instantiate([returnType]);
+      var asyncStarImpl = asyncStarImplElement.instantiate(
+        typeArguments: [returnType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
       return js.call('new #.new(#).stream', [_emitType(asyncStarImpl), gen]);
     }
 
@@ -5735,7 +5665,10 @@
     if (itemType.isDynamic) return list;
 
     // Call `new JSArray<E>.of(list)`
-    var arrayType = getLegacyRawClassType(_jsArray).instantiate([itemType]);
+    var arrayType = _jsArray.instantiate(
+      typeArguments: [itemType],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     return js.call('#.of(#)', [_emitType(arrayType), list]);
   }
 
@@ -5764,8 +5697,14 @@
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
-    type = identity ? identityHashMapImplType : linkedHashMapImplType;
-    return _emitType(type.instantiate(typeArgs));
+    var element =
+        identity ? identityHashMapImplElement : linkedHashMapImplElement;
+    return _emitType(
+      element.instantiate(
+        typeArguments: typeArgs,
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+    );
   }
 
   js_ast.Expression _emitConstSet(
@@ -5778,8 +5717,14 @@
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
-    type = identity ? identityHashSetImplType : linkedHashSetImplType;
-    return _emitType(type.instantiate(typeArgs));
+    var element =
+        identity ? identityHashSetImplElement : linkedHashSetImplElement;
+    return _emitType(
+      element.instantiate(
+        typeArguments: typeArgs,
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+    );
   }
 
   @override
@@ -5893,8 +5838,10 @@
       if (_isUiAsCodeElement(node)) {
         // Create a temporary variable to build a new collection from.
         var previousCollectionVariable = _currentCollectionVariable;
-        var arrayType =
-            getLegacyRawClassType(_jsArray).instantiate([elementType]);
+        var arrayType = _jsArray.instantiate(
+          typeArguments: [elementType],
+          nullabilitySuffix: NullabilitySuffix.star,
+        );
         var temporaryIdentifier = _createTemporary('items', arrayType);
         _currentCollectionVariable = _emitSimpleIdentifier(temporaryIdentifier);
         var items = js.statement('let # = #',
@@ -6160,10 +6107,16 @@
   /// available. If the element is `external`, the element is used to statically
   /// resolve the JS interop/dart:html static member. Otherwise it is ignored.
   js_ast.Expression _emitStaticMemberName(String name, [Element element]) {
-    if (element != null && _isExternal(element)) {
-      var newName = getAnnotationName(element, isJSName) ??
-          _getJSInteropStaticMemberName(element);
-      if (newName != null) return js.escapedString(newName, "'");
+    if (element != null) {
+      if (_isExternal(element)) {
+        var newName = getAnnotationName(element, isJSName) ??
+            _getJSInteropStaticMemberName(element);
+        if (newName != null) return js.escapedString(newName, "'");
+      }
+      // Allow the Dart SDK to assign names to statics with the @JSExportName
+      // annotation.
+      var exportName = getJSExportName(element);
+      if (exportName != null) return propertyName(exportName);
     }
 
     switch (name) {
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index 74d485c..09374d2 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -196,6 +196,9 @@
     // that build systems do not depend on passing windows-style paths here.
     return p.toUri(moduleName).toString();
   }
+
+  // TODO(nshahan) Cleanup when NNBD graduates experimental status.
+  bool get nonNullableEnabled => experiments['non-nullable'] ?? false;
 }
 
 /// Finds explicit module names of the form `path=name` in [summaryPaths],
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 9a92ecd..4fa082c 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -30,6 +30,8 @@
 
 const _binaryName = 'dartdevc -k';
 
+// ignore_for_file: DEPRECATED_MEMBER_USE
+
 /// Invoke the compiler with [args].
 ///
 /// Returns `true` if the program compiled without any fatal errors.
@@ -313,18 +315,8 @@
     compilerState.options.onDiagnostic = diagnosticMessageHandler;
     Component incrementalComponent = await incrementalCompiler.computeDelta(
         entryPoints: inputs, fullComponent: true);
-    result = fe.DdcResult(incrementalComponent, doneInputSummaries,
-        incrementalCompiler.userCode.loader.hierarchy);
-
-    // Workaround for DDC relying on isExternal being set to true.
-    for (var lib in cachedSdkInput.component.libraries) {
-      lib.isExternal = true;
-    }
-    for (Component c in doneInputSummaries) {
-      for (Library lib in c.libraries) {
-        lib.isExternal = true;
-      }
-    }
+    result = fe.DdcResult(incrementalComponent, cachedSdkInput.component,
+        doneInputSummaries, incrementalCompiler.userCode.loader.hierarchy);
   }
   compilerState.options.onDiagnostic = null; // See http://dartbug.com/36983.
 
@@ -333,7 +325,14 @@
   }
 
   var component = result.component;
-  if (!options.emitMetadata && _checkForDartMirrorsImport(component)) {
+  Set<Library> librariesFromDill = result.computeLibrariesFromDill();
+  Component compiledLibraries =
+      Component(nameRoot: component.root, uriToSource: component.uriToSource);
+  for (Library lib in component.libraries) {
+    if (!librariesFromDill.contains(lib)) compiledLibraries.libraries.add(lib);
+  }
+
+  if (!options.emitMetadata && _checkForDartMirrorsImport(compiledLibraries)) {
     return CompilerResult(1, kernelState: compilerState);
   }
 
@@ -376,7 +375,7 @@
   var compiler = ProgramCompiler(component, result.classHierarchy, options);
 
   var jsModule = compiler.emitModule(
-      component, result.inputSummaries, inputSummaries, summaryModules);
+      compiledLibraries, result.inputSummaries, inputSummaries, summaryModules);
 
   // Also the old Analyzer backend had some code to make debugging better when
   // --single-out-file is used, but that option does not appear to be used by
@@ -532,7 +531,7 @@
 
 bool _checkForDartMirrorsImport(Component component) {
   for (var library in component.libraries) {
-    if (library.isExternal || library.importUri.scheme == 'dart') continue;
+    if (library.importUri.scheme == 'dart') continue;
     for (var dep in library.dependencies) {
       var uri = dep.targetLibrary.importUri;
       if (uri.scheme == 'dart' && uri.path == 'mirrors') {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 3493030..939ee1b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -288,7 +288,7 @@
       }
     }
 
-    var libraries = component.libraries.where((l) => !l.isExternal);
+    var libraries = component.libraries;
 
     // Initialize our library variables.
     var items = startModule(libraries);
@@ -968,138 +968,61 @@
       if (prop != null) markSubtypeOf(prop);
     }
 
-    // TODO(jmesserly): share these hand coded type checks with the old back
-    // end, perhaps by factoring them into a common file, or move them to be
-    // static methdos in the SDK. (Or wait until we delete the old back end.)
-    if (c.enclosingLibrary == _coreTypes.coreLibrary) {
-      if (c == _coreTypes.objectClass) {
-        // Everything is an Object.
-        body.add(js.statement(
-            '#.is = function is_Object(o) { return true; }', [className]));
-        body.add(js.statement(
-            '#.as = function as_Object(o) { return o; }', [className]));
-        body.add(js.statement(
-            '#._check = function check_Object(o) { return o; }', [className]));
-        return null;
-      }
-      if (c == _coreTypes.stringClass) {
-        body.add(js.statement(
-            '#.is = function is_String(o) { return typeof o == "string"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_String(o) {'
-            '  if (typeof o == "string" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_String(o) {'
-            '  if (typeof o == "string" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (c == _coreTypes.functionClass) {
-        body.add(js.statement(
-            '#.is = function is_Function(o) { return typeof o == "function"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_Function(o) {'
-            '  if (typeof o == "function" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_String(o) {'
-            '  if (typeof o == "function" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (c == _coreTypes.intClass) {
-        body.add(js.statement(
-            '#.is = function is_int(o) {'
-            '  return typeof o == "number" && Math.floor(o) == o;'
-            '}',
-            className));
-        body.add(js.statement(
-            '#.as = function as_int(o) {'
-            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
-            '    return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_int(o) {'
-            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
-            '    return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (c == _coreTypes.nullClass) {
-        body.add(js.statement(
-            '#.is = function is_Null(o) { return o == null; }', className));
-        body.add(js.statement(
-            '#.as = function as_Null(o) {'
-            '  if (o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_Null(o) {'
-            '  if (o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (c == _coreTypes.numClass || c == _coreTypes.doubleClass) {
-        body.add(js.statement(
-            '#.is = function is_num(o) { return typeof o == "number"; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_num(o) {'
-            '  if (typeof o == "number" || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_num(o) {'
-            '  if (typeof o == "number" || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
-      if (c == _coreTypes.boolClass) {
-        body.add(js.statement(
-            '#.is = function is_bool(o) { return o === true || o === false; }',
-            className));
-        body.add(js.statement(
-            '#.as = function as_bool(o) {'
-            '  if (o === true || o === false || o == null) return o;'
-            '  return #.as(o, #, false);'
-            '}',
-            [className, runtimeModule, className]));
-        body.add(js.statement(
-            '#._check = function check_bool(o) {'
-            '  if (o === true || o === false || o == null) return o;'
-            '  return #.as(o, #, true);'
-            '}',
-            [className, runtimeModule, className]));
-        return null;
-      }
+    if (c.enclosingLibrary == _coreTypes.coreLibrary &&
+        (c == _coreTypes.objectClass ||
+            c == _coreTypes.stringClass ||
+            c == _coreTypes.functionClass ||
+            c == _coreTypes.intClass ||
+            c == _coreTypes.nullClass ||
+            c == _coreTypes.numClass ||
+            c == _coreTypes.doubleClass ||
+            c == _coreTypes.boolClass)) {
+      // Custom type tests for these types are in the patch files.
+      return null;
     }
-    if (c.enclosingLibrary == _coreTypes.asyncLibrary) {
-      if (c == _coreTypes.futureOrClass) {
-        var typeParam = TypeParameterType(c.typeParameters[0]);
+
+    if (c.enclosingLibrary == _coreTypes.asyncLibrary &&
+        c == _coreTypes.futureOrClass) {
+      // These methods are difficult to place in the runtime or patch files.
+      // * They need to be callable from the class but they can't be static
+      //   methods on the FutureOr class in Dart because they reference the
+      //   generic type parameter.
+      // * There isn't an obvious place in dart:_runtime were we could place a
+      //   method that adds these type tests (similar to addTypeTests()) because
+      //   in the bootstrap ordering the Future class hasn't been defined yet.
+      if (_options.nonNullableEnabled) {
+        // TODO(nshahan) Update FutureOr type tests for NNBD
+        var typeParam =
+            TypeParameterType(c.typeParameters[0], Nullability.legacy);
         var typeT = visitTypeParameterType(typeParam);
-        var futureOfT = visitInterfaceType(
-            InterfaceType(_coreTypes.futureClass, [typeParam]));
+        var futureOfT = visitInterfaceType(InterfaceType(
+            _coreTypes.futureClass, Nullability.legacy, [typeParam]));
+        body.add(js.statement('''
+            #.is = function is_FutureOr(o) {
+              return #.is(o) || #.is(o);
+            }
+            ''', [className, typeT, futureOfT]));
+        // TODO(jmesserly): remove the fallback to `dart.as`. It's only for the
+        // _ignoreTypeFailure logic.
+        body.add(js.statement('''
+            #.as = function as_FutureOr(o) {
+              if (o == null || #.is(o) || #.is(o)) return o;
+              return #.as(o, this, false);
+            }
+            ''', [className, typeT, futureOfT, runtimeModule]));
+        body.add(js.statement('''
+            #._check = function check_FutureOr(o) {
+              if (o == null || #.is(o) || #.is(o)) return o;
+              return #.as(o, this, true);
+            }
+            ''', [className, typeT, futureOfT, runtimeModule]));
+        return null;
+      } else {
+        var typeParam =
+            TypeParameterType(c.typeParameters[0], Nullability.legacy);
+        var typeT = visitTypeParameterType(typeParam);
+        var futureOfT = visitInterfaceType(InterfaceType(
+            _coreTypes.futureClass, Nullability.legacy, [typeParam]));
         body.add(js.statement('''
             #.is = function is_FutureOr(o) {
               return #.is(o) || #.is(o);
@@ -1304,7 +1227,7 @@
       if (!_options.emitMetadata && member.isStatic) continue;
 
       var name = member.name.name;
-      var reifiedType = _getMemberRuntimeType(member, c) as FunctionType;
+      var reifiedType = _memberRuntimeType(member, c) as FunctionType;
 
       // Don't add redundant signatures for inherited methods whose signature
       // did not change.  If we are not overriding, or if the thing we are
@@ -1317,7 +1240,7 @@
           : null;
 
       var needsSignature = memberOverride == null ||
-          reifiedType != _getMemberRuntimeType(memberOverride, c);
+          reifiedType != _memberRuntimeType(memberOverride, c);
 
       if (needsSignature) {
         js_ast.Expression type;
@@ -1396,7 +1319,7 @@
   }
 
   js_ast.Expression _emitFieldSignature(Field field, Class fromClass) {
-    var type = _getTypeFromClass(field.type, field.enclosingClass, fromClass);
+    var type = _typeFromClass(field.type, field.enclosingClass, fromClass);
     var args = [_emitType(type)];
     var annotations = field.annotations;
     if (_options.emitMetadata &&
@@ -1412,7 +1335,7 @@
         field.isFinal ? 'finalFieldType(#)' : 'fieldType(#)', [args]);
   }
 
-  DartType _getMemberRuntimeType(Member member, Class fromClass) {
+  DartType _memberRuntimeType(Member member, Class fromClass) {
     var f = member.function;
     if (f == null) {
       return (member as Field).type;
@@ -1429,18 +1352,18 @@
 
       // TODO(jmesserly): do covariant type parameter bounds also need to be
       // reified as `Object`?
-      result = FunctionType(
-          f.positionalParameters.map(reifyParameter).toList(), f.returnType,
+      result = FunctionType(f.positionalParameters.map(reifyParameter).toList(),
+          f.returnType, Nullability.legacy,
           namedParameters: f.namedParameters.map(reifyNamedParameter).toList()
             ..sort(),
           typeParameters: f.thisFunctionType.typeParameters,
           requiredParameterCount: f.requiredParameterCount);
     }
-    return _getTypeFromClass(result, member.enclosingClass, fromClass)
+    return _typeFromClass(result, member.enclosingClass, fromClass)
         as FunctionType;
   }
 
-  DartType _getTypeFromClass(DartType type, Class superclass, Class subclass) {
+  DartType _typeFromClass(DartType type, Class superclass, Class subclass) {
     if (identical(superclass, subclass)) return type;
     return Substitution.fromSupertype(
             _hierarchy.getClassAsInstanceOf(subclass, superclass))
@@ -1848,7 +1771,7 @@
     if (superMember == null) return const [];
 
     substituteType(DartType t) {
-      return _getTypeFromClass(t, superMember.enclosingClass, enclosingClass);
+      return _typeFromClass(t, superMember.enclosingClass, enclosingClass);
     }
 
     var name = _declareMemberName(member);
@@ -2352,8 +2275,12 @@
     if (member != null) {
       var jsName = _emitJSInteropStaticMemberName(member);
       if (jsName != null) return jsName;
-    }
 
+      // Allow the Dart SDK to assign names to statics with the @JSExportName
+      // annotation.
+      var exportName = _jsExportName(member);
+      if (exportName != null) return propertyName(exportName);
+    }
     switch (name) {
       // Reserved for the compiler to do `x as T`.
       case 'as':
@@ -2450,7 +2377,7 @@
     return false;
   }
 
-  String _getJSNameWithoutGlobal(NamedNode n) {
+  String _jsNameWithoutGlobal(NamedNode n) {
     if (!usesJSInterop(n)) return null;
     var libraryJSName = _annotationName(getLibrary(n), isPublicJSAnnotation);
     var jsName = _annotationName(n, isPublicJSAnnotation) ?? getTopLevelName(n);
@@ -2458,7 +2385,7 @@
   }
 
   js_ast.PropertyAccess _emitJSInterop(NamedNode n) {
-    var jsName = _getJSNameWithoutGlobal(n);
+    var jsName = _jsNameWithoutGlobal(n);
     if (jsName == null) return null;
     return _emitJSInteropForGlobal(jsName);
   }
@@ -2625,7 +2552,7 @@
       return runtimeCall(
           'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
     }
-    var jsName = _getJSNameWithoutGlobal(c);
+    var jsName = _jsNameWithoutGlobal(c);
     if (jsName != null) {
       return runtimeCall('lazyJSType(() => #, #)',
           [_emitJSInteropForGlobal(jsName), js.escapedString(jsName)]);
@@ -2969,10 +2896,9 @@
         gen = js.call('() => #(#)', [gen, mutatedParams]);
       }
 
-      var returnType =
-          _getExpectedReturnType(function, _coreTypes.iterableClass);
-      var syncIterable =
-          _emitType(InterfaceType(_syncIterableClass, [returnType]));
+      var returnType = _expectedReturnType(function, _coreTypes.iterableClass);
+      var syncIterable = _emitType(
+          InterfaceType(_syncIterableClass, Nullability.legacy, [returnType]));
       return js.call('new #.new(#)', [syncIterable, gen]);
     }
 
@@ -2986,8 +2912,9 @@
       // _AsyncStarImpl has an example of the generated code.
       var gen = emitGeneratorFn((_) => [_asyncStarController]);
 
-      var returnType = _getExpectedReturnType(function, _coreTypes.streamClass);
-      var asyncStarImpl = InterfaceType(_asyncStarImplClass, [returnType]);
+      var returnType = _expectedReturnType(function, _coreTypes.streamClass);
+      var asyncStarImpl =
+          InterfaceType(_asyncStarImplClass, Nullability.legacy, [returnType]);
       return js.call('new #.new(#).stream', [_emitType(asyncStarImpl), gen]);
     }
 
@@ -3011,7 +2938,7 @@
   }
 
   /// Gets the expected return type of a `sync*` or `async*` body.
-  DartType _getExpectedReturnType(FunctionNode f, Class expected) {
+  DartType _expectedReturnType(FunctionNode f, Class expected) {
     var type = f.thisFunctionType.returnType;
     if (type is InterfaceType) {
       var match = _hierarchy.getTypeAsInstanceOf(type, expected);
@@ -3169,7 +3096,7 @@
     for (var t in typeFormals) {
       if (t.isGenericCovariantImpl && !_types.isTop(t.bound)) {
         body.add(runtimeStatement('checkTypeBound(#, #, #)', [
-          _emitType(TypeParameterType(t)),
+          _emitType(TypeParameterType(t, Nullability.legacy)),
           _emitType(t.bound),
           propertyName(t.name)
         ]));
@@ -3259,7 +3186,8 @@
   ///
   /// This is the most common kind of marking, and is used for most expressions
   /// and statements.
-  SourceLocation _nodeStart(TreeNode node) => _getLocation(node.fileOffset);
+  SourceLocation _nodeStart(TreeNode node) =>
+      _toSourceLocation(node.fileOffset);
 
   /// Gets the end position of [node] for use in source mapping.
   ///
@@ -3270,7 +3198,7 @@
   /// has already been emitted. For example, `foo.bar` we only need to mark the
   /// end of `.bar` to ensure `foo.bar` has a hover tooltip.
   NodeEnd _nodeEnd(int endOffset) {
-    var loc = _getLocation(endOffset);
+    var loc = _toSourceLocation(endOffset);
     return loc != null ? NodeEnd(loc) : null;
   }
 
@@ -3279,12 +3207,12 @@
   //
   // TODO(jmesserly): we need a lot more nodes to support hover.
   NodeSpan _variableSpan(int offset, int nameLength) {
-    var start = _getLocation(offset);
-    var end = _getLocation(offset + nameLength);
+    var start = _toSourceLocation(offset);
+    var end = _toSourceLocation(offset + nameLength);
     return start != null && end != null ? NodeSpan(start, end) : null;
   }
 
-  SourceLocation _getLocation(int offset) {
+  SourceLocation _toSourceLocation(int offset) {
     if (offset == -1) return null;
     var fileUri = _currentUri;
     if (fileUri == null) return null;
@@ -3310,8 +3238,8 @@
   /// source code.
   HoverComment _hoverComment(
       js_ast.Expression expr, int offset, int nameLength) {
-    var start = _getLocation(offset);
-    var end = _getLocation(offset + nameLength);
+    var start = _toSourceLocation(offset);
+    var end = _toSourceLocation(offset + nameLength);
     return start != null && end != null ? HoverComment(expr, start, end) : null;
   }
 
@@ -3376,11 +3304,12 @@
       jsCondition = runtimeCall('test(#)', [jsCondition]);
     }
 
-    var encodedConditionSource = node
-        .enclosingComponent.uriToSource[node.location.file].source
-        .sublist(node.conditionStartOffset, node.conditionEndOffset);
-    var conditionSource = utf8.decode(encodedConditionSource);
-    var location = _getLocation(node.conditionStartOffset);
+    var encodedSource =
+        node.enclosingComponent.uriToSource[node.location.file].source;
+    var source = utf8.decode(encodedSource, allowMalformed: true);
+    var conditionSource =
+        source.substring(node.conditionStartOffset, node.conditionEndOffset);
+    var location = _toSourceLocation(node.conditionStartOffset);
     return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
       jsCondition,
       runtimeModule,
@@ -4166,7 +4095,7 @@
     if (target is Field || target is Procedure && target.isAccessor) {
       var fromType = target.getterType;
       if (fromType is InterfaceType) {
-        var callName = _getImplicitCallTarget(fromType);
+        var callName = _implicitCallTarget(fromType);
         if (callName != null) {
           return js.call('#.#.#(#)', [jsReceiver, jsName, callName, args]);
         }
@@ -4214,9 +4143,9 @@
   }
 
   bool _isDirectCallable(DartType t) =>
-      t is FunctionType || t is InterfaceType && usesJSInterop(t.classNode);
+      t is FunctionType || (t is InterfaceType && usesJSInterop(t.classNode));
 
-  js_ast.Expression _getImplicitCallTarget(InterfaceType from) {
+  js_ast.Expression _implicitCallTarget(InterfaceType from) {
     var c = from.classNode;
     var member = _hierarchy.getInterfaceMember(c, Name("call"));
     if (member is Procedure && !member.isAccessor && !usesJSInterop(c)) {
@@ -4881,7 +4810,7 @@
 
     var type = ctorClass.typeParameters.isEmpty
         ? _coreTypes.legacyRawType(ctorClass)
-        : InterfaceType(ctorClass, args.types);
+        : InterfaceType(ctorClass, Nullability.legacy, args.types);
 
     if (isFromEnvironmentInvocation(_coreTypes, node)) {
       var value = _constants.evaluate(node);
@@ -4942,7 +4871,7 @@
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= _typeRep.isPrimitive(typeArgs[0]);
     var c = identity ? _identityHashMapImplClass : _linkedHashMapImplClass;
-    return _emitType(InterfaceType(c, typeArgs));
+    return _emitType(InterfaceType(c, Nullability.legacy, typeArgs));
   }
 
   js_ast.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
@@ -4950,7 +4879,7 @@
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= _typeRep.isPrimitive(typeArgs[0]);
     var c = identity ? _identityHashSetImplClass : _linkedHashSetImplClass;
-    return _emitType(InterfaceType(c, typeArgs));
+    return _emitType(InterfaceType(c, Nullability.legacy, typeArgs));
   }
 
   js_ast.Expression _emitObjectLiteral(Arguments node) {
@@ -5171,7 +5100,8 @@
     if (itemType == const DynamicType()) return list;
 
     // Call `new JSArray<E>.of(list)`
-    var arrayType = InterfaceType(_jsArrayClass, [itemType]);
+    var arrayType =
+        InterfaceType(_jsArrayClass, Nullability.legacy, [itemType]);
     return js.call('#.of(#)', [_emitType(arrayType), list]);
   }
 
@@ -5187,8 +5117,8 @@
   js_ast.Expression visitSetLiteral(SetLiteral node) {
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
-      var setType = visitInterfaceType(
-          InterfaceType(_linkedHashSetClass, [node.typeArgument]));
+      var setType = visitInterfaceType(InterfaceType(
+          _linkedHashSetClass, Nullability.legacy, [node.typeArgument]));
       if (node.expressions.isEmpty) {
         return js.call('#.new()', [setType]);
       }
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index d79ce0b..c7f7e28 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -489,9 +489,9 @@
 /// to be produced in the set of expressions that cannot be null by DDC's null
 /// inference.
 Future expectNotNull(String code, String expectedNotNull) async {
-  var component = await kernelCompile(code);
-  var collector = NotNullCollector();
-  component.accept(collector);
+  var result = await kernelCompile(code);
+  var collector = NotNullCollector(result.librariesFromDill);
+  result.component.accept(collector);
   var actualNotNull = collector.notNullExpressions
       // ConstantExpressions print the table offset - we want to compare
       // against the underlying constant value instead.
@@ -517,15 +517,19 @@
 
 /// Given the Dart [code], expects all the expressions inferred to be not-null.
 Future expectAllNotNull(String code) async {
-  (await kernelCompile(code)).accept(ExpectAllNotNull());
+  var result = (await kernelCompile(code));
+  result.component.accept(ExpectAllNotNull(result.librariesFromDill));
 }
 
 bool useAnnotations = false;
 NullableInference inference;
 
 class _TestRecursiveVisitor extends RecursiveVisitor<void> {
+  final Set<Library> librariesFromDill;
   int _functionNesting = 0;
 
+  _TestRecursiveVisitor(this.librariesFromDill);
+
   @override
   visitComponent(Component node) {
     var hierarchy = ClassHierarchy(node);
@@ -543,7 +547,7 @@
 
   @override
   visitLibrary(Library node) {
-    if (node.isExternal ||
+    if (librariesFromDill.contains(node) ||
         node.importUri.scheme == 'package' &&
             node.importUri.pathSegments[0] == 'meta') {
       return;
@@ -564,6 +568,8 @@
 class NotNullCollector extends _TestRecursiveVisitor {
   final notNullExpressions = <Expression>[];
 
+  NotNullCollector(Set<Library> librariesFromDill) : super(librariesFromDill);
+
   @override
   defaultExpression(Expression node) {
     if (!inference.isNullable(node)) {
@@ -574,6 +580,8 @@
 }
 
 class ExpectAllNotNull extends _TestRecursiveVisitor {
+  ExpectAllNotNull(Set<Library> librariesFromDill) : super(librariesFromDill);
+
   @override
   defaultExpression(Expression node) {
     expect(inference.isNullable(node), false,
@@ -585,7 +593,14 @@
 fe.InitializedCompilerState _compilerState;
 final _fileSystem = fe.MemoryFileSystem(Uri.file('/memory/'));
 
-Future<Component> kernelCompile(String code) async {
+class CompileResult {
+  final Component component;
+  final Set<Library> librariesFromDill;
+
+  CompileResult(this.component, this.librariesFromDill);
+}
+
+Future<CompileResult> kernelCompile(String code) async {
   var succeeded = true;
   void diagnosticMessageHandler(fe.DiagnosticMessage message) {
     if (message.severity == fe.Severity.error) {
@@ -625,5 +640,7 @@
   fe.DdcResult result =
       await fe.compile(_compilerState, [mainUri], diagnosticMessageHandler);
   expect(succeeded, true);
-  return result.component;
+
+  Set<Library> librariesFromDill = result.computeLibrariesFromDill();
+  return CompileResult(result.component, librariesFromDill);
 }
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 2f5193b..783bee2 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -50,7 +50,8 @@
         new CompilerContext(
             new ProcessedOptions(options: options, inputs: [entryPoint])),
         component,
-        outlineOnly);
+        outlineOnly,
+        incrementalSerializer);
   }
 
   /// Returns a component whose libraries are the recompiled libraries,
diff --git a/pkg/front_end/lib/src/api_unstable/compiler_state.dart b/pkg/front_end/lib/src/api_unstable/compiler_state.dart
index 06998b7..9baa0b7 100644
--- a/pkg/front_end/lib/src/api_unstable/compiler_state.dart
+++ b/pkg/front_end/lib/src/api_unstable/compiler_state.dart
@@ -38,12 +38,7 @@
 class WorkerInputComponent {
   final List<int> digest;
   final Component component;
-  final Set<Uri> externalLibs;
-  WorkerInputComponent(this.digest, this.component)
-      : externalLibs = component.libraries
-            .where((lib) => lib.isExternal)
-            .map((lib) => lib.importUri)
-            .toSet();
+  WorkerInputComponent(this.digest, this.component);
 }
 
 bool digestsEqual(List<int> a, List<int> b) {
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 9560262..1f39033 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -9,7 +9,7 @@
 
 import 'package:kernel/class_hierarchy.dart';
 
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/kernel.dart' show Component, Library;
 
 import 'package:kernel/target/targets.dart' show Target;
 
@@ -71,11 +71,30 @@
 
 class DdcResult {
   final Component component;
+  final Component sdkSummary;
   final List<Component> inputSummaries;
   final ClassHierarchy classHierarchy;
 
-  DdcResult(this.component, this.inputSummaries, this.classHierarchy)
+  DdcResult(
+      this.component, this.sdkSummary, this.inputSummaries, this.classHierarchy)
       : assert(classHierarchy != null);
+
+  Set<Library> computeLibrariesFromDill() {
+    Set<Library> librariesFromDill = new Set<Library>();
+
+    for (Component c in inputSummaries) {
+      for (Library lib in c.libraries) {
+        librariesFromDill.add(lib);
+      }
+    }
+    if (sdkSummary != null) {
+      for (Library lib in sdkSummary.libraries) {
+        librariesFromDill.add(lib);
+      }
+    }
+
+    return librariesFromDill;
+  }
 }
 
 Future<InitializedCompilerState> initializeCompiler(
@@ -108,8 +127,10 @@
     // as external.
     (await oldState.processedOpts.loadSdkSummary(null))
         .libraries
+        // ignore: DEPRECATED_MEMBER_USE
         .forEach((lib) => lib.isExternal = false);
     (await oldState.processedOpts.loadInputSummaries(null))
+        // ignore: DEPRECATED_MEMBER_USE
         .forEach((p) => p.libraries.forEach((lib) => lib.isExternal = false));
 
     return oldState;
@@ -188,7 +209,9 @@
   Component component = compilerResult?.component;
   if (component == null) return null;
 
-  // This should be cached.
+  // These should be cached.
+  Component sdkSummary = await processedOpts.loadSdkSummary(null);
   List<Component> summaries = await processedOpts.loadInputSummaries(null);
-  return new DdcResult(component, summaries, compilerResult.classHierarchy);
+  return new DdcResult(
+      component, sdkSummary, summaries, compilerResult.classHierarchy);
 }
diff --git a/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart b/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart
index d7a4797..3916c39 100644
--- a/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart
+++ b/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart
@@ -120,10 +120,6 @@
         options = oldState.options;
         processedOpts = oldState.processedOpts;
         Component sdkComponent = cachedSdkInput.component;
-        // Reset the state of the component.
-        for (Library lib in sdkComponent.libraries) {
-          lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
-        }
 
         // Make sure the canonical name root knows about the sdk - otherwise we
         // won't be able to link to it when loading more outlines.
@@ -185,9 +181,8 @@
         } else {
           // Need to reset cached components so they are usable again.
           Component component = cachedInput.component;
-          for (Library lib in component.libraries) {
-            lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
-            if (trackNeededDillLibraries) {
+          if (trackNeededDillLibraries) {
+            for (Library lib in component.libraries) {
               libraryToInputDill[lib.importUri] = summaryUri;
             }
           }
diff --git a/pkg/front_end/lib/src/compute_platform_binaries_location.dart b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
index ad98f28..2c36d10 100644
--- a/pkg/front_end/lib/src/compute_platform_binaries_location.dart
+++ b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
@@ -14,9 +14,11 @@
 /// of the platform libraries that are used to avoid recompiling those
 /// libraries.
 Uri computePlatformBinariesLocation({bool forceBuildDir: false}) {
+  String resolvedExecutable = Platform.environment['resolvedExecutable'];
   // The directory of the Dart VM executable.
   Uri vmDirectory = Uri.base
-      .resolveUri(new Uri.file(Platform.resolvedExecutable))
+      .resolveUri(
+          new Uri.file(resolvedExecutable ?? Platform.resolvedExecutable))
       .resolve(".");
   if (vmDirectory.path.endsWith("/bin/")) {
     // Looks like the VM is in a `/bin/` directory, so this is running from a
diff --git a/pkg/front_end/lib/src/external_state_snapshot.dart b/pkg/front_end/lib/src/external_state_snapshot.dart
index 0484dc0..c49ce26 100644
--- a/pkg/front_end/lib/src/external_state_snapshot.dart
+++ b/pkg/front_end/lib/src/external_state_snapshot.dart
@@ -12,6 +12,7 @@
 
   ExternalStateSnapshot(Component component)
       : snapshots = new List<ExternalState>.from(
+            // ignore: DEPRECATED_MEMBER_USE
             component.libraries.map((l) => new ExternalState(l, l.isExternal)));
 
   void restore() {
@@ -28,6 +29,7 @@
   ExternalState(this.library, this.isExternal);
 
   void restore() {
+    // ignore: DEPRECATED_MEMBER_USE
     library.isExternal = isExternal;
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index e47b4a1..98f0245 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -617,19 +617,15 @@
   @override
   InterfaceType get legacyRawType {
     // TODO(dmitryas): Use computeBound instead of DynamicType here?
-    return _legacyRawType ??= new InterfaceType(
-        cls,
-        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
-        Nullability.legacy);
+    return _legacyRawType ??= new InterfaceType(cls, Nullability.legacy,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()));
   }
 
   @override
   InterfaceType get nullableRawType {
     // TODO(dmitryas): Use computeBound instead of DynamicType here?
-    return _nullableRawType ??= new InterfaceType(
-        cls,
-        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
-        Nullability.nullable);
+    return _nullableRawType ??= new InterfaceType(cls, Nullability.nullable,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()));
   }
 
   @override
@@ -637,8 +633,8 @@
     // TODO(dmitryas): Use computeBound instead of DynamicType here?
     return _nonNullableRawType ??= new InterfaceType(
         cls,
-        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
-        Nullability.nonNullable);
+        Nullability.nonNullable,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()));
   }
 
   @override
@@ -665,7 +661,7 @@
     }
     return arguments == null
         ? rawType(nullability)
-        : new InterfaceType(cls, arguments, nullability);
+        : new InterfaceType(cls, nullability, arguments);
   }
 
   @override
@@ -807,7 +803,8 @@
     SourceLibraryBuilder library = this.library;
 
     List<TypeArgumentIssue> issues = findTypeArgumentIssues(
-        new InterfaceType(supertype.classNode, supertype.typeArguments),
+        new InterfaceType(
+            supertype.classNode, Nullability.legacy, supertype.typeArguments),
         typeEnvironment,
         allowSuperBounded: false);
     if (issues != null) {
@@ -1411,7 +1408,8 @@
           <TypeParameter, DartType>{};
       for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
         substitutionMap[interfaceFunction.typeParameters[i]] =
-            new TypeParameterType(declaredFunction.typeParameters[i]);
+            new TypeParameterType(
+                declaredFunction.typeParameters[i], Nullability.legacy);
       }
       Substitution substitution = Substitution.fromMap(substitutionMap);
       for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index 07565c4..8c730f3 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -6,7 +6,7 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -35,6 +35,7 @@
 import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
 import 'library_builder.dart';
+import 'member_builder.dart';
 import 'metadata_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
@@ -64,10 +65,6 @@
 
   bool get isEligibleForTopLevelInference;
 
-  Constructor build(SourceLibraryBuilder libraryBuilder);
-
-  FunctionNode buildFunction(LibraryBuilder library);
-
   /// The [Constructor] built by this builder.
   Constructor get constructor;
 
@@ -126,6 +123,15 @@
             compilationUnit, charOffset, nativeMethodName);
 
   @override
+  Member get readTarget => null;
+
+  @override
+  Member get writeTarget => null;
+
+  @override
+  Member get invokeTarget => constructor;
+
+  @override
   ConstructorBuilder get origin => actualOrigin ?? this;
 
   @override
@@ -162,6 +168,13 @@
   }
 
   @override
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.Constructor);
+  }
+
+  @override
   Constructor build(SourceLibraryBuilder libraryBuilder) {
     if (_constructor.name == null) {
       _constructor.function = buildFunction(libraryBuilder);
@@ -213,10 +226,11 @@
     List<DartType> typeParameterTypes = new List<DartType>();
     for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
       TypeParameter typeParameter = enclosingClass.typeParameters[i];
-      typeParameterTypes.add(new TypeParameterType(typeParameter));
+      typeParameterTypes
+          .add(new TypeParameterType(typeParameter, Nullability.legacy));
     }
-    functionNode.returnType =
-        new InterfaceType(enclosingClass, typeParameterTypes);
+    functionNode.returnType = new InterfaceType(
+        enclosingClass, Nullability.legacy, typeParameterTypes);
     return functionNode;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index 4cc11c3..2a17bdcb 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -273,9 +273,9 @@
         coreLibrary.scope, charOffset, fileUri, libraryBuilder);
     listType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
 
-    FieldBuilder indexFieldBuilder = firstMemberNamed("index");
+    FieldBuilderImpl indexFieldBuilder = firstMemberNamed("index");
     Field indexField = indexFieldBuilder.build(libraryBuilder);
-    FieldBuilder nameFieldBuilder = firstMemberNamed("_name");
+    FieldBuilderImpl nameFieldBuilder = firstMemberNamed("_name");
     Field nameField = nameFieldBuilder.build(libraryBuilder);
     ProcedureBuilder toStringBuilder = firstMemberNamed("toString");
     toStringBuilder.body = new ReturnStatement(
@@ -286,17 +286,17 @@
         if (enumConstantInfo != null) {
           Builder declaration = firstMemberNamed(enumConstantInfo.name);
           if (declaration.isField) {
-            FieldBuilder field = declaration;
+            FieldBuilderImpl field = declaration;
             values.add(new StaticGet(field.build(libraryBuilder)));
           }
         }
       }
     }
-    FieldBuilder valuesBuilder = firstMemberNamed("values");
+    FieldBuilderImpl valuesBuilder = firstMemberNamed("values");
     valuesBuilder.build(libraryBuilder);
     valuesBuilder.initializer = new ListLiteral(values,
         typeArgument: rawType(library.nonNullable), isConst: true);
-    ConstructorBuilder constructorBuilder = constructorScopeBuilder[""];
+    ConstructorBuilderImpl constructorBuilder = constructorScopeBuilder[""];
     Constructor constructor = constructorBuilder.build(libraryBuilder);
     constructor.initializers.insert(
         0,
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 75a5060..941904a 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -6,7 +6,7 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
 
-import 'package:kernel/ast.dart' hide MapEntry, Variance;
+import 'package:kernel/ast.dart' hide MapEntry;
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -30,7 +30,7 @@
 import '../source/source_loader.dart' show SourceLoader;
 
 import '../type_inference/type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly, Variance;
+    show IncludesTypeParametersNonCovariantly;
 
 import '../type_inference/type_inferrer.dart'
     show ExpressionInferenceResult, TypeInferrerImpl;
@@ -66,8 +66,6 @@
 
   bool get isEligibleForInference;
 
-  Field build(SourceLibraryBuilder libraryBuilder);
-
   DartType get builtType;
 }
 
@@ -138,6 +136,26 @@
     return true;
   }
 
+  @override
+  Member get readTarget => field;
+
+  @override
+  Member get writeTarget => isAssignable ? field : null;
+
+  @override
+  Member get invokeTarget => field;
+
+  @override
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(
+        member,
+        isExtensionMember
+            ? BuiltMemberKind.ExtensionField
+            : BuiltMemberKind.Field);
+  }
+
   Field build(SourceLibraryBuilder libraryBuilder) {
     field
       ..isCovariant = isCovariant
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index 2ddba04..bd2d60d 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -7,7 +7,7 @@
 import 'dart:core' hide MapEntry;
 
 import 'package:front_end/src/fasta/kernel/kernel_api.dart';
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/type_algebra.dart';
 
@@ -34,7 +34,7 @@
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import '../type_inference/type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly, Variance;
+    show IncludesTypeParametersNonCovariantly;
 
 import 'builder.dart';
 import 'class_builder.dart';
@@ -103,8 +103,6 @@
 
   bool get isNative;
 
-  FunctionNode buildFunction(LibraryBuilder library);
-
   /// Returns the [index]th parameter of this function.
   ///
   /// The index is the syntactical index, including both positional and named
@@ -128,8 +126,6 @@
   /// members.
   List<TypeParameter> get extensionTypeParameters;
 
-  Member build(SourceLibraryBuilder library);
-
   void becomeNative(Loader loader);
 
   bool checkPatch(FunctionBuilder patch);
@@ -339,7 +335,6 @@
   @override
   bool get isNative => nativeMethodName != null;
 
-  @override
   FunctionNode buildFunction(LibraryBuilder library) {
     assert(function == null);
     FunctionNode result = new FunctionNode(body, asyncMarker: asyncModifier);
@@ -497,6 +492,8 @@
     }
   }
 
+  Member build(SourceLibraryBuilder library);
+
   @override
   void becomeNative(Loader loader) {
     MemberBuilder constructor = loader.getNativeAnnotation();
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index dde5a40..c1aa78c1 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -101,11 +101,11 @@
       }
     }
     return new FunctionType(positionalParameters, builtReturnType,
+        nullabilityBuilder.build(library),
         namedParameters: namedParameters ?? const <NamedType>[],
         typeParameters: typeParameters ?? const <TypeParameter>[],
         requiredParameterCount: requiredParameterCount,
-        typedefType: origin,
-        nullability: nullabilityBuilder.build(library));
+        typedefType: origin);
   }
 
   Supertype buildSupertype(
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index c4475da..6e0219e 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -30,11 +30,25 @@
   /// The [Member] built by this builder;
   Member get member;
 
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  Member get extensionTearOff;
+  /// The [Member] to use when reading from this member builder.
+  ///
+  /// For a field, a getter or a regular method this is the [member] itself.
+  /// For an instance extension method this is special tear-off function. For
+  /// a constructor, an operator, a factory or a setter this is `null`.
+  Member get readTarget;
 
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  Procedure get procedure;
+  /// The [Member] to use when write to this member builder.
+  ///
+  /// For an assignable field or a setter this is the [member] itself. For
+  /// a constructor, a non-assignable field, a getter, an operator or a regular
+  /// method this is `null`.
+  Member get writeTarget;
+
+  /// The [Member] to use when invoking this member builder.
+  ///
+  /// For a constructor, a field, a regular method, a getter an operator or
+  /// a factory this is the [member] itself. For a setter this is `null`.
+  Member get invokeTarget;
 
   // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
   ProcedureKind get kind;
@@ -106,20 +120,14 @@
 
   // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
   @override
-  Member get extensionTearOff =>
-      unsupported("extensionTearOff", charOffset, fileUri);
-
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  @override
-  Procedure get procedure => unsupported("procedure", charOffset, fileUri);
-
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  @override
   ProcedureKind get kind => unsupported("kind", charOffset, fileUri);
 
   @override
   void buildOutlineExpressions(LibraryBuilder library) {}
 
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f);
+
   @override
   String get fullNameForErrors => name;
 
@@ -135,6 +143,19 @@
   ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
 }
 
+enum BuiltMemberKind {
+  Constructor,
+  RedirectingFactory,
+  Field,
+  Method,
+  ExtensionField,
+  ExtensionMethod,
+  ExtensionGetter,
+  ExtensionSetter,
+  ExtensionOperator,
+  ExtensionTearOff,
+}
+
 class MemberDataForTesting {
   final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
 
diff --git a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
index 16686fb..4fe2571 100644
--- a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
@@ -8,9 +8,12 @@
 
 import '../kernel/load_library_builder.dart' show LoadLibraryBuilder;
 
+import '../fasta_codes.dart';
+
 import '../scope.dart';
 
 import 'builder.dart';
+import 'extension_builder.dart';
 import 'library_builder.dart';
 
 class PrefixBuilder extends BuilderImpl {
@@ -47,6 +50,11 @@
   }
 
   void addToExportScope(String name, Builder member, int charOffset) {
+    if (deferred && member is ExtensionBuilder) {
+      parent.addProblem(templateDeferredExtensionImport.withArguments(name),
+          charOffset, noLength, fileUri);
+    }
+
     Builder existing =
         exportScope.lookupLocalMember(name, setter: member.isSetter);
     Builder result;
@@ -58,6 +66,9 @@
       result = member;
     }
     exportScope.addLocalMember(name, result, setter: member.isSetter);
+    if (result is ExtensionBuilder) {
+      exportScope.addExtension(result);
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 4823b32..766bb6d 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -5,7 +5,7 @@
 import 'dart:core' hide MapEntry;
 
 import 'package:front_end/src/fasta/kernel/kernel_api.dart';
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/type_algebra.dart';
 
@@ -16,7 +16,7 @@
 import '../messages.dart'
     show messageConstFactoryRedirectionToNonConst, noLength;
 
-import '../problems.dart' show unexpected;
+import '../problems.dart' show unexpected, unhandled;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -25,7 +25,9 @@
 import 'extension_builder.dart';
 import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
+import 'member_builder.dart';
 import 'metadata_builder.dart';
+import 'library_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
 
@@ -36,6 +38,10 @@
 
   AsyncMarker actualAsyncModifier;
 
+  Procedure get procedure;
+
+  ProcedureKind get kind;
+
   Procedure get actualProcedure;
 
   bool hadTypesInferred;
@@ -49,8 +55,6 @@
 
   /// Returns `true` if this procedure is declared in an extension declaration.
   bool get isExtensionMethod;
-
-  Procedure build(SourceLibraryBuilder libraryBuilder);
 }
 
 class ProcedureBuilderImpl extends FunctionBuilderImpl
@@ -110,6 +114,49 @@
             compilationUnit, charOffset, nativeMethodName);
 
   @override
+  Member get readTarget {
+    switch (kind) {
+      case ProcedureKind.Method:
+        return extensionTearOff ?? procedure;
+      case ProcedureKind.Getter:
+        return procedure;
+      case ProcedureKind.Operator:
+      case ProcedureKind.Setter:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get writeTarget {
+    switch (kind) {
+      case ProcedureKind.Setter:
+        return procedure;
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get invokeTarget {
+    switch (kind) {
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return procedure;
+      case ProcedureKind.Setter:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
   ProcedureBuilder get origin => actualOrigin ?? this;
 
   @override
@@ -155,6 +202,36 @@
   }
 
   @override
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    if (isExtensionMethod) {
+      switch (kind) {
+        case ProcedureKind.Method:
+          f(member, BuiltMemberKind.ExtensionMethod);
+          break;
+        case ProcedureKind.Getter:
+          f(member, BuiltMemberKind.ExtensionGetter);
+          break;
+        case ProcedureKind.Setter:
+          f(member, BuiltMemberKind.ExtensionSetter);
+          break;
+        case ProcedureKind.Operator:
+          f(member, BuiltMemberKind.ExtensionOperator);
+          break;
+        case ProcedureKind.Factory:
+          throw new UnsupportedError(
+              'Unexpected extension method kind ${kind}');
+      }
+      if (extensionTearOff != null) {
+        f(extensionTearOff, BuiltMemberKind.ExtensionTearOff);
+      }
+    } else {
+      f(member, BuiltMemberKind.Method);
+    }
+  }
+
+  @override
   Procedure build(SourceLibraryBuilder libraryBuilder) {
     // TODO(ahe): I think we may call this twice on parts. Investigate.
     if (_procedure.name == null) {
@@ -244,7 +321,7 @@
       TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
       typeParameters.add(newTypeParameter);
       typeArguments.add(substitutionMap[typeParameter] =
-          new TypeParameterType(newTypeParameter));
+          new TypeParameterType(newTypeParameter, Nullability.legacy));
     }
 
     List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
@@ -354,7 +431,6 @@
   @override
   Procedure get procedure => isPatch ? origin.procedure : _procedure;
 
-  @override
   Procedure get extensionTearOff {
     if (isExtensionInstanceMember && kind == ProcedureKind.Method) {
       _extensionTearOff ??= new Procedure(null, ProcedureKind.Method, null,
@@ -460,8 +536,8 @@
       if (function.typeParameters != null) {
         Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
         for (int i = 0; i < function.typeParameters.length; i++) {
-          substitution[function.typeParameters[i]] =
-              new TypeParameterType(actualOrigin.function.typeParameters[i]);
+          substitution[function.typeParameters[i]] = new TypeParameterType(
+              actualOrigin.function.typeParameters[i], Nullability.legacy);
         }
         List<DartType> newTypeArguments =
             new List<DartType>(typeArguments.length);
@@ -475,6 +551,13 @@
   }
 
   @override
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.RedirectingFactory);
+  }
+
+  @override
   Procedure build(SourceLibraryBuilder library) {
     Procedure result = super.build(library);
     result.isRedirectingFactoryConstructor = true;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index eda4189..4e7da64 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -124,7 +124,7 @@
           name.length,
           fileUri);
     }
-    return new TypeParameterType(parameter, null, nullability);
+    return new TypeParameterType(parameter, nullability);
   }
 
   TypeBuilder asTypeBuilder() {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
index 3992966..707eea5 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
@@ -15,11 +15,10 @@
 class DillExtensionMemberBuilder extends DillMemberBuilder {
   final ExtensionMemberDescriptor _descriptor;
 
-  @override
-  final Member extensionTearOff;
+  final Member _extensionTearOff;
 
   DillExtensionMemberBuilder(Member member, this._descriptor, Builder parent,
-      [this.extensionTearOff])
+      [this._extensionTearOff])
       : super(member, parent);
 
   @override
@@ -28,20 +27,6 @@
   bool get isExternal => member.isExternal;
 
   @override
-  Procedure get procedure {
-    switch (_descriptor.kind) {
-      case ExtensionMemberKind.Method:
-      case ExtensionMemberKind.Getter:
-      case ExtensionMemberKind.Operator:
-      case ExtensionMemberKind.Setter:
-        return member;
-      case ExtensionMemberKind.TearOff:
-      case ExtensionMemberKind.Field:
-    }
-    return unsupported("procedure", charOffset, fileUri);
-  }
-
-  @override
   ProcedureKind get kind {
     switch (_descriptor.kind) {
       case ExtensionMemberKind.Method:
@@ -59,5 +44,57 @@
   }
 
   @override
+  Member get readTarget {
+    if (isField) {
+      return member;
+    }
+    switch (kind) {
+      case ProcedureKind.Method:
+        return _extensionTearOff ?? member;
+      case ProcedureKind.Getter:
+        return member;
+      case ProcedureKind.Operator:
+      case ProcedureKind.Setter:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get writeTarget {
+    if (isField) {
+      return isAssignable ? member : null;
+    }
+    switch (kind) {
+      case ProcedureKind.Setter:
+        return member;
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get invokeTarget {
+    if (isField) {
+      return member;
+    }
+    switch (kind) {
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return member;
+      case ProcedureKind.Setter:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
   bool get isAssignable => member is Field && member.hasSetter;
 }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index 4e3f3ef..d384778 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -9,6 +9,7 @@
 
 import '../builder/builder.dart';
 import '../builder/member_builder.dart';
+import '../builder/library_builder.dart';
 
 import '../kernel/kernel_builder.dart'
     show isRedirectingGenerativeConstructorImplementation;
@@ -63,6 +64,69 @@
 
   @override
   bool get isAssignable => member is Field && member.hasSetter;
+
+  @override
+  Member get readTarget {
+    if (isField) {
+      return member;
+    } else if (isConstructor) {
+      return null;
+    }
+    switch (kind) {
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+        return member;
+      case ProcedureKind.Operator:
+      case ProcedureKind.Setter:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get writeTarget {
+    if (isField) {
+      return isAssignable ? member : null;
+    } else if (isConstructor) {
+      return null;
+    }
+    switch (kind) {
+      case ProcedureKind.Setter:
+        return member;
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  Member get invokeTarget {
+    if (isField) {
+      return member;
+    } else if (isConstructor) {
+      return member;
+    }
+    switch (kind) {
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return member;
+      case ProcedureKind.Setter:
+        return null;
+    }
+    throw unhandled('ProcedureKind', '$kind', charOffset, fileUri);
+  }
+
+  @override
+  void buildMembers(
+      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    throw new UnsupportedError('DillMemberBuilder.buildMembers');
+  }
 }
 
 int computeModifiers(Member member) {
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 a815e0d..377f607 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -22,6 +22,17 @@
         lengthOfSpan,
         optional;
 
+import 'package:_fe_analyzer_shared/src/parser/quote.dart'
+    show
+        Quote,
+        analyzeQuote,
+        unescape,
+        unescapeFirstStringPart,
+        unescapeLastStringPart,
+        unescapeString;
+
+import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
 
 import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
@@ -81,15 +92,6 @@
 import '../problems.dart'
     show internalProblem, unexpected, unhandled, unsupported;
 
-import '../quote.dart'
-    show
-        Quote,
-        analyzeQuote,
-        unescape,
-        unescapeFirstStringPart,
-        unescapeLastStringPart,
-        unescapeString;
-
 import '../scope.dart';
 
 import '../source/scope_listener.dart'
@@ -103,7 +105,7 @@
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import '../source/stack_listener.dart' show offsetForToken;
+import '../source/stack_listener_impl.dart' show offsetForToken;
 
 import '../source/value_kinds.dart';
 
@@ -872,9 +874,8 @@
         }
       }
     }
-
-    typeInferrer?.inferFunctionBody(
-        this, _computeReturnTypeContext(member), asyncModifier, body);
+    typeInferrer?.inferFunctionBody(this, _computeReturnTypeContext(member),
+        asyncModifier, builder.member.function, body);
     if (body != null) {
       libraryBuilder.loader.transformPostInference(
           body, transformSetLiterals, transformCollections);
@@ -1256,7 +1257,7 @@
     ReturnStatementImpl fakeReturn = new ReturnStatementImpl(true, expression);
 
     typeInferrer?.inferFunctionBody(
-        this, const DynamicType(), AsyncMarker.Sync, fakeReturn);
+        this, const DynamicType(), AsyncMarker.Sync, null, fakeReturn);
 
     return fakeReturn.expression;
   }
@@ -1421,14 +1422,14 @@
   @override
   void handleSend(Token beginToken, Token endToken) {
     assert(checkState(beginToken, [
-      ValueKind.ArgumentsOrNull,
-      ValueKind.TypeArgumentsOrNull,
+      ValueKinds.ArgumentsOrNull,
+      ValueKinds.TypeArgumentsOrNull,
       unionOfKinds([
-        ValueKind.Expression,
-        ValueKind.Generator,
-        ValueKind.Identifier,
-        ValueKind.ParserRecovery,
-        ValueKind.ProblemBuilder
+        ValueKinds.Expression,
+        ValueKinds.Generator,
+        ValueKinds.Identifier,
+        ValueKinds.ParserRecovery,
+        ValueKinds.ProblemBuilder
       ])
     ]));
     debugEvent("Send");
@@ -1539,59 +1540,39 @@
 
   void doBinaryExpression(Token token) {
     assert(checkState(token, <ValueKind>[
-      unionOfKinds([ValueKind.Expression, ValueKind.Generator]),
-      unionOfKinds([ValueKind.Expression, ValueKind.Generator]),
+      unionOfKinds([ValueKinds.Expression, ValueKinds.Generator]),
+      unionOfKinds([ValueKinds.Expression, ValueKinds.Generator]),
     ]));
     Expression right = popForValue();
     Object left = pop();
-    bool negate = false;
-    String operator = token.stringValue;
-    if (identical("!=", operator)) {
-      operator = "==";
-      negate = true;
-    }
     int fileOffset = offsetForToken(token);
-    Name name = new Name(operator);
-    if (!isBinaryOperator(operator) && !isMinusOperator(operator)) {
-      if (isUserDefinableOperator(operator)) {
-        push(buildProblem(fasta.templateNotBinaryOperator.withArguments(token),
-            token.charOffset, token.length));
+    String operator = token.stringValue;
+    bool isNot = identical("!=", operator);
+    if (isNot || identical("==", operator)) {
+      if (left is Generator) {
+        push(left.buildEqualsOperation(token, right, isNot: isNot));
       } else {
-        push(buildProblem(fasta.templateInvalidOperator.withArguments(token),
-            token.charOffset, token.length));
+        assert(left is Expression);
+        push(forest.createEquals(fileOffset, left, right, isNot: isNot));
       }
-    } else if (left is ExplicitExtensionAccessGenerator) {
-      // TODO(johnniwinther): Use this code path for all generators. Currently
-      // TypeUseGenerator starts complaining about `Map<` not being a method
-      // instead of `<` not defined on `Type`.
-      Object result = left.buildPropertyAccess(
-          new SendAccessGenerator(this, token, name,
-              forest.createArguments(fileOffset, <Expression>[right]),
-              isPotentiallyConstant: true),
-          fileOffset,
-          false);
-      push(negate ? forest.createNot(fileOffset, toValue(result)) : result);
     } else {
-      bool isSuper = false;
-      Expression leftValue;
-      if (left is ThisAccessGenerator && left.isSuper) {
-        ThisAccessGenerator thisAccessorReceiver = left;
-        isSuper = true;
-        leftValue =
-            forest.createThisExpression(thisAccessorReceiver.fileOffset);
+      Name name = new Name(operator);
+      if (!isBinaryOperator(operator) && !isMinusOperator(operator)) {
+        if (isUserDefinableOperator(operator)) {
+          push(buildProblem(
+              fasta.templateNotBinaryOperator.withArguments(token),
+              token.charOffset,
+              token.length));
+        } else {
+          push(buildProblem(fasta.templateInvalidOperator.withArguments(token),
+              token.charOffset, token.length));
+        }
+      } else if (left is Generator) {
+        push(left.buildBinaryOperation(token, name, right));
       } else {
-        leftValue = toValue(left);
+        assert(left is Expression);
+        push(forest.createBinary(fileOffset, left, name, right));
       }
-      Expression result = buildMethodInvocation(
-          leftValue,
-          name,
-          forest.createArguments(fileOffset, <Expression>[right]),
-          token.charOffset,
-          // This *could* be a constant expression, we can't know without
-          // evaluating [left] and [right].
-          isConstantExpression: !isSuper,
-          isSuper: isSuper);
-      push(negate ? forest.createNot(fileOffset, result) : result);
     }
   }
 
@@ -1852,9 +1833,6 @@
       return new ParserErrorGenerator(this, token, fasta.messageSyntheticToken);
     }
     Builder declaration = scope.lookup(name, charOffset, uri);
-    if (declaration is UnlinkedDeclaration) {
-      return new UnlinkedGenerator(this, token, declaration);
-    }
     if (declaration == null &&
         prefix == null &&
         (classBuilder?.isPatch ?? false)) {
@@ -2566,11 +2544,11 @@
   @override
   void endForStatement(Token endToken) {
     assert(checkState(endToken, <ValueKind>[
-      /* body */ ValueKind.Statement,
-      /* expression count */ ValueKind.Integer,
-      /* left separator */ ValueKind.Token,
-      /* left parenthesis */ ValueKind.Token,
-      /* for keyword */ ValueKind.Token,
+      /* body */ ValueKinds.Statement,
+      /* expression count */ ValueKinds.Integer,
+      /* left separator */ ValueKinds.Token,
+      /* left parenthesis */ ValueKinds.Token,
+      /* for keyword */ ValueKinds.Token,
     ]));
     debugEvent("ForStatement");
     Statement body = popStatement();
@@ -2582,15 +2560,16 @@
 
     assert(checkState(endToken, <ValueKind>[
       /* expressions */ ...repeatedKinds(
-          unionOfKinds(<ValueKind>[ValueKind.Expression, ValueKind.Generator]),
+          unionOfKinds(
+              <ValueKind>[ValueKinds.Expression, ValueKinds.Generator]),
           updateExpressionCount),
-      /* condition */ ValueKind.Statement,
+      /* condition */ ValueKinds.Statement,
       /* variable or expression */ unionOfKinds(<ValueKind>[
-        ValueKind.Generator,
-        ValueKind.ExpressionOrNull,
-        ValueKind.Statement,
-        ValueKind.ObjectList,
-        ValueKind.ParserRecovery,
+        ValueKinds.Generator,
+        ValueKinds.ExpressionOrNull,
+        ValueKinds.Statement,
+        ValueKinds.ObjectList,
+        ValueKinds.ParserRecovery,
       ]),
     ]));
 
@@ -2919,7 +2898,7 @@
   @override
   void handleNonNullAssertExpression(Token bang) {
     assert(checkState(bang, [
-      unionOfKinds([ValueKind.Expression, ValueKind.Generator])
+      unionOfKinds([ValueKinds.Expression, ValueKinds.Generator])
     ]));
     if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullAssertExpressionNotEnabled(bang);
@@ -3438,9 +3417,9 @@
   void handleIndexedExpression(
       Token openSquareBracket, Token closeSquareBracket) {
     assert(checkState(openSquareBracket, [
-      unionOfKinds([ValueKind.Expression, ValueKind.Generator]),
+      unionOfKinds([ValueKinds.Expression, ValueKinds.Generator]),
       unionOfKinds(
-          [ValueKind.Expression, ValueKind.Generator, ValueKind.Initializer])
+          [ValueKinds.Expression, ValueKinds.Generator, ValueKinds.Initializer])
     ]));
     debugEvent("IndexedExpression");
     Expression index = popForValue();
@@ -3449,11 +3428,11 @@
       push(receiver.buildIndexedAccess(index, openSquareBracket));
     } else if (receiver is Expression) {
       push(IndexedAccessGenerator.make(
-          this, openSquareBracket, receiver, index, null, null));
+          this, openSquareBracket, receiver, index));
     } else {
       assert(receiver is Initializer);
       push(IndexedAccessGenerator.make(
-          this, openSquareBracket, toValue(receiver), index, null, null));
+          this, openSquareBracket, toValue(receiver), index));
     }
   }
 
@@ -3461,8 +3440,8 @@
   void handleUnaryPrefixExpression(Token token) {
     assert(checkState(token, <ValueKind>[
       unionOfKinds(<ValueKind>[
-        ValueKind.Expression,
-        ValueKind.Generator,
+        ValueKinds.Expression,
+        ValueKinds.Generator,
       ]),
     ]));
     debugEvent("UnaryPrefixExpression");
@@ -3476,33 +3455,11 @@
       }
       int fileOffset = offsetForToken(token);
       Name name = new Name(operator);
-      if (receiver is ExplicitExtensionAccessGenerator) {
-        // TODO(johnniwinther): Use this code path for all generators. Currently
-        // TypeUseGenerator starts complaining about `-Map` not being a method
-        // instead of `unary-` not defined on `Type`.
-        push(receiver.buildPropertyAccess(
-            new SendAccessGenerator(
-                this, token, name, forest.createArgumentsEmpty(fileOffset),
-                isPotentiallyConstant: true),
-            fileOffset,
-            false));
+      if (receiver is Generator) {
+        push(receiver.buildUnaryOperation(token, name));
       } else {
-        bool isSuper = false;
-        Expression receiverValue;
-        if (receiver is ThisAccessGenerator && receiver.isSuper) {
-          ThisAccessGenerator thisAccessorReceiver = receiver;
-          isSuper = true;
-          receiverValue =
-              forest.createThisExpression(thisAccessorReceiver.fileOffset);
-        } else {
-          receiverValue = toValue(receiver);
-        }
-        push(buildMethodInvocation(receiverValue, name,
-            forest.createArgumentsEmpty(fileOffset), fileOffset,
-            // This *could* be a constant expression, we can't know without
-            // evaluating [receiver].
-            isConstantExpression: !isSuper,
-            isSuper: isSuper));
+        assert(receiver is Expression);
+        push(forest.createUnary(fileOffset, name, receiver));
       }
     }
   }
@@ -3581,13 +3538,13 @@
   /// name.
   void pushQualifiedReference(Token start, Token periodBeforeName) {
     assert(checkState(start, [
-      /*suffix*/ if (periodBeforeName != null) ValueKind.Identifier,
-      /*type arguments*/ ValueKind.TypeArgumentsOrNull,
+      /*suffix*/ if (periodBeforeName != null) ValueKinds.Identifier,
+      /*type arguments*/ ValueKinds.TypeArgumentsOrNull,
       /*type*/ unionOfKinds([
-        ValueKind.Generator,
-        ValueKind.QualifiedName,
-        ValueKind.ProblemBuilder,
-        ValueKind.ParserRecovery
+        ValueKinds.Generator,
+        ValueKinds.QualifiedName,
+        ValueKinds.ProblemBuilder,
+        ValueKinds.ParserRecovery
       ])
     ]));
     Identifier suffix = popIfNotNull(periodBeforeName);
@@ -3600,7 +3557,7 @@
       Object qualifier = qualified.qualifier;
       assert(checkValue(
           start,
-          unionOfKinds([ValueKind.Generator, ValueKind.ProblemBuilder]),
+          unionOfKinds([ValueKinds.Generator, ValueKinds.ProblemBuilder]),
           qualifier));
       if (qualifier is TypeUseGenerator) {
         type = qualifier;
@@ -3635,13 +3592,13 @@
     push(suffix ?? identifier ?? NullValue.Identifier);
 
     assert(checkState(start, [
-      /*constructor name identifier*/ ValueKind.IdentifierOrNull,
-      /*constructor name*/ ValueKind.Name,
-      /*type arguments*/ ValueKind.TypeArgumentsOrNull,
+      /*constructor name identifier*/ ValueKinds.IdentifierOrNull,
+      /*constructor name*/ ValueKinds.Name,
+      /*type arguments*/ ValueKinds.TypeArgumentsOrNull,
       /*class*/ unionOfKinds([
-        ValueKind.Generator,
-        ValueKind.ProblemBuilder,
-        ValueKind.ParserRecovery
+        ValueKinds.Generator,
+        ValueKinds.ProblemBuilder,
+        ValueKinds.ParserRecovery
       ]),
     ]));
   }
@@ -3871,14 +3828,14 @@
   void _buildConstructorReferenceInvocation(
       Token nameToken, int offset, Constness constness) {
     assert(checkState(nameToken, [
-      /*arguments*/ ValueKind.Arguments,
-      /*constructor name identifier*/ ValueKind.IdentifierOrNull,
-      /*constructor name*/ ValueKind.Name,
-      /*type arguments*/ ValueKind.TypeArgumentsOrNull,
+      /*arguments*/ ValueKinds.Arguments,
+      /*constructor name identifier*/ ValueKinds.IdentifierOrNull,
+      /*constructor name*/ ValueKinds.Name,
+      /*type arguments*/ ValueKinds.TypeArgumentsOrNull,
       /*class*/ unionOfKinds([
-        ValueKind.Generator,
-        ValueKind.ProblemBuilder,
-        ValueKind.ParserRecovery
+        ValueKinds.Generator,
+        ValueKinds.ProblemBuilder,
+        ValueKinds.ParserRecovery
       ]),
     ]));
     Arguments arguments = pop();
@@ -4293,6 +4250,9 @@
           ..parent = variable
           ..fileOffset = formals.charOffset;
         exitLocalScope();
+        // This is matched by the call to [beginNode] in [enterFunction].
+        typeInferrer?.assignedVariables
+            ?.endNode(variable.initializer, isClosure: true);
         Expression expression = new NamedFunctionExpressionJudgment(variable);
         if (oldInitializer != null) {
           // This must have been a compile-time error.
@@ -4322,9 +4282,9 @@
         } else {
           push(declaration);
         }
+        // This is matched by the call to [beginNode] in [enterFunction].
+        typeInferrer?.assignedVariables?.endNode(declaration, isClosure: true);
       }
-      // This is matched by the call to [beginNode] in [enterFunction].
-      typeInferrer?.assignedVariables?.endNode(declaration, isClosure: true);
     } else {
       return unhandled("${declaration.runtimeType}", "pushNamedFunction",
           token.charOffset, uri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 42703d9..76a4af6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -159,7 +159,7 @@
   if (typeParameterCount != 0) {
     List<DartType> types = new List<DartType>(typeParameterCount);
     for (int i = 0; i < typeParameterCount; i++) {
-      types[i] = new TypeParameterType(aTypeParameters[i]);
+      types[i] = new TypeParameterType(aTypeParameters[i], Nullability.legacy);
     }
     substitution = Substitution.fromPairs(bTypeParameters, types);
     for (int i = 0; i < typeParameterCount; i++) {
@@ -299,6 +299,7 @@
         // faster to check for `Null` before calling this method.
         return new InterfaceType(
             superclass,
+            Nullability.legacy,
             new List<DartType>.filled(
                 superclass.typeParameters.length, coreTypes.nullType));
       }
@@ -658,7 +659,8 @@
       }
       List<DartType> types = new List<DartType>(typeParameterCount);
       for (int i = 0; i < typeParameterCount; i++) {
-        types[i] = new TypeParameterType(aTypeParameters[i]);
+        types[i] =
+            new TypeParameterType(aTypeParameters[i], Nullability.legacy);
       }
       substitution = Substitution.fromPairs(bTypeParameters, types);
       for (int i = 0; i < typeParameterCount; i++) {
@@ -2018,7 +2020,7 @@
   @override
   InterfaceType futureType(DartType type, Nullability nullability) {
     return new InterfaceType(
-        hierarchy.futureClass, <DartType>[type], nullability);
+        hierarchy.futureClass, nullability, <DartType>[type]);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index cdede9d..fe48a98 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -100,7 +100,6 @@
     TypeEnvironment typeEnvironment,
     ErrorReporter errorReporter,
     {bool keepFields: true,
-    bool keepVariables: false,
     bool evaluateAnnotations: true,
     bool desugarSets: false,
     bool enableTripleShift: false,
@@ -109,7 +108,6 @@
       backend,
       environmentDefines,
       keepFields,
-      keepVariables,
       evaluateAnnotations,
       desugarSets,
       enableTripleShift,
@@ -128,7 +126,6 @@
 
   /// Whether to preserve constant [Field]s.  All use-sites will be rewritten.
   final bool keepFields;
-  final bool keepVariables;
   final bool evaluateAnnotations;
   final bool desugarSets;
   final bool enableTripleShift;
@@ -138,7 +135,6 @@
       this.backend,
       Map<String, String> environmentDefines,
       this.keepFields,
-      this.keepVariables,
       this.evaluateAnnotations,
       this.desugarSets,
       this.enableTripleShift,
@@ -269,6 +265,7 @@
 
   @override
   FunctionNode visitFunctionNode(FunctionNode node) {
+    transformList(node.typeParameters, this, node);
     final int positionalParameterCount = node.positionalParameters.length;
     for (int i = 0; i < positionalParameterCount; ++i) {
       final VariableDeclaration variable = node.positionalParameters[i];
@@ -305,7 +302,7 @@
           ..parent = node;
 
         // If this constant is inlined, remove it.
-        if (!keepVariables && shouldInline(node.initializer)) {
+        if (shouldInline(node.initializer)) {
           if (constant is! UnevaluatedConstant) {
             // If the constant is unevaluated we need to keep the expression,
             // so that, in the case the constant contains error but the local
@@ -2253,6 +2250,9 @@
   bool visitTypedefType(TypedefType node) {
     return node.unalias.accept(this);
   }
+
+  @override
+  bool visitNeverType(NeverType node) => true;
 }
 
 bool _isFormalParameter(VariableDeclaration variable) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 0c2f81f..3fac4c1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -55,7 +55,7 @@
 
 import '../scope.dart';
 
-import '../source/stack_listener.dart' show offsetForToken;
+import '../source/stack_listener_impl.dart' show offsetForToken;
 
 import 'body_builder.dart' show noLocation;
 
@@ -79,7 +79,7 @@
         Procedure,
         VariableDeclaration;
 
-import 'kernel_builder.dart' show LoadLibraryBuilder, UnlinkedDeclaration;
+import 'kernel_builder.dart' show LoadLibraryBuilder;
 
 import 'kernel_shadow_ast.dart';
 
@@ -247,6 +247,24 @@
     }
   }
 
+  /*Expression | Generator*/ buildEqualsOperation(Token token, Expression right,
+      {bool isNot}) {
+    assert(isNot != null);
+    return _forest.createEquals(offsetForToken(token), buildSimpleRead(), right,
+        isNot: isNot);
+  }
+
+  /*Expression | Generator*/ buildBinaryOperation(
+      Token token, Name binaryName, Expression right) {
+    return _forest.createBinary(
+        offsetForToken(token), buildSimpleRead(), binaryName, right);
+  }
+
+  /*Expression | Generator*/ buildUnaryOperation(Token token, Name unaryName) {
+    return _forest.createUnary(
+        offsetForToken(token), unaryName, buildSimpleRead());
+  }
+
   /// Returns a [TypeBuilder] for this subexpression instantiated with the
   /// type [arguments]. If no type arguments are provided [arguments] is `null`.
   ///
@@ -412,8 +430,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -550,8 +567,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   /// Creates a [Generator] for the access of property [name] on [receiver].
@@ -694,8 +710,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -796,8 +811,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -927,8 +941,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -948,12 +961,11 @@
 
   final Expression index;
 
-  final Procedure getter;
+  final bool isNullAware;
 
-  final Procedure setter;
-
-  IndexedAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.receiver, this.index, this.getter, this.setter)
+  IndexedAccessGenerator(
+      ExpressionGeneratorHelper helper, Token token, this.receiver, this.index,
+      {this.isNullAware: false})
       : super(helper, token);
 
   @override
@@ -968,23 +980,14 @@
         receiver,
         indexGetName,
         _helper.forest.createArguments(fileOffset, <Expression>[index]),
-        fileOffset,
-        interfaceTarget: getter);
+        fileOffset);
   }
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    if (voidContext) {
-      return _helper.buildMethodInvocation(
-          receiver,
-          indexSetName,
-          _helper.forest
-              .createArguments(fileOffset, <Expression>[index, value]),
-          fileOffset,
-          interfaceTarget: setter);
-    } else {
-      return new IndexSet(receiver, index, value)..fileOffset = fileOffset;
-    }
+    return new IndexSet(receiver, index, value,
+        forEffect: voidContext, readOnlyReceiver: false)
+      ..fileOffset = fileOffset;
   }
 
   @override
@@ -1034,8 +1037,8 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+        isNullAware: false);
   }
 
   @override
@@ -1045,25 +1048,14 @@
     printNodeOn(receiver, sink, syntheticNames: syntheticNames);
     sink.write(", index: ");
     printNodeOn(index, sink, syntheticNames: syntheticNames);
-    sink.write(", getter: ");
-    printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
-    sink.write(", setter: ");
-    printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
   }
 
-  static Generator make(
-      ExpressionGeneratorHelper helper,
-      Token token,
-      Expression receiver,
-      Expression index,
-      Procedure getter,
-      Procedure setter) {
+  static Generator make(ExpressionGeneratorHelper helper, Token token,
+      Expression receiver, Expression index) {
     if (helper.forest.isThisExpression(receiver)) {
-      return new ThisIndexedAccessGenerator(
-          helper, token, index, getter, setter);
+      return new ThisIndexedAccessGenerator(helper, token, index);
     } else {
-      return new IndexedAccessGenerator(
-          helper, token, receiver, index, getter, setter);
+      return new IndexedAccessGenerator(helper, token, receiver, index);
     }
   }
 }
@@ -1073,12 +1065,8 @@
 class ThisIndexedAccessGenerator extends Generator {
   final Expression index;
 
-  final Procedure getter;
-
-  final Procedure setter;
-
-  ThisIndexedAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.index, this.getter, this.setter)
+  ThisIndexedAccessGenerator(
+      ExpressionGeneratorHelper helper, Token token, this.index)
       : super(helper, token);
 
   @override
@@ -1094,24 +1082,15 @@
         receiver,
         indexGetName,
         _helper.forest.createArguments(fileOffset, <Expression>[index]),
-        fileOffset,
-        interfaceTarget: getter);
+        fileOffset);
   }
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
     Expression receiver = _helper.forest.createThisExpression(fileOffset);
-    if (voidContext) {
-      return _helper.buildMethodInvocation(
-          receiver,
-          indexSetName,
-          _helper.forest
-              .createArguments(fileOffset, <Expression>[index, value]),
-          fileOffset,
-          interfaceTarget: setter);
-    } else {
-      return new IndexSet(receiver, index, value)..fileOffset = fileOffset;
-    }
+    return new IndexSet(receiver, index, value,
+        forEffect: voidContext, readOnlyReceiver: true)
+      ..fileOffset = fileOffset;
   }
 
   @override
@@ -1165,8 +1144,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -1174,10 +1152,6 @@
     NameSystem syntheticNames = new NameSystem();
     sink.write(", index: ");
     printNodeOn(index, sink, syntheticNames: syntheticNames);
-    sink.write(", getter: ");
-    printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
-    sink.write(", setter: ");
-    printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
   }
 }
 
@@ -1273,8 +1247,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -1466,8 +1439,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -1569,21 +1541,21 @@
     if (getterBuilder != null) {
       if (getterBuilder.isGetter) {
         assert(!getterBuilder.isStatic);
-        readTarget = getterBuilder.member;
+        readTarget = getterBuilder.readTarget;
       } else if (getterBuilder.isRegularMethod) {
         assert(!getterBuilder.isStatic);
-        readTarget = getterBuilder.extensionTearOff;
-        invokeTarget = getterBuilder.procedure;
+        readTarget = getterBuilder.readTarget;
+        invokeTarget = getterBuilder.invokeTarget;
       } else if (getterBuilder is FunctionBuilder && getterBuilder.isOperator) {
         assert(!getterBuilder.isStatic);
-        invokeTarget = getterBuilder.member;
+        invokeTarget = getterBuilder.invokeTarget;
       }
     }
     Procedure writeTarget;
     if (setterBuilder != null) {
       if (setterBuilder.isSetter) {
         assert(!setterBuilder.isStatic);
-        writeTarget = setterBuilder.member;
+        writeTarget = setterBuilder.writeTarget;
         targetName ??= setterBuilder.name;
       } else {
         return unhandled(
@@ -1750,8 +1722,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -1880,16 +1851,16 @@
       } else if (getterBuilder.isGetter) {
         assert(!getterBuilder.isStatic);
         MemberBuilder memberBuilder = getterBuilder;
-        readTarget = memberBuilder.member;
+        readTarget = memberBuilder.readTarget;
       } else if (getterBuilder.isRegularMethod) {
         assert(!getterBuilder.isStatic);
         MemberBuilder procedureBuilder = getterBuilder;
-        readTarget = procedureBuilder.extensionTearOff;
-        invokeTarget = procedureBuilder.procedure;
+        readTarget = procedureBuilder.readTarget;
+        invokeTarget = procedureBuilder.invokeTarget;
       } else if (getterBuilder is FunctionBuilder && getterBuilder.isOperator) {
         assert(!getterBuilder.isStatic);
         MemberBuilder memberBuilder = getterBuilder;
-        invokeTarget = memberBuilder.member;
+        invokeTarget = memberBuilder.invokeTarget;
       } else {
         return unhandled(
             "${getterBuilder.runtimeType}",
@@ -1906,7 +1877,7 @@
       } else if (setterBuilder.isSetter) {
         assert(!setterBuilder.isStatic);
         MemberBuilder memberBuilder = setterBuilder;
-        writeTarget = memberBuilder.member;
+        writeTarget = memberBuilder.writeTarget;
       } else {
         return unhandled(
             "${setterBuilder.runtimeType}",
@@ -2169,8 +2140,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -2374,8 +2344,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -2467,7 +2436,8 @@
     return _makeInvalidRead();
   }
 
-  Generator _createInstanceAccess(Token token, Name name, {bool isNullAware}) {
+  Generator _createInstanceAccess(Token token, Name name,
+      {bool isNullAware: false}) {
     Builder getter = extensionBuilder.lookupLocalMemberByName(name);
     if (getter != null && (getter.isStatic || getter.isField)) {
       getter = null;
@@ -2513,9 +2483,24 @@
   }
 
   @override
+  buildBinaryOperation(Token token, Name binaryName, Expression right) {
+    int fileOffset = offsetForToken(token);
+    Generator generator = _createInstanceAccess(token, binaryName);
+    return generator.doInvocation(
+        fileOffset, _forest.createArguments(fileOffset, <Expression>[right]));
+  }
+
+  @override
+  buildUnaryOperation(Token token, Name unaryName) {
+    int fileOffset = offsetForToken(token);
+    Generator generator = _createInstanceAccess(token, unaryName);
+    return generator.doInvocation(
+        fileOffset, _forest.createArgumentsEmpty(fileOffset));
+  }
+
+  @override
   doInvocation(int offset, Arguments arguments) {
-    Generator generator =
-        _createInstanceAccess(token, callName, isNullAware: false);
+    Generator generator = _createInstanceAccess(token, callName);
     return generator.doInvocation(offset, arguments);
   }
 
@@ -2641,8 +2626,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -2770,11 +2754,15 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
-    return _helper.wrapInDeferredCheck(
-        suffixGenerator.doInvocation(offset, arguments),
-        prefixGenerator.prefix,
-        token.charOffset);
+  doInvocation(int offset, Arguments arguments) {
+    Object suffix = suffixGenerator.doInvocation(offset, arguments);
+    if (suffix is Expression) {
+      return _helper.wrapInDeferredCheck(
+          suffix, prefixGenerator.prefix, fileOffset);
+    } else {
+      return new DeferredAccessGenerator(
+          _helper, token, prefixGenerator, suffix);
+    }
   }
 
   @override
@@ -2794,8 +2782,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -3071,7 +3058,9 @@
   String get _plainNameForRead => targetName;
 
   @override
-  Expression buildSimpleRead() => expression;
+  Expression buildSimpleRead() => _createRead();
+
+  Expression _createRead() => expression;
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
@@ -3081,7 +3070,7 @@
   @override
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
-    Expression read = buildSimpleRead();
+    Expression read = _createRead();
     Expression write = _makeInvalidWrite(value);
     return new IfNullSet(read, write, forEffect: voidContext)
       ..fileOffset = offset;
@@ -3096,7 +3085,7 @@
       bool isPostIncDec: false}) {
     MethodInvocation binary = _helper.forest.createMethodInvocation(
         offset,
-        buildSimpleRead(),
+        _createRead(),
         binaryOperator,
         _helper.forest.createArguments(offset, <Expression>[value]),
         interfaceTarget: interfaceTarget);
@@ -3118,7 +3107,7 @@
 
   @override
   doInvocation(int offset, Arguments arguments) {
-    return _helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
+    return _helper.buildMethodInvocation(_createRead(), callName, arguments,
         adjustForImplicitCall(targetName, offset),
         isImplicitCall: true);
   }
@@ -3127,8 +3116,7 @@
   Generator buildIndexedAccess(Expression index, Token token) {
     // TODO(johnniwinther): The read-only quality of the variable should be
     // passed on to the generator.
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, _createRead(), index);
   }
 
   @override
@@ -3256,8 +3244,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 }
 
@@ -3334,121 +3321,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
-  }
-}
-
-class UnlinkedGenerator extends Generator {
-  final UnlinkedDeclaration declaration;
-
-  final Expression receiver;
-
-  final Name name;
-
-  UnlinkedGenerator(
-      ExpressionGeneratorHelper helper, Token token, this.declaration)
-      : name = new Name(declaration.name, helper.libraryBuilder.library),
-        receiver = new InvalidExpression(declaration.name)
-          ..fileOffset = offsetForToken(token),
-        super(helper, token);
-
-  @override
-  String get _plainNameForRead => declaration.name;
-
-  @override
-  String get _debugName => "UnlinkedGenerator";
-
-  @override
-  void printOn(StringSink sink) {
-    sink.write(", name: ");
-    sink.write(declaration.name);
-  }
-
-  @override
-  Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    return _helper.forest.createPropertySet(fileOffset, receiver, name, value,
-        forEffect: voidContext);
-  }
-
-  @override
-  Expression buildSimpleRead() {
-    return _forest.createPropertyGet(fileOffset, receiver, name);
-  }
-
-  @override
-  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
-      {bool voidContext: false}) {
-    VariableDeclaration variable =
-        _helper.forest.createVariableDeclarationForValue(receiver);
-    PropertyGet read = _forest.createPropertyGet(fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset), name);
-    PropertySet write = _helper.forest.createPropertySet(fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset), name, value,
-        forEffect: voidContext);
-    return new IfNullPropertySet(variable, read, write, forEffect: voidContext)
-      ..fileOffset = offset;
-  }
-
-  @override
-  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
-      {int offset: TreeNode.noOffset,
-      bool voidContext: false,
-      Procedure interfaceTarget,
-      bool isPreIncDec: false,
-      bool isPostIncDec: false}) {
-    return new CompoundPropertySet(receiver, name, binaryOperator, value,
-        forEffect: voidContext,
-        readOnlyReceiver: false,
-        readOffset: fileOffset,
-        binaryOffset: offset,
-        writeOffset: fileOffset)
-      ..fileOffset = offset;
-  }
-
-  @override
-  Expression buildPostfixIncrement(Name binaryOperator,
-      {int offset = TreeNode.noOffset,
-      bool voidContext = false,
-      Procedure interfaceTarget}) {
-    Expression value = _forest.createIntLiteral(offset, 1);
-    if (voidContext) {
-      return buildCompoundAssignment(binaryOperator, value,
-          offset: offset,
-          voidContext: voidContext,
-          interfaceTarget: interfaceTarget,
-          isPostIncDec: true);
-    }
-    VariableDeclaration variable =
-        _helper.forest.createVariableDeclarationForValue(receiver);
-    VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
-        _forest.createPropertyGet(fileOffset,
-            _helper.createVariableGet(variable, receiver.fileOffset), name));
-    MethodInvocation binary = _helper.forest.createMethodInvocation(
-        offset,
-        _helper.createVariableGet(read, fileOffset),
-        binaryOperator,
-        _helper.forest.createArguments(offset, <Expression>[value]),
-        interfaceTarget: interfaceTarget);
-    VariableDeclaration write = _helper.forest
-        .createVariableDeclarationForValue(_helper.forest.createPropertySet(
-            fileOffset,
-            _helper.createVariableGet(variable, receiver.fileOffset),
-            name,
-            binary,
-            forEffect: true));
-    return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
-  }
-
-  @override
-  Expression doInvocation(int offset, Arguments arguments) {
-    return unsupported("doInvocation", offset, _uri);
-  }
-
-  @override
-  Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 }
 
@@ -3515,8 +3388,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 }
 
@@ -3760,8 +3632,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -3851,8 +3722,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 
   @override
@@ -3960,8 +3830,7 @@
 
   @override
   Generator buildIndexedAccess(Expression index, Token token) {
-    return new IndexedAccessGenerator(
-        _helper, token, buildSimpleRead(), index, null, null);
+    return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
   }
 }
 
@@ -4122,6 +3991,56 @@
     }
   }
 
+  @override
+  buildEqualsOperation(Token token, Expression right, {bool isNot}) {
+    assert(isNot != null);
+    if (isSuper) {
+      int offset = offsetForToken(token);
+      Expression result = _helper.buildMethodInvocation(
+          _forest.createThisExpression(fileOffset),
+          equalsName,
+          _forest.createArguments(offset, <Expression>[right]),
+          offset,
+          isSuper: true,
+          isImplicitCall: false);
+      if (isNot) {
+        result = _forest.createNot(offset, result);
+      }
+      return result;
+    }
+    return super.buildEqualsOperation(token, right, isNot: isNot);
+  }
+
+  @override
+  buildBinaryOperation(Token token, Name binaryName, Expression right) {
+    if (isSuper) {
+      int offset = offsetForToken(token);
+      return _helper.buildMethodInvocation(
+          _forest.createThisExpression(fileOffset),
+          binaryName,
+          _forest.createArguments(offset, <Expression>[right]),
+          offset,
+          isSuper: true,
+          isImplicitCall: false);
+    }
+    return super.buildBinaryOperation(token, binaryName, right);
+  }
+
+  @override
+  buildUnaryOperation(Token token, Name unaryName) {
+    if (isSuper) {
+      int offset = offsetForToken(token);
+      return _helper.buildMethodInvocation(
+          _forest.createThisExpression(fileOffset),
+          unaryName,
+          _forest.createArgumentsEmpty(offset),
+          offset,
+          isSuper: true,
+          isImplicitCall: false);
+    }
+    return super.buildUnaryOperation(token, unaryName);
+  }
+
   Initializer buildConstructorInitializer(
       int offset, Name name, Arguments arguments) {
     Constructor constructor = _helper.lookupConstructor(name, isSuper: isSuper);
@@ -4200,7 +4119,7 @@
           _helper.lookupInstanceMember(indexGetName, isSuper: true),
           _helper.lookupInstanceMember(indexSetName, isSuper: true));
     } else {
-      return new ThisIndexedAccessGenerator(_helper, token, index, null, null);
+      return new ThisIndexedAccessGenerator(_helper, token, index);
     }
   }
 
@@ -4434,17 +4353,57 @@
   }
 }
 
+/// [ParenthesizedExpressionGenerator] represents the subexpression whose prefix
+/// is a parenthesized expression.
+///
+/// For instance:
+///
+///   method(final a) {
+///     final b = null;
+///     (a);           // this generator is created for `(a)`.
+///     (a)[];         // this generator is created for `(a)`.
+///     (b)();         // this generator is created for `(b)`.
+///     (b).c = (a.d); // this generator is created for `(a.d)` and `(b)`.
+///   }
+///
+// TODO(johnniwinther): Remove this in favor of [ParenthesizedExpression] when
+// the [TypePromoter] is replaced by [FlowAnalysis].
 class ParenthesizedExpressionGenerator extends ReadOnlyAccessGenerator {
   ParenthesizedExpressionGenerator(
       ExpressionGeneratorHelper helper, Token token, Expression expression)
       : super(helper, token, expression, null);
 
+  @override
+  Expression buildSimpleRead() => expression;
+
+  @override
+  Expression _createRead() =>
+      _helper.forest.createParenthesized(fileOffset, expression);
+
   String get _debugName => "ParenthesizedExpressionGenerator";
 
   Expression _makeInvalidWrite(Expression value) {
     return _helper.buildProblem(messageCannotAssignToParenthesizedExpression,
         fileOffset, lengthForToken(token));
   }
+
+  /* Expression | Generator */ buildPropertyAccess(
+      IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
+    if (send is SendAccessGenerator) {
+      return _helper.buildMethodInvocation(
+          _createRead(), send.name, send.arguments, offsetForToken(send.token),
+          isNullAware: isNullAware,
+          isConstantExpression: send.isPotentiallyConstant);
+    } else {
+      if (_helper.constantContext != ConstantContext.none &&
+          send.name != lengthName) {
+        _helper.addProblem(
+            messageNotAConstantExpression, fileOffset, token.length);
+      }
+      return PropertyAccessGenerator.make(
+          _helper, send.token, _createRead(), send.name, isNullAware);
+    }
+  }
 }
 
 Expression makeLet(VariableDeclaration variable, Expression body) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 6d4a8a5..0b0b77f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -608,7 +608,7 @@
   }
 
   TypeParameterType createTypeParameterType(TypeParameter typeParameter) {
-    return new TypeParameterType(typeParameter);
+    return new TypeParameterType(typeParameter, Nullability.legacy);
   }
 
   FunctionExpression createFunctionExpression(
@@ -675,6 +675,34 @@
         readOnlyReceiver: readOnlyReceiver)
       ..fileOffset = fileOffset;
   }
+
+  EqualsExpression createEquals(
+      int fileOffset, Expression left, Expression right,
+      {bool isNot}) {
+    assert(fileOffset != null);
+    assert(isNot != null);
+    return new EqualsExpression(left, right, isNot: isNot)
+      ..fileOffset = fileOffset;
+  }
+
+  BinaryExpression createBinary(
+      int fileOffset, Expression left, Name binaryName, Expression right) {
+    assert(fileOffset != null);
+    return new BinaryExpression(left, binaryName, right)
+      ..fileOffset = fileOffset;
+  }
+
+  UnaryExpression createUnary(
+      int fileOffset, Name unaryName, Expression expression) {
+    assert(fileOffset != null);
+    return new UnaryExpression(unaryName, expression)..fileOffset = fileOffset;
+  }
+
+  ParenthesizedExpression createParenthesized(
+      int fileOffset, Expression expression) {
+    assert(fileOffset != null);
+    return new ParenthesizedExpression(expression)..fileOffset = fileOffset;
+  }
 }
 
 class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 3c9d8f2c..958b6c0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -13,6 +13,7 @@
         Member,
         Name,
         NamedExpression,
+        Nullability,
         Procedure,
         ProcedureKind,
         ReturnStatement,
@@ -23,6 +24,7 @@
         TypeParameterType,
         VariableDeclaration,
         VariableGet,
+        Variance,
         VoidType;
 
 import 'package:kernel/transformations/flags.dart' show TransformerFlag;
@@ -34,7 +36,7 @@
 import "../problems.dart" show unhandled;
 
 import "../type_inference/type_inference_engine.dart"
-    show IncludesTypeParametersNonCovariantly, Variance;
+    show IncludesTypeParametersNonCovariantly;
 
 import "../type_inference/type_inferrer.dart" show getNamedFormal;
 
@@ -269,7 +271,8 @@
             new NamedExpression(parameter.name, new VariableGet(parameter)))
         .toList();
     List<DartType> typeArguments = function.typeParameters
-        .map<DartType>((typeParameter) => new TypeParameterType(typeParameter))
+        .map<DartType>((typeParameter) =>
+            new TypeParameterType(typeParameter, Nullability.legacy))
         .toList();
     Arguments arguments = new Arguments(positionalArguments,
         types: typeArguments, named: namedArguments);
@@ -319,7 +322,7 @@
           ..isGenericCovariantImpl = targetTypeParameter.isGenericCovariantImpl;
         typeParameters[i] = typeParameter;
         additionalSubstitution[targetTypeParameter] =
-            new TypeParameterType(typeParameter);
+            new TypeParameterType(typeParameter, Nullability.legacy);
       }
       substitution = Substitution.combine(
           substitution, Substitution.fromMap(additionalSubstitution));
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index b411490..f1f9283 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -37,68 +37,6 @@
   @override
   ExpressionInferenceResult defaultExpression(
       Expression node, DartType typeContext) {
-    if (node is InternalExpression) {
-      switch (node.kind) {
-        case InternalExpressionKind.Cascade:
-          return visitCascade(node, typeContext);
-        case InternalExpressionKind.CompoundExtensionIndexSet:
-          return visitCompoundExtensionIndexSet(node, typeContext);
-        case InternalExpressionKind.CompoundExtensionSet:
-          return visitCompoundExtensionSet(node, typeContext);
-        case InternalExpressionKind.CompoundIndexSet:
-          return visitCompoundIndexSet(node, typeContext);
-        case InternalExpressionKind.CompoundPropertySet:
-          return visitCompoundPropertySet(node, typeContext);
-        case InternalExpressionKind.CompoundSuperIndexSet:
-          return visitCompoundSuperIndexSet(node, typeContext);
-        case InternalExpressionKind.DeferredCheck:
-          return visitDeferredCheck(node, typeContext);
-        case InternalExpressionKind.ExtensionIndexSet:
-          return visitExtensionIndexSet(node, typeContext);
-        case InternalExpressionKind.ExtensionTearOff:
-          return visitExtensionTearOff(node, typeContext);
-        case InternalExpressionKind.ExtensionSet:
-          return visitExtensionSet(node, typeContext);
-        case InternalExpressionKind.IfNull:
-          return visitIfNullExpression(node, typeContext);
-        case InternalExpressionKind.IfNullExtensionIndexSet:
-          return visitIfNullExtensionIndexSet(node, typeContext);
-        case InternalExpressionKind.IfNullIndexSet:
-          return visitIfNullIndexSet(node, typeContext);
-        case InternalExpressionKind.IfNullPropertySet:
-          return visitIfNullPropertySet(node, typeContext);
-        case InternalExpressionKind.IfNullSet:
-          return visitIfNullSet(node, typeContext);
-        case InternalExpressionKind.IfNullSuperIndexSet:
-          return visitIfNullSuperIndexSet(node, typeContext);
-        case InternalExpressionKind.IndexSet:
-          return visitIndexSet(node, typeContext);
-        case InternalExpressionKind.LoadLibraryTearOff:
-          return visitLoadLibraryTearOff(node, typeContext);
-        case InternalExpressionKind.LocalPostIncDec:
-          return visitLocalPostIncDec(node, typeContext);
-        case InternalExpressionKind.NullAwareCompoundSet:
-          return visitNullAwareCompoundSet(node, typeContext);
-        case InternalExpressionKind.NullAwareExtension:
-          return visitNullAwareExtension(node, typeContext);
-        case InternalExpressionKind.NullAwareIfNullSet:
-          return visitNullAwareIfNullSet(node, typeContext);
-        case InternalExpressionKind.NullAwareMethodInvocation:
-          return visitNullAwareMethodInvocation(node, typeContext);
-        case InternalExpressionKind.NullAwarePropertyGet:
-          return visitNullAwarePropertyGet(node, typeContext);
-        case InternalExpressionKind.NullAwarePropertySet:
-          return visitNullAwarePropertySet(node, typeContext);
-        case InternalExpressionKind.PropertyPostIncDec:
-          return visitPropertyPostIncDec(node, typeContext);
-        case InternalExpressionKind.StaticPostIncDec:
-          return visitStaticPostIncDec(node, typeContext);
-        case InternalExpressionKind.SuperIndexSet:
-          return visitSuperIndexSet(node, typeContext);
-        case InternalExpressionKind.SuperPostIncDec:
-          return visitSuperPostIncDec(node, typeContext);
-      }
-    }
     return _unhandledExpression(node, typeContext);
   }
 
@@ -231,6 +169,7 @@
         node.operand, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: true);
     node.operand = operandResult.expression..parent = node;
+    inferrer.flowAnalysis.asExpression_end(node.operand, node.type);
     return new ExpressionInferenceResult(node.type, node);
   }
 
@@ -241,9 +180,9 @@
 
   @override
   void visitAssertStatement(AssertStatement node) {
+    inferrer.flowAnalysis.assert_begin();
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    inferrer.flowAnalysis.assert_begin();
     ExpressionInferenceResult conditionResult = inferrer.inferExpression(
         node.condition, expectedType, !inferrer.isTopLevel,
         isVoidAllowed: true);
@@ -293,7 +232,8 @@
 
   @override
   void visitBreakStatement(BreakStatement node) {
-    // No inference needs to be done.
+    // TODO(johnniwinther): Refactor break/continue encoding.
+    inferrer.flowAnalysis.handleBreak(node.target);
   }
 
   ExpressionInferenceResult visitCascade(Cascade node, DartType typeContext) {
@@ -421,7 +361,7 @@
       ExtensionTearOff node, DartType typeContext) {
     FunctionType calleeType = node.target != null
         ? node.target.function.functionType
-        : new FunctionType([], const DynamicType());
+        : new FunctionType([], const DynamicType(), Nullability.legacy);
     TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
     DartType inferredType = inferrer.inferInvocation(
         typeContext, node.fileOffset, calleeType, node.arguments);
@@ -980,6 +920,7 @@
 
   @override
   void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
+    inferrer.flowAnalysis.functionExpression_begin(node);
     inferrer.inferMetadataKeepingHelper(
         node.variable, node.variable.annotations);
     DartType returnContext =
@@ -987,13 +928,16 @@
     DartType inferredType =
         visitFunctionNode(node.function, null, returnContext, node.fileOffset);
     node.variable.type = inferredType;
+    inferrer.flowAnalysis.functionExpression_end();
   }
 
   @override
   ExpressionInferenceResult visitFunctionExpression(
       FunctionExpression node, DartType typeContext) {
+    inferrer.flowAnalysis.functionExpression_begin(node);
     DartType inferredType =
         visitFunctionNode(node.function, typeContext, null, node.fileOffset);
+    inferrer.flowAnalysis.functionExpression_end();
     return new ExpressionInferenceResult(inferredType, node);
   }
 
@@ -1024,6 +968,7 @@
             lhsResult.inferredType, equalsName, node.fileOffset)
         .member;
 
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(node.left);
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
     ExpressionInferenceResult rhsResult;
@@ -1035,6 +980,8 @@
       rhsResult = inferrer.inferExpression(node.right, typeContext, true,
           isVoidAllowed: true);
     }
+    inferrer.flowAnalysis.ifNullExpression_end();
+
     // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
     //   UP(t0, t1)
     // - Then the inferred type is T.
@@ -1146,6 +1093,8 @@
         node.operand, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: false);
     node.operand = operandResult.expression..parent = node;
+    inferrer.flowAnalysis
+        .isExpression_end(node, node.operand, /*isNot:*/ false, node.type);
     return new ExpressionInferenceResult(
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), node);
   }
@@ -1180,7 +1129,7 @@
       ExpressionInferenceResult spreadResult = inferrer.inferExpression(
           element.expression,
           new InterfaceType(inferrer.coreTypes.iterableClass,
-              <DartType>[inferredTypeArgument]),
+              Nullability.legacy, <DartType>[inferredTypeArgument]),
           inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
       element.expression = spreadResult.expression..parent = element;
@@ -1460,8 +1409,8 @@
             inferredSpreadTypes, inferredConditionTypes);
       }
     }
-    DartType inferredType =
-        new InterfaceType(listClass, [inferredTypeArgument]);
+    DartType inferredType = new InterfaceType(
+        listClass, Nullability.legacy, [inferredTypeArgument]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (inferenceNeeded) {
@@ -1482,13 +1431,17 @@
     ExpressionInferenceResult leftResult = inferrer.inferExpression(
         node.left, boolType, !inferrer.isTopLevel,
         isVoidAllowed: false);
+    Expression left = inferrer.ensureAssignableResult(boolType, leftResult);
+    node.left = left..parent = node;
+    inferrer.flowAnalysis
+        .logicalBinaryOp_rightBegin(node.left, isAnd: node.operator == '&&');
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         node.right, boolType, !inferrer.isTopLevel,
         isVoidAllowed: false);
-    Expression left = inferrer.ensureAssignableResult(boolType, leftResult);
-    node.left = left..parent = node;
     Expression right = inferrer.ensureAssignableResult(boolType, rightResult);
     node.right = right..parent = node;
+    inferrer.flowAnalysis
+        .logicalBinaryOp_end(node, node.right, isAnd: node.operator == '&&');
     return new ExpressionInferenceResult(boolType, node);
   }
 
@@ -1611,8 +1564,8 @@
       mapEntryClass ??=
           inferrer.coreTypes.index.getClass('dart:core', 'MapEntry');
       // TODO(dmitryas):  Handle the case of an ambiguous Set.
-      entry.entryType = new InterfaceType(
-          mapEntryClass, <DartType>[actualKeyType, actualValueType]);
+      entry.entryType = new InterfaceType(mapEntryClass, Nullability.legacy,
+          <DartType>[actualKeyType, actualValueType]);
 
       bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
           spreadType,
@@ -1936,7 +1889,7 @@
             .getTypeAsInstanceOf(typeContext, inferrer.coreTypes.iterableClass);
       } else if (!typeContextIsIterable && typeContextIsMap) {
         spreadTypeContext = new InterfaceType(inferrer.coreTypes.mapClass,
-            <DartType>[inferredKeyType, inferredValueType]);
+            Nullability.legacy, <DartType>[inferredKeyType, inferredValueType]);
       }
       for (int index = 0; index < node.entries.length; ++index) {
         MapEntry entry = node.entries[index];
@@ -2012,8 +1965,8 @@
           }
         }
 
-        DartType inferredType =
-            new InterfaceType(inferrer.coreTypes.setClass, inferredTypesForSet);
+        DartType inferredType = new InterfaceType(inferrer.coreTypes.setClass,
+            Nullability.legacy, inferredTypesForSet);
         return new ExpressionInferenceResult(inferredType, setLiteral);
       }
       if (canBeSet && canBeMap && node.entries.isNotEmpty) {
@@ -2054,8 +2007,8 @@
         node.entries[index] = entry..parent = node;
       }
     }
-    DartType inferredType =
-        new InterfaceType(mapClass, [inferredKeyType, inferredValueType]);
+    DartType inferredType = new InterfaceType(
+        mapClass, Nullability.legacy, [inferredKeyType, inferredValueType]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
@@ -2160,6 +2113,7 @@
         boolType, operandResult,
         fileOffset: node.fileOffset);
     node.operand = operand..parent = node;
+    inferrer.flowAnalysis.logicalNot_end(node, node.operand);
     return new ExpressionInferenceResult(boolType, node);
   }
 
@@ -2173,6 +2127,7 @@
     node.operand = operandResult.expression..parent = node;
     // TODO(johnniwinther): Check that the inferred type is potentially
     //  nullable.
+    inferrer.flowAnalysis.nonNullAssert_end(node.operand);
     // TODO(johnniwinther): Return `NonNull(inferredType)`.
     return new ExpressionInferenceResult(operandResult.inferredType, node);
   }
@@ -2467,8 +2422,11 @@
       receiver = receiverResult.expression;
     }
     DartType receiverType = receiverResult.inferredType;
-    VariableDeclaration receiverVariable =
-        createVariable(receiver, receiverType);
+    VariableDeclaration receiverVariable;
+    if (!node.forEffect && !node.readOnlyReceiver) {
+      receiverVariable = createVariable(receiver, receiverType);
+      receiver = createVariableGet(receiverVariable);
+    }
 
     ObjectAccessTarget indexSetTarget = inferrer.findInterfaceMember(
         receiverType, indexSetName, node.fileOffset,
@@ -2483,38 +2441,46 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    VariableDeclaration indexVariable =
-        createVariable(index, indexResult.inferredType);
+    VariableDeclaration indexVariable;
+    if (!node.forEffect) {
+      indexVariable = createVariable(index, indexResult.inferredType);
+      index = createVariableGet(indexVariable);
+    }
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
-    VariableDeclaration valueVariable =
-        createVariable(value, valueResult.inferredType);
+
+    VariableDeclaration valueVariable;
+    if (!node.forEffect) {
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+    }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
     Expression assignment = _computeIndexSet(
-        node.fileOffset,
-        createVariableGet(receiverVariable),
-        receiverType,
-        indexSetTarget,
-        createVariableGet(indexVariable),
-        createVariableGet(valueVariable));
+        node.fileOffset, receiver, receiverType, indexSetTarget, index, value);
 
-    VariableDeclaration assignmentVariable =
-        createVariable(assignment, const VoidType());
-    Expression replacement = new Let(
-        receiverVariable,
-        createLet(
-            indexVariable,
-            createLet(
-                valueVariable,
-                createLet(
-                    assignmentVariable, createVariableGet(valueVariable))))
-          ..fileOffset = node.fileOffset);
+    Expression replacement;
+    if (node.forEffect) {
+      replacement = assignment;
+    } else {
+      assert(indexVariable != null);
+      assert(valueVariable != null);
+      VariableDeclaration assignmentVariable =
+          createVariable(assignment, const VoidType());
+      replacement = createLet(
+          indexVariable,
+          createLet(valueVariable,
+              createLet(assignmentVariable, createVariableGet(valueVariable))));
+      if (receiverVariable != null) {
+        replacement = createLet(receiverVariable, replacement);
+      }
+    }
+    replacement..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult.nullAware(
         inferredType, replacement, nullAwareGuard);
   }
@@ -3076,6 +3042,53 @@
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
+  /// Creates an equals expression of using [left] and [right] as operands.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [leftType] is
+  /// the already inferred type of the [left] expression. The inferred type of
+  /// [right] is computed by this method. If [isNot] is `true` the result is
+  /// negated to perform a != operation.
+  ExpressionInferenceResult _computeEqualsExpression(
+      int fileOffset, Expression left, DartType leftType, Expression right,
+      {bool isNot}) {
+    assert(isNot != null);
+    inferrer.flowAnalysis.equalityOp_rightBegin(left);
+    ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
+        leftType, equalsName, fileOffset,
+        includeExtensionMethods: true);
+
+    bool typeNeeded = !inferrer.isTopLevel;
+    ExpressionInferenceResult rightResult = inferrer.inferExpression(
+        right, const UnknownType(), typeNeeded,
+        isVoidAllowed: false);
+    right = rightResult.expression;
+
+    assert(equalsTarget.isInstanceMember);
+    if (inferrer.instrumentation != null && leftType == const DynamicType()) {
+      inferrer.instrumentation.record(
+          inferrer.uriForInstrumentation,
+          fileOffset,
+          'target',
+          new InstrumentationValueForMember(equalsTarget.member));
+    }
+
+    Expression equals = new MethodInvocation(
+        left,
+        equalsName,
+        new Arguments(<Expression>[
+          right,
+        ])
+          ..fileOffset = fileOffset,
+        equalsTarget.member)
+      ..fileOffset = fileOffset;
+    if (isNot) {
+      equals = new Not(equals)..fileOffset = fileOffset;
+    }
+    inferrer.flowAnalysis.equalityOp_end(equals, right, notEqual: isNot);
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), equals);
+  }
+
   /// Creates a binary expression of the binary operator with [binaryName] using
   /// [left] and [right] as operands.
   ///
@@ -3084,6 +3097,8 @@
   /// [right] is computed by this method.
   ExpressionInferenceResult _computeBinaryExpression(int fileOffset,
       Expression left, DartType leftType, Name binaryName, Expression right) {
+    assert(binaryName != equalsName);
+
     ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
         leftType, binaryName, fileOffset,
         includeExtensionMethods: true);
@@ -3096,12 +3111,25 @@
     DartType rightType =
         inferrer.getPositionalParameterTypeForTarget(binaryTarget, leftType, 0);
 
-    ExpressionInferenceResult rightResult =
-        inferrer.inferExpression(right, rightType, true, isVoidAllowed: true);
+    bool isOverloadedArithmeticOperatorAndType =
+        inferrer.isOverloadedArithmeticOperatorAndType(binaryTarget, leftType);
+
+    bool typeNeeded =
+        !inferrer.isTopLevel || isOverloadedArithmeticOperatorAndType;
+    ExpressionInferenceResult rightResult = inferrer
+        .inferExpression(right, rightType, typeNeeded, isVoidAllowed: true);
+    if (rightResult.inferredType == null) {
+      assert(!typeNeeded,
+          "Missing right type for overloaded arithmetic operator.");
+      return new ExpressionInferenceResult(
+          binaryType,
+          inferrer.engine.forest
+              .createBinary(fileOffset, left, binaryName, right));
+    }
+
     right = inferrer.ensureAssignableResult(rightType, rightResult);
 
-    if (inferrer.isOverloadedArithmeticOperatorAndType(
-        binaryTarget, leftType)) {
+    if (isOverloadedArithmeticOperatorAndType) {
       binaryType = inferrer.typeSchemaEnvironment
           .getTypeOfOverloadedArithmetic(leftType, rightResult.inferredType);
     }
@@ -3121,6 +3149,16 @@
             ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
     } else {
+      if (binaryTarget.isInstanceMember &&
+          inferrer.instrumentation != null &&
+          leftType == const DynamicType()) {
+        inferrer.instrumentation.record(
+            inferrer.uriForInstrumentation,
+            fileOffset,
+            'target',
+            new InstrumentationValueForMember(binaryTarget.member));
+      }
+
       binary = new MethodInvocation(
           left,
           binaryName,
@@ -3147,6 +3185,70 @@
     return new ExpressionInferenceResult(binaryType, binary);
   }
 
+  /// Creates a unary expression of the unary operator with [unaryName] using
+  /// [expression] as the operand.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes.
+  /// [expressionType] is the already inferred type of the [expression].
+  ExpressionInferenceResult _computeUnaryExpression(int fileOffset,
+      Expression expression, DartType expressionType, Name unaryName) {
+    ObjectAccessTarget unaryTarget = inferrer.findInterfaceMember(
+        expressionType, unaryName, fileOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind unaryCheckKind =
+        inferrer.preCheckInvocationContravariance(expressionType, unaryTarget,
+            isThisReceiver: false);
+
+    DartType unaryType = inferrer.getReturnType(unaryTarget, expressionType);
+
+    Expression unary;
+    if (unaryTarget.isMissing) {
+      unary = inferrer.createMissingUnary(
+          fileOffset, expression, expressionType, unaryName);
+    } else if (unaryTarget.isExtensionMember) {
+      assert(unaryTarget.extensionMethodKind != ProcedureKind.Setter);
+      unary = new StaticInvocation(
+          unaryTarget.member,
+          new Arguments(<Expression>[
+            expression,
+          ], types: unaryTarget.inferredExtensionTypeArguments)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    } else {
+      if (unaryTarget.isInstanceMember &&
+          inferrer.instrumentation != null &&
+          expressionType == const DynamicType()) {
+        inferrer.instrumentation.record(
+            inferrer.uriForInstrumentation,
+            fileOffset,
+            'target',
+            new InstrumentationValueForMember(unaryTarget.member));
+      }
+
+      unary = new MethodInvocation(
+          expression,
+          unaryName,
+          new Arguments(<Expression>[])..fileOffset = fileOffset,
+          unaryTarget.member)
+        ..fileOffset = fileOffset;
+
+      if (unaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(
+              inferrer.uriForInstrumentation,
+              fileOffset,
+              'checkReturn',
+              new InstrumentationValueForType(expressionType));
+        }
+        unary = new AsExpression(unary, unaryType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
+      }
+    }
+    return new ExpressionInferenceResult(unaryType, unary);
+  }
+
   /// Creates an index operation of [readTarget] on [receiver] using [index] as
   /// the argument.
   ///
@@ -3964,6 +4066,7 @@
   @override
   ExpressionInferenceResult visitNullLiteral(
       NullLiteral node, DartType typeContext) {
+    inferrer.flowAnalysis.nullLiteral(node);
     return new ExpressionInferenceResult(inferrer.coreTypes.nullType, node);
   }
 
@@ -4162,7 +4265,8 @@
     List<DartType> typeArguments =
         new List<DartType>(classTypeParameters.length);
     for (int i = 0; i < typeArguments.length; i++) {
-      typeArguments[i] = new TypeParameterType(classTypeParameters[i]);
+      typeArguments[i] =
+          new TypeParameterType(classTypeParameters[i], Nullability.legacy);
     }
     ArgumentsImpl.setNonInferrableArgumentTypes(node.arguments, typeArguments);
     inferrer.inferInvocation(null, node.fileOffset,
@@ -4264,7 +4368,8 @@
             inferredSpreadTypes, inferredConditionTypes);
       }
     }
-    DartType inferredType = new InterfaceType(setClass, [inferredTypeArgument]);
+    DartType inferredType =
+        new InterfaceType(setClass, Nullability.legacy, [inferredTypeArgument]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (inferenceNeeded) {
@@ -4314,7 +4419,7 @@
       StaticInvocation node, DartType typeContext) {
     FunctionType calleeType = node.target != null
         ? node.target.function.functionType
-        : new FunctionType([], const DynamicType());
+        : new FunctionType([], const DynamicType(), Nullability.legacy);
     TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
     DartType inferredType = inferrer.inferInvocation(
         typeContext, node.fileOffset, calleeType, node.arguments);
@@ -4491,6 +4596,12 @@
   }
 
   void visitCatch(Catch node) {
+    if (node.exception != null) {
+      inferrer.flowAnalysis.initialize(node.exception);
+    }
+    if (node.stackTrace != null) {
+      inferrer.flowAnalysis.initialize(node.stackTrace);
+    }
     inferrer.inferStatement(node.body);
   }
 
@@ -4537,6 +4648,7 @@
     Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
         fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
     node.value = rhs..parent = node;
+    inferrer.flowAnalysis.write(node.variable, rhsResult.inferredType);
     return new ExpressionInferenceResult(rhsResult.inferredType, node);
   }
 
@@ -4552,6 +4664,7 @@
           isVoidAllowed: true);
       inferredType =
           inferrer.inferDeclarationType(initializerResult.inferredType);
+      inferrer.flowAnalysis.initialize(node);
     } else {
       inferredType = const DynamicType();
     }
@@ -4583,11 +4696,20 @@
   ExpressionInferenceResult visitVariableGet(
       covariant VariableGetImpl node, DartType typeContext) {
     VariableDeclarationImpl variable = node.variable;
-    bool mutatedInClosure = variable._mutatedInClosure;
-    DartType declaredOrInferredType = variable.type;
+    bool isUnassigned = !inferrer.flowAnalysis.isAssigned(variable);
+    if (isUnassigned) {
+      inferrer.dataForTesting?.flowAnalysisResult?.unassignedNodes?.add(node);
+    }
 
-    DartType promotedType = inferrer.typePromoter
-        .computePromotedType(node._fact, node._scope, mutatedInClosure);
+    DartType promotedType;
+    DartType declaredOrInferredType = variable.type;
+    if (inferrer.isNonNullableByDefault) {
+      promotedType = inferrer.flowAnalysis.variableRead(node, variable);
+    } else {
+      bool mutatedInClosure = variable._mutatedInClosure;
+      promotedType = inferrer.typePromoter
+          .computePromotedType(node._fact, node._scope, mutatedInClosure);
+    }
     if (promotedType != null) {
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
@@ -4647,7 +4769,8 @@
     DartType inferredType = inferrer.typeSchemaEnvironment
         .futureType(const DynamicType(), Nullability.legacy);
     if (node.arguments != null) {
-      FunctionType calleeType = new FunctionType([], inferredType);
+      FunctionType calleeType =
+          new FunctionType([], inferredType, Nullability.legacy);
       inferrer.inferInvocation(
           typeContext, node.fileOffset, calleeType, node.arguments);
     }
@@ -4659,7 +4782,8 @@
     DartType inferredType = new FunctionType(
         [],
         inferrer.typeSchemaEnvironment
-            .futureType(const DynamicType(), Nullability.legacy));
+            .futureType(const DynamicType(), Nullability.legacy),
+        Nullability.legacy);
     Expression replacement = new StaticGet(node.target)
       ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
@@ -4672,6 +4796,106 @@
     return new ExpressionInferenceResult(
         inferrer.coreTypes.objectRawType(inferrer.library.nullable), node);
   }
+
+  ExpressionInferenceResult visitEquals(
+      EqualsExpression node, DartType typeContext) {
+    ExpressionInferenceResult leftResult =
+        inferrer.inferExpression(node.left, const UnknownType(), true);
+    return _computeEqualsExpression(node.fileOffset, leftResult.expression,
+        leftResult.inferredType, node.right,
+        isNot: node.isNot);
+  }
+
+  ExpressionInferenceResult visitBinary(
+      BinaryExpression node, DartType typeContext) {
+    ExpressionInferenceResult leftResult =
+        inferrer.inferExpression(node.left, const UnknownType(), true);
+    return _computeBinaryExpression(node.fileOffset, leftResult.expression,
+        leftResult.inferredType, node.binaryName, node.right);
+  }
+
+  ExpressionInferenceResult visitUnary(
+      UnaryExpression node, DartType typeContext) {
+    ExpressionInferenceResult expressionResult;
+    if (node.unaryName.name == 'unary-') {
+      // Replace integer literals in a double context with the corresponding
+      // double literal if it's exact.  For double literals, the negation is
+      // folded away.  In any non-double context, or if there is no exact
+      // double value, then the corresponding integer literal is left.  The
+      // negation is not folded away so that platforms with web literals can
+      // distinguish between (non-negated) 0x8000000000000000 represented as
+      // integer literal -9223372036854775808 which should be a positive number,
+      // and negated 9223372036854775808 represented as
+      // -9223372036854775808.unary-() which should be a negative number.
+      if (node.expression is IntJudgment) {
+        IntJudgment receiver = node.expression;
+        if (inferrer.isDoubleContext(typeContext)) {
+          double doubleValue = receiver.asDouble(negated: true);
+          if (doubleValue != null) {
+            Expression replacement = new DoubleLiteral(doubleValue)
+              ..fileOffset = node.fileOffset;
+            DartType inferredType =
+                inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
+            return new ExpressionInferenceResult(inferredType, replacement);
+          }
+        }
+        Expression error = checkWebIntLiteralsErrorIfUnexact(
+            inferrer, receiver.value, receiver.literal, receiver.fileOffset);
+        if (error != null) {
+          return new ExpressionInferenceResult(const DynamicType(), error);
+        }
+      } else if (node.expression is ShadowLargeIntLiteral) {
+        ShadowLargeIntLiteral receiver = node.expression;
+        if (!receiver.isParenthesized) {
+          if (inferrer.isDoubleContext(typeContext)) {
+            double doubleValue = receiver.asDouble(negated: true);
+            if (doubleValue != null) {
+              Expression replacement = new DoubleLiteral(doubleValue)
+                ..fileOffset = node.fileOffset;
+              DartType inferredType = inferrer.coreTypes
+                  .doubleRawType(inferrer.library.nonNullable);
+              return new ExpressionInferenceResult(inferredType, replacement);
+            }
+          }
+          int intValue = receiver.asInt64(negated: true);
+          if (intValue == null) {
+            Expression error = inferrer.helper.buildProblem(
+                templateIntegerLiteralIsOutOfRange
+                    .withArguments(receiver.literal),
+                receiver.fileOffset,
+                receiver.literal.length);
+            return new ExpressionInferenceResult(const DynamicType(), error);
+          }
+          if (intValue != null) {
+            Expression error = checkWebIntLiteralsErrorIfUnexact(
+                inferrer, intValue, receiver.literal, receiver.fileOffset);
+            if (error != null) {
+              return new ExpressionInferenceResult(const DynamicType(), error);
+            }
+            expressionResult = new ExpressionInferenceResult(
+                inferrer.coreTypes.intRawType(inferrer.library.nonNullable),
+                new IntLiteral(-intValue)
+                  ..fileOffset = node.expression.fileOffset);
+          }
+        }
+      }
+    }
+    if (expressionResult == null) {
+      expressionResult =
+          inferrer.inferExpression(node.expression, const UnknownType(), true);
+    }
+    return _computeUnaryExpression(node.fileOffset, expressionResult.expression,
+        expressionResult.inferredType, node.unaryName);
+  }
+
+  ExpressionInferenceResult visitParenthesized(
+      ParenthesizedExpression node, DartType typeContext) {
+    ExpressionInferenceResult result = inferrer.inferExpression(
+        node.expression, typeContext, true,
+        isVoidAllowed: true);
+    return new ExpressionInferenceResult(
+        result.inferredType, result.expression);
+  }
 }
 
 class ForInResult {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index ebbb736..b70d248 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -23,8 +23,6 @@
 
 export 'load_library_builder.dart' show LoadLibraryBuilder;
 
-export 'unlinked_scope.dart' show UnlinkedDeclaration;
-
 int compareProcedures(Procedure a, Procedure b) {
   int i = "${a.fileUri}".compareTo("${b.fileUri}");
   if (i != 0) return i;
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 5a7862b..ae75f53 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -20,7 +20,7 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution;
 
@@ -243,6 +243,7 @@
 }
 
 enum InternalExpressionKind {
+  Binary,
   Cascade,
   CompoundExtensionIndexSet,
   CompoundExtensionSet,
@@ -250,6 +251,7 @@
   CompoundPropertySet,
   CompoundSuperIndexSet,
   DeferredCheck,
+  Equals,
   ExtensionIndexSet,
   ExtensionTearOff,
   ExtensionSet,
@@ -268,10 +270,12 @@
   NullAwareMethodInvocation,
   NullAwarePropertyGet,
   NullAwarePropertySet,
+  Parenthesized,
   PropertyPostIncDec,
   StaticPostIncDec,
   SuperIndexSet,
   SuperPostIncDec,
+  Unary,
 }
 
 /// Common base class for internal expressions.
@@ -279,15 +283,19 @@
   InternalExpressionKind get kind;
 
   @override
-  R accept<R>(ExpressionVisitor<R> visitor) => visitor.defaultExpression(this);
+  R accept<R>(ExpressionVisitor<R> visitor) =>
+      unsupported("${runtimeType}.accept", -1, null);
 
   @override
   R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) =>
-      visitor.defaultExpression(this, arg);
+      unsupported("${runtimeType}.accept1", -1, null);
 
   @override
   DartType getStaticType(types) =>
       unsupported("${runtimeType}.getStaticType", -1, null);
+
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext);
 }
 
 /// Front end specific implementation of [Argument].
@@ -384,6 +392,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCascade(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.Cascade;
 
   /// Adds [expression] to the list of [expressions] performed on [variable].
@@ -420,6 +434,12 @@
     expression?.parent = this;
   }
 
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitDeferredCheck(this, typeContext);
+  }
+
   InternalExpressionKind get kind => InternalExpressionKind.DeferredCheck;
 
   @override
@@ -514,6 +534,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullExpression(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IfNull;
 
   @override
@@ -692,6 +718,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwareMethodInvocation(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.NullAwareMethodInvocation;
 
@@ -733,6 +765,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwarePropertyGet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.NullAwarePropertyGet;
 
@@ -774,6 +812,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwarePropertySet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.NullAwarePropertySet;
 
@@ -974,6 +1018,12 @@
   LoadLibraryTearOff(this.import, this.target);
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitLoadLibraryTearOff(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.LoadLibraryTearOff;
 
   @override
@@ -1025,6 +1075,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullPropertySet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IfNullPropertySet;
 
   @override
@@ -1079,6 +1135,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IfNullSet;
 
   @override
@@ -1189,6 +1251,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCompoundExtensionSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.CompoundExtensionSet;
 
@@ -1268,6 +1336,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCompoundPropertySet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.CompoundPropertySet;
 
   @override
@@ -1321,6 +1395,12 @@
       : this(null, read, write);
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitPropertyPostIncDec(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.PropertyPostIncDec;
 
   @override
@@ -1364,6 +1444,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitLocalPostIncDec(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.LocalPostIncDec;
 
   @override
@@ -1406,6 +1492,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitStaticPostIncDec(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.StaticPostIncDec;
 
   @override
@@ -1448,6 +1540,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitSuperPostIncDec(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.SuperPostIncDec;
 
   @override
@@ -1492,14 +1590,26 @@
   /// The value expression of the operation.
   Expression value;
 
-  // TODO(johnniwinther): Add `readOnlyReceiver` capability.
-  IndexSet(this.receiver, this.index, this.value) {
+  final bool forEffect;
+
+  final bool readOnlyReceiver;
+
+  IndexSet(this.receiver, this.index, this.value,
+      {this.forEffect, this.readOnlyReceiver})
+      : assert(forEffect != null),
+        assert(readOnlyReceiver != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IndexSet;
 
   @override
@@ -1555,6 +1665,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitSuperIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.SuperIndexSet;
 
   @override
@@ -1624,6 +1740,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitExtensionIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.ExtensionIndexSet;
 
   @override
@@ -1715,6 +1837,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IfNullIndexSet;
 
   @override
@@ -1796,6 +1924,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullSuperIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.IfNullSuperIndexSet;
 
   @override
@@ -1883,6 +2017,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitIfNullExtensionIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.IfNullExtensionIndexSet;
 
@@ -1971,6 +2111,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCompoundIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.CompoundIndexSet;
 
   @override
@@ -2076,6 +2222,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwareCompoundSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.NullAwareCompoundSet;
 
@@ -2153,6 +2305,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwareIfNullSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.NullAwareIfNullSet;
 
   @override
@@ -2232,6 +2390,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCompoundSuperIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.CompoundSuperIndexSet;
 
@@ -2338,6 +2502,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitCompoundExtensionIndexSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind =>
       InternalExpressionKind.CompoundExtensionIndexSet;
 
@@ -2420,6 +2590,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitExtensionSet(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.ExtensionSet;
 
   @override
@@ -2460,6 +2636,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitNullAwareExtension(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.NullAwareExtension;
 
   @override
@@ -2520,6 +2702,12 @@
   }
 
   @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitExtensionTearOff(this, typeContext);
+  }
+
+  @override
   InternalExpressionKind get kind => InternalExpressionKind.ExtensionTearOff;
 
   @override
@@ -2536,6 +2724,148 @@
   }
 }
 
+/// Internal expression for an equals or not-equals expression.
+class EqualsExpression extends InternalExpression {
+  Expression left;
+  Expression right;
+  bool isNot;
+
+  EqualsExpression(this.left, this.right, {this.isNot})
+      : assert(isNot != null) {
+    left?.parent = this;
+    right?.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitEquals(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.Equals;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    left?.accept(v);
+    right?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (left != null) {
+      left = left.accept<TreeNode>(v);
+      left?.parent = this;
+    }
+    if (right != null) {
+      right = right.accept<TreeNode>(v);
+      right?.parent = this;
+    }
+  }
+}
+
+/// Internal expression for a binary expression.
+class BinaryExpression extends InternalExpression {
+  Expression left;
+  Name binaryName;
+  Expression right;
+
+  BinaryExpression(this.left, this.binaryName, this.right) {
+    left?.parent = this;
+    right?.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitBinary(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.Binary;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    left?.accept(v);
+    right?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (left != null) {
+      left = left.accept<TreeNode>(v);
+      left?.parent = this;
+    }
+    if (right != null) {
+      right = right.accept<TreeNode>(v);
+      right?.parent = this;
+    }
+  }
+}
+
+/// Internal expression for a unary expression.
+class UnaryExpression extends InternalExpression {
+  Name unaryName;
+  Expression expression;
+
+  UnaryExpression(this.unaryName, this.expression) {
+    expression?.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitUnary(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.Unary;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    expression?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (expression != null) {
+      expression = expression.accept<TreeNode>(v);
+      expression?.parent = this;
+    }
+  }
+}
+
+/// Internal expression for a parenthesized expression.
+class ParenthesizedExpression extends InternalExpression {
+  Expression expression;
+
+  ParenthesizedExpression(this.expression) {
+    expression?.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitParenthesized(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.Parenthesized;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    expression?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (expression != null) {
+      expression = expression.accept<TreeNode>(v);
+      expression?.parent = this;
+    }
+  }
+}
+
 /// Creates a [Let] of [variable] with the given [body] using
 /// `variable.fileOffset` as the file offset for the let.
 ///
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 22369f8..0a6001d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -25,6 +25,7 @@
         Library,
         Name,
         NamedExpression,
+        Nullability,
         NullLiteral,
         Procedure,
         RedirectingInitializer,
@@ -558,9 +559,11 @@
     List<DartType> typeParameterTypes = new List<DartType>();
     for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
       TypeParameter typeParameter = enclosingClass.typeParameters[i];
-      typeParameterTypes.add(new TypeParameterType(typeParameter));
+      typeParameterTypes
+          .add(new TypeParameterType(typeParameter, Nullability.legacy));
     }
-    return new InterfaceType(enclosingClass, typeParameterTypes);
+    return new InterfaceType(
+        enclosingClass, Nullability.legacy, typeParameterTypes);
   }
 
   void setupTopAndBottomTypes() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
index 4d053bd..e209c0b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
@@ -13,6 +13,7 @@
         LoadLibrary,
         Member,
         Name,
+        Nullability,
         Procedure,
         ProcedureKind,
         ReturnStatement;
@@ -54,7 +55,7 @@
         ProcedureKind.Method,
         new FunctionNode(new ReturnStatement(expression),
             returnType: new InterfaceType(parent.loader.coreTypes.futureClass,
-                <DartType>[const DynamicType()])),
+                Nullability.legacy, <DartType>[const DynamicType()])),
         fileUri: parent.library.fileUri,
         isStatic: true)
       ..startFileOffset = charOffset
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index ff2b557..e56558a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -14,6 +14,7 @@
         Let,
         Member,
         NullLiteral,
+        Nullability,
         Procedure,
         StaticGet,
         StringLiteral,
@@ -135,7 +136,8 @@
   List<DartType> typeArguments = <DartType>[]..length =
       member.function.typeParameters.length;
   for (int i = 0; i < typeArguments.length; i++) {
-    typeArguments[i] = new TypeParameterType(member.function.typeParameters[i]);
+    typeArguments[i] = new TypeParameterType(
+        member.function.typeParameters[i], Nullability.legacy);
   }
 
   // We use the [tortoise and hare algorithm]
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index d210b0c..369a2d3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -32,6 +32,7 @@
         MethodInvocation,
         Name,
         Not,
+        Nullability,
         NullLiteral,
         Procedure,
         PropertyGet,
@@ -130,12 +131,14 @@
       result = new VariableDeclaration.forValue(
           new StaticInvocation(
               setFactory, new Arguments([], types: [elementType])),
-          type: new InterfaceType(coreTypes.setClass, [elementType]),
+          type: new InterfaceType(
+              coreTypes.setClass, Nullability.legacy, [elementType]),
           isFinal: true);
     } else {
       result = new VariableDeclaration.forValue(
           new ListLiteral([], typeArgument: elementType),
-          type: new InterfaceType(coreTypes.listClass, [elementType]),
+          type: new InterfaceType(
+              coreTypes.listClass, Nullability.legacy, [elementType]),
           isFinal: true);
     }
     List<Statement> body = [result];
@@ -332,8 +335,8 @@
     // Build a block expression and create an empty map.
     VariableDeclaration result = new VariableDeclaration.forValue(
         new MapLiteral([], keyType: node.keyType, valueType: node.valueType),
-        type: new InterfaceType(
-            coreTypes.mapClass, [node.keyType, node.valueType]),
+        type: new InterfaceType(coreTypes.mapClass, Nullability.legacy,
+            [node.keyType, node.valueType]),
         isFinal: true);
     List<Statement> body = [result];
     // Add all the entries up to the first control-flow entry.
@@ -444,15 +447,15 @@
       value = new VariableGet(temp);
     }
 
-    DartType entryType =
-        new InterfaceType(mapEntryClass, <DartType>[keyType, valueType]);
+    DartType entryType = new InterfaceType(
+        mapEntryClass, Nullability.legacy, <DartType>[keyType, valueType]);
     VariableDeclaration elt;
     Statement loopBody;
     if (entry.entryType == null ||
         !typeEnvironment.isSubtypeOf(entry.entryType, entryType,
             SubtypeCheckMode.ignoringNullabilities)) {
       elt = new VariableDeclaration(null,
-          type: new InterfaceType(mapEntryClass,
+          type: new InterfaceType(mapEntryClass, Nullability.legacy,
               <DartType>[const DynamicType(), const DynamicType()]),
           isFinal: true);
       VariableDeclaration keyVar = new VariableDeclaration.forValue(
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
index ab150cf..0a61069 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
@@ -14,6 +14,7 @@
         Let,
         MethodInvocation,
         Name,
+        Nullability,
         Procedure,
         SetLiteral,
         StaticInvocation,
@@ -57,7 +58,8 @@
     VariableDeclaration setVar = new VariableDeclaration.forValue(
         new StaticInvocation(
             setFactory, new Arguments([], types: [node.typeArgument])),
-        type: new InterfaceType(coreTypes.setClass, [node.typeArgument]));
+        type: new InterfaceType(
+            coreTypes.setClass, Nullability.legacy, [node.typeArgument]));
     // Innermost body of let chain: setVar
     Expression setExp = new VariableGet(setVar);
     for (int i = node.expressions.length - 1; i >= 0; i--) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index 2a5cbe3..91ab53c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -25,6 +25,7 @@
         MapConstant,
         NeverType,
         NullConstant,
+        Nullability,
         PartialInstantiationConstant,
         Procedure,
         SetConstant,
@@ -270,7 +271,8 @@
   }
 
   void visitInstanceConstant(InstanceConstant node) {
-    new InterfaceType(node.classNode, node.typeArguments).accept(this);
+    new InterfaceType(node.classNode, Nullability.legacy, node.typeArguments)
+        .accept(this);
     result.add(" {");
     bool first = true;
     for (Field field in node.classNode.fields) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
index d44fcec..37a3272 100644
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/types.dart
@@ -22,10 +22,13 @@
         Variance,
         VoidType;
 
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_algebra.dart'
+    show Substitution, combineNullabilitiesForSubstitution;
 
 import 'package:kernel/type_environment.dart';
 
+import 'package:kernel/src/future_or.dart';
+
 import 'kernel_builder.dart' show ClassHierarchyBuilder;
 
 class Types implements SubtypeTester {
@@ -231,17 +234,17 @@
     for (int i = 0; i < s.length; i++) {
       int variance = p[i].variance;
       if (variance == Variance.contravariant) {
-        result = result.join(performNullabilityAwareSubtypeCheck(t[i], s[i]));
+        result = result.and(performNullabilityAwareSubtypeCheck(t[i], s[i]));
         if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
       } else if (variance == Variance.invariant) {
-        result = result.join(isSameTypeKernel(s[i], t[i]));
+        result = result.and(isSameTypeKernel(s[i], t[i]));
         if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
       } else {
-        result = result.join(performNullabilityAwareSubtypeCheck(s[i], t[i]));
+        result = result.and(performNullabilityAwareSubtypeCheck(s[i], t[i]));
         if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
@@ -252,7 +255,7 @@
 
   IsSubtypeOf isSameTypeKernel(DartType s, DartType t) {
     return performNullabilityAwareSubtypeCheck(s, t)
-        .joinWithSubtypeCheckFor(t, s, this);
+        .andSubtypeCheckFor(t, s, this);
   }
 
   @override
@@ -275,7 +278,7 @@
   InterfaceType futureType(DartType type,
       [Nullability nullability = Nullability.legacy]) {
     return new InterfaceType(
-        hierarchy.coreTypes.futureClass, <DartType>[type], nullability);
+        hierarchy.coreTypes.futureClass, nullability, <DartType>[type]);
   }
 
   @override
@@ -354,7 +357,7 @@
     return types
         .areTypeArgumentsOfSubtypeKernel(asSupertype.typeArguments,
             t.typeArguments, t.classNode.typeParameters)
-        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
@@ -362,7 +365,7 @@
       TypeParameterType s, InterfaceType t, Types types) {
     return types
         .performNullabilityAwareSubtypeCheck(s.parameter.bound, t)
-        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
@@ -372,12 +375,12 @@
     // Rules 7.1 and 7.2.
     return types
         .performNullabilityAwareSubtypeCheck(arguments.single, t)
-        .joinWithSubtypeCheckFor(
-            new InterfaceType(types.hierarchy.futureClass, arguments,
-                Nullability.nonNullable),
+        .andSubtypeCheckFor(
+            new InterfaceType(types.hierarchy.futureClass,
+                Nullability.nonNullable, arguments),
             t,
             types)
-        .join(new IsSubtypeOf.basedSolelyOnNullabilities(futureOr, t));
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(futureOr, t));
   }
 
   @override
@@ -404,7 +407,7 @@
     // Rule 5.
     return types
         .performNullabilityAwareSubtypeCheck(s.unalias, t)
-        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
@@ -423,43 +426,45 @@
     if (sTypeVariables.length != tTypeVariables.length) {
       return const IsSubtypeOf.never();
     }
+    IsSubtypeOf result = const IsSubtypeOf.always();
     if (sTypeVariables.isNotEmpty) {
       // If the function types have type variables, we alpha-rename the type
       // variables of [s] to use those of [t].
+
+      // As an optimization, we first check if the bounds of the type variables
+      // of the two types on the same positions are mutual subtypes without
+      // alpha-renaming them.
       List<DartType> typeVariableSubstitution = <DartType>[];
-      bool secondBoundsCheckNeeded = false;
       for (int i = 0; i < sTypeVariables.length; i++) {
         TypeParameter sTypeVariable = sTypeVariables[i];
         TypeParameter tTypeVariable = tTypeVariables[i];
-        if (!types
-            .isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound)
-            .isSubtypeWhenIgnoringNullabilities()) {
-          // If the bounds aren't the same, we need to try again after
-          // computing the substitution of type variables.
-          secondBoundsCheckNeeded = true;
-        }
-        typeVariableSubstitution.add(new TypeParameterType(tTypeVariable));
+        result = result.and(
+            types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound));
+        typeVariableSubstitution.add(new TypeParameterType(tTypeVariable,
+            TypeParameterType.computeNullabilityFromBound(tTypeVariable)));
       }
       Substitution substitution =
           Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
-      if (secondBoundsCheckNeeded) {
+      // If the bounds aren't the same, we need to try again after computing the
+      // substitution of type variables.
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
+        result = const IsSubtypeOf.always();
         for (int i = 0; i < sTypeVariables.length; i++) {
           TypeParameter sTypeVariable = sTypeVariables[i];
           TypeParameter tTypeVariable = tTypeVariables[i];
-          if (!types
-              .isSameTypeKernel(
-                  substitution.substituteType(sTypeVariable.bound),
-                  tTypeVariable.bound)
-              .isSubtypeWhenIgnoringNullabilities()) {
+          result = result.and(types.isSameTypeKernel(
+              substitution.substituteType(sTypeVariable.bound),
+              tTypeVariable.bound));
+          if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         }
       }
       s = substitution.substituteType(s.withoutTypeParameters);
     }
-    if (!types
-        .performNullabilityAwareSubtypeCheck(s.returnType, t.returnType)
-        .isSubtypeWhenIgnoringNullabilities()) {
+    result = result.and(
+        types.performNullabilityAwareSubtypeCheck(s.returnType, t.returnType));
+    if (!result.isSubtypeWhenIgnoringNullabilities()) {
       return const IsSubtypeOf.never();
     }
     List<DartType> sPositional = s.positionalParameters;
@@ -473,9 +478,9 @@
       return const IsSubtypeOf.never();
     }
     for (int i = 0; i < tPositional.length; i++) {
-      if (!types
-          .performNullabilityAwareSubtypeCheck(tPositional[i], sPositional[i])
-          .isSubtypeWhenIgnoringNullabilities()) {
+      result = result.and(types.performNullabilityAwareSubtypeCheck(
+          tPositional[i], sPositional[i]));
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
         // Rule 15, Tj <: Sj.
         return const IsSubtypeOf.never();
       }
@@ -501,15 +506,14 @@
           if (sNamed[sCount].name == name) break;
         }
         if (sCount == sNamed.length) return const IsSubtypeOf.never();
-        if (!types
-            .performNullabilityAwareSubtypeCheck(
-                tNamed[tCount].type, sNamed[sCount].type)
-            .isSubtypeWhenIgnoringNullabilities()) {
+        result = result.and(types.performNullabilityAwareSubtypeCheck(
+            tNamed[tCount].type, sNamed[sCount].type));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
       }
     }
-    return const IsSubtypeOf.always();
+    return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
@@ -544,7 +548,9 @@
   IsSubtypeOf isTypeParameterRelated(
       TypeParameterType s, FunctionType t, Types types) {
     // Rule 13.
-    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t);
+    return types
+        .performNullabilityAwareSubtypeCheck(s.parameter.bound, t)
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
@@ -565,21 +571,41 @@
   @override
   IsSubtypeOf isTypeParameterRelated(
       TypeParameterType s, TypeParameterType t, Types types) {
-    return s.parameter == t.parameter ||
-            // Rule 13.
-            types
-                .performNullabilityAwareSubtypeCheck(s.bound, t)
-                .isSubtypeWhenIgnoringNullabilities()
-        ? const IsSubtypeOf.always()
-        : const IsSubtypeOf.never();
+    IsSubtypeOf result = const IsSubtypeOf.always();
+    if (s.parameter != t.parameter) {
+      result = types.performNullabilityAwareSubtypeCheck(s.bound, t);
+    }
+    if (s.nullability == Nullability.undetermined &&
+        t.nullability == Nullability.undetermined) {
+      // The two nullabilities are undetermined, but are connected via
+      // additional constraint, namely that they will be equal at run time.
+      return result;
+    }
+    return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
   IsSubtypeOf isIntersectionRelated(
       TypeParameterType intersection, TypeParameterType t, Types types) {
-    return intersection.parameter == t.parameter
-        ? const IsSubtypeOf.always()
-        : const IsSubtypeOf.never(); // Rule 8.
+    // Nullable types aren't promoted to intersection types.
+    // TODO(dmitryas): Uncomment the following when the inference is updated.
+    //assert(intersection.typeParameterTypeNullability != Nullability.nullable);
+
+    // Rule 8.
+    if (intersection.parameter == t.parameter) {
+      if (intersection.nullability == Nullability.undetermined &&
+          t.nullability == Nullability.undetermined) {
+        // The two nullabilities are undetermined, but are connected via
+        // additional constraint, namely that they will be equal at run time.
+        return const IsSubtypeOf.always();
+      }
+      return new IsSubtypeOf.basedSolelyOnNullabilities(intersection, t);
+    }
+
+    // Rule 12.
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound.withNullability(intersection.nullability),
+        t);
   }
 
   @override
@@ -676,16 +702,20 @@
   IsSubtypeOf isInterfaceRelated(
       InterfaceType s, InterfaceType futureOr, Types types) {
     List<DartType> arguments = futureOr.typeArguments;
-    if (types
-        .performNullabilityAwareSubtypeCheck(s, arguments.single)
-        .isSubtypeWhenIgnoringNullabilities()) {
-      return const IsSubtypeOf.always(); // Rule 11.
-    }
-    // Rule 10.
-    return types.performNullabilityAwareSubtypeCheck(
-        s,
-        new InterfaceType(
-            types.hierarchy.futureClass, arguments, futureOr.nullability));
+
+    Nullability unitedNullability =
+        computeNullabilityOfFutureOr(futureOr, types.hierarchy.futureOrClass);
+
+    return types
+        // Rule 11.
+        .performNullabilityAwareSubtypeCheck(
+            s, arguments.single.withNullability(unitedNullability))
+        // Rule 10.
+        .orSubtypeCheckFor(
+            s,
+            new InterfaceType(
+                types.hierarchy.futureClass, unitedNullability, arguments),
+            types);
   }
 
   @override
@@ -702,39 +732,46 @@
       DynamicType s, InterfaceType futureOr, Types types) {
     // Rule 11.
     DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(s, argument);
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.futureOrClass)));
   }
 
   @override
   IsSubtypeOf isVoidRelated(VoidType s, InterfaceType futureOr, Types types) {
     // Rule 11.
     DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(s, argument);
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.futureOrClass)));
   }
 
   @override
   IsSubtypeOf isTypeParameterRelated(
       TypeParameterType s, InterfaceType futureOr, Types types) {
     List<DartType> arguments = futureOr.typeArguments;
-    if (types
-        .performNullabilityAwareSubtypeCheck(s, arguments.single)
-        .isSubtypeWhenIgnoringNullabilities()) {
-      // Rule 11.
-      return const IsSubtypeOf.always();
-    }
-
-    if (types
-        .performNullabilityAwareSubtypeCheck(s.parameter.bound, futureOr)
-        .isSubtypeWhenIgnoringNullabilities()) {
-      // Rule 13.
-      return const IsSubtypeOf.always();
-    }
-
-    // Rule 10.
-    return types.performNullabilityAwareSubtypeCheck(
-        s,
-        new InterfaceType(
-            types.hierarchy.futureClass, arguments, futureOr.nullability));
+    Nullability unitedNullability =
+        computeNullabilityOfFutureOr(futureOr, types.hierarchy.futureOrClass);
+    // TODO(dmitryas): Revise the original optimization.
+    return types
+        // Rule 11.
+        .performNullabilityAwareSubtypeCheck(
+            s, arguments.single.withNullability(unitedNullability))
+        // Rule 13.
+        .orSubtypeCheckFor(
+            s.parameter.bound.withNullability(
+                combineNullabilitiesForSubstitution(
+                    s.parameter.bound.nullability, s.nullability)),
+            futureOr,
+            types)
+        // Rule 10.
+        .orSubtypeCheckFor(
+            s,
+            new InterfaceType(
+                types.hierarchy.futureClass, unitedNullability, arguments),
+            types);
   }
 
   @override
@@ -742,20 +779,18 @@
       FunctionType s, InterfaceType futureOr, Types types) {
     // Rule 11.
     DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(s, argument);
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.futureOrClass)));
   }
 
   @override
   IsSubtypeOf isIntersectionRelated(
       TypeParameterType intersection, InterfaceType futureOr, Types types) {
-    if (isTypeParameterRelated(intersection, futureOr, types)
-        .isSubtypeWhenIgnoringNullabilities()) {
-      // Rule 8.
-      return const IsSubtypeOf.always();
-    }
-    // Rule 12.
-    return types.performNullabilityAwareSubtypeCheck(
-        intersection.promotedBound, futureOr);
+    return isTypeParameterRelated(intersection, futureOr, types) // Rule 8.
+        .orSubtypeCheckFor(
+            intersection.promotedBound, futureOr, types); // Rule 12.
   }
 
   @override
@@ -773,14 +808,8 @@
       TypeParameterType tIntersection, Types types) {
     // Rule 9.
     return const IsTypeParameterSubtypeOf()
-                .isIntersectionRelated(sIntersection, tIntersection, types)
-                .isSubtypeWhenIgnoringNullabilities() &&
-            types
-                .performNullabilityAwareSubtypeCheck(
-                    sIntersection, tIntersection.promotedBound)
-                .isSubtypeWhenIgnoringNullabilities()
-        ? const IsSubtypeOf.always()
-        : const IsSubtypeOf.never();
+        .isIntersectionRelated(sIntersection, tIntersection, types)
+        .andSubtypeCheckFor(sIntersection, tIntersection.promotedBound, types);
   }
 
   @override
@@ -788,14 +817,8 @@
       TypeParameterType s, TypeParameterType intersection, Types types) {
     // Rule 9.
     return const IsTypeParameterSubtypeOf()
-                .isTypeParameterRelated(s, intersection, types)
-                .isSubtypeWhenIgnoringNullabilities() &&
-            types
-                .performNullabilityAwareSubtypeCheck(
-                    s, intersection.promotedBound)
-                .isSubtypeWhenIgnoringNullabilities()
-        ? const IsSubtypeOf.always()
-        : const IsSubtypeOf.never();
+        .isTypeParameterRelated(s, intersection, types)
+        .andSubtypeCheckFor(s, intersection.promotedBound, types);
   }
 
   @override
@@ -884,7 +907,7 @@
       TypeParameterType s, NeverType t, Types types) {
     return types
         .performNullabilityAwareSubtypeCheck(s.bound, t)
-        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   IsSubtypeOf isTypedefRelated(TypedefType s, NeverType t, Types types) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart b/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
deleted file mode 100644
index 8463914..0000000
--- a/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../builder/builder.dart';
-
-import '../scope.dart';
-
-/// Scope that returns an [UnlinkedDeclaration] if a name can't be resolved.
-/// This is intended to be used as the `enclosingScope` in `BodyBuilder` to
-/// create ASTs with building outlines.
-class UnlinkedScope extends Scope {
-  UnlinkedScope() : super.top(isModifiable: false);
-
-  Builder lookupIn(String name, int charOffset, Uri fileUri,
-      Map<String, Builder> map, bool isInstanceScope) {
-    return new UnlinkedDeclaration(name, isInstanceScope, charOffset, fileUri);
-  }
-}
-
-class UnlinkedDeclaration extends BuilderImpl {
-  final String name;
-
-  final bool isInstanceScope;
-
-  @override
-  final int charOffset;
-
-  @override
-  final Uri fileUri;
-
-  UnlinkedDeclaration(
-      this.name, this.isInstanceScope, this.charOffset, this.fileUri);
-
-  @override
-  Builder get parent => null;
-
-  @override
-  String get fullNameForErrors => name;
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index 8262018..c24a87a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -16,6 +16,7 @@
         Component,
         DartType,
         Library,
+        Nullability,
         Procedure,
         Supertype,
         TreeNode,
@@ -96,7 +97,8 @@
       TypeParameter newNode = new TypeParameter(typeParam.name)
         ..parent = fakeClass;
       typeParams[typeParam] = newNode;
-      typeSubstitution[typeParam] = new TypeParameterType(newNode);
+      typeSubstitution[typeParam] =
+          new TypeParameterType(newNode, Nullability.legacy);
     }
     CloneVisitor cloner = new CloneVisitor(
         typeSubstitution: typeSubstitution, typeParams: typeParams);
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index bae007a..225546e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -9,15 +9,19 @@
 import 'package:kernel/ast.dart'
     show
         AsExpression,
+        BottomType,
         Class,
         Component,
         DartType,
+        DynamicType,
         ExpressionStatement,
         Field,
         FunctionType,
         InterfaceType,
+        InvalidType,
         Library,
         Member,
+        NeverType,
         Nullability,
         Procedure,
         StaticInvocation,
@@ -25,7 +29,8 @@
         SuperPropertyGet,
         SuperPropertySet,
         TreeNode,
-        TypeParameter;
+        TypeParameter,
+        VoidType;
 
 import 'package:kernel/transformations/flags.dart' show TransformerFlag;
 
@@ -42,22 +47,22 @@
     show RedirectingFactoryBody, getRedirectingFactoryBody;
 
 List<LocatedMessage> verifyComponent(Component component,
-    {bool isOutline: false, bool skipPlatform: false}) {
+    {bool isOutline, bool afterConst, bool skipPlatform: false}) {
   FastaVerifyingVisitor verifier =
-      new FastaVerifyingVisitor(isOutline, skipPlatform);
+      new FastaVerifyingVisitor(isOutline, afterConst, skipPlatform);
   component.accept(verifier);
   return verifier.errors;
 }
 
 class FastaVerifyingVisitor extends VerifyingVisitor {
   final List<LocatedMessage> errors = <LocatedMessage>[];
+  Library currentLibrary = null;
 
   Uri fileUri;
   final bool skipPlatform;
 
-  FastaVerifyingVisitor(bool isOutline, this.skipPlatform) {
-    this.isOutline = isOutline;
-  }
+  FastaVerifyingVisitor(bool isOutline, bool afterConst, this.skipPlatform)
+      : super(isOutline: isOutline, afterConst: afterConst);
 
   Uri checkLocation(TreeNode node, String name, Uri fileUri) {
     if (name == null || name.contains("#")) {
@@ -145,7 +150,9 @@
       return;
     }
     fileUri = checkLocation(node, node.name, node.fileUri);
+    currentLibrary = node;
     super.visitLibrary(node);
+    currentLibrary = null;
   }
 
   @override
@@ -166,12 +173,40 @@
     super.visitProcedure(node);
   }
 
+  bool isNullType(DartType node) {
+    if (node is InterfaceType) {
+      Uri importUri = node.classNode.enclosingLibrary.importUri;
+      return node.classNode.name == "Null" &&
+          importUri.scheme == "dart" &&
+          importUri.path == "core";
+    }
+    return false;
+  }
+
   @override
   defaultDartType(DartType node) {
     if (node is UnknownType) {
       // Note: we can't pass [node] to [problem] because it's not a [TreeNode].
       problem(null, "Unexpected appearance of the unknown type.");
     }
+    bool neverLegacy = isNullType(node) ||
+        node is DynamicType ||
+        node is InvalidType ||
+        node is VoidType ||
+        node is NeverType ||
+        node is BottomType;
+    bool expectedLegacy =
+        !currentLibrary.isNonNullableByDefault && !neverLegacy;
+    if (expectedLegacy && node.nullability != Nullability.legacy) {
+      problem(
+          null, "Found a non-legacy type '${node}' in an opted-out library.");
+    }
+    Nullability nodeNullability =
+        node is InvalidType ? Nullability.undetermined : node.nullability;
+    if (currentLibrary.isNonNullableByDefault &&
+        nodeNullability == Nullability.legacy) {
+      problem(null, "Found a legacy type '${node}' in an opted-in library.");
+    }
     super.defaultDartType(node);
   }
 
@@ -192,11 +227,7 @@
 
   @override
   visitInterfaceType(InterfaceType node) {
-    Uri importUri = node.classNode.enclosingLibrary.importUri;
-    if (node.classNode.name == "Null" &&
-        importUri.scheme == "dart" &&
-        importUri.path == "core" &&
-        node.nullability != Nullability.nullable) {
+    if (isNullType(node) && node.nullability != Nullability.nullable) {
       problem(null, "Found a not nullable Null type: ${node}");
     }
     super.visitInterfaceType(node);
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index f2e6550..1fb9f37 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -257,7 +257,7 @@
     _local.forEach(f);
   }
 
-  void forEachLocalSetter(void Function(String name, Builder member) f) {
+  void forEachLocalSetter(void Function(String name, MemberBuilder member) f) {
     _setters.forEach(f);
   }
 
@@ -467,6 +467,12 @@
     ensureScope();
     return super._setters;
   }
+
+  @override
+  Set<ExtensionBuilder> get _extensions {
+    ensureScope();
+    return super._extensions;
+  }
 }
 
 class ScopeBuilder {
@@ -597,41 +603,52 @@
       String name, Builder builder, int charOffset, Uri fileUri)
       : super(name, builder, charOffset, fileUri);
 
+  @override
   Member get member => null;
 
+  @override
+  Member get readTarget => null;
+
+  @override
+  Member get writeTarget => null;
+
+  @override
+  Member get invokeTarget => null;
+
   bool get isNative => false;
 
   @override
   bool get isAssignable => false;
 
+  @override
   ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
 
+  @override
   void set parent(Builder value) {
     throw new UnsupportedError('AmbiguousMemberBuilder.parent=');
   }
 
+  @override
   LibraryBuilder get library {
     throw new UnsupportedError('AmbiguousMemberBuilder.parent=');
   }
 
   // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  Member get extensionTearOff => null;
-
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  Procedure get procedure => null;
-
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
+  @override
   ProcedureKind get kind => null;
 
+  @override
   void buildOutlineExpressions(LibraryBuilder library) {
     throw new UnsupportedError(
         'AmbiguousMemberBuilder.buildOutlineExpressions');
   }
 
+  @override
   void inferType() {
     throw new UnsupportedError('AmbiguousMemberBuilder.inferType');
   }
 
+  @override
   void inferCopiedType(covariant Object other) {
     throw new UnsupportedError('AmbiguousMemberBuilder.inferCopiedType');
   }
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index a9638af..ade334e 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -7,6 +7,13 @@
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show Assert, DeclarationKind, MemberKind, Parser, optional;
 
+import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
+
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
+    show FixedNullableList, NullValue, ParserRecovery;
+
+import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
+
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import 'package:kernel/ast.dart'
@@ -58,8 +65,6 @@
 import '../problems.dart'
     show DebugAbort, internalProblem, unexpected, unhandled;
 
-import '../quote.dart' show unescapeString;
-
 import '../scope.dart';
 
 import '../source/value_kinds.dart';
@@ -71,10 +76,9 @@
 
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 
-import 'stack_listener.dart'
-    show FixedNullableList, NullValue, ParserRecovery, StackListener;
+import 'stack_listener_impl.dart';
 
-class DietListener extends StackListener {
+class DietListener extends StackListenerImpl {
   final SourceLibraryBuilder libraryBuilder;
 
   final ClassHierarchy hierarchy;
@@ -130,7 +134,7 @@
 
   @override
   void endMetadataStar(int count) {
-    assert(checkState(null, repeatedKinds(ValueKind.Token, count)));
+    assert(checkState(null, repeatedKinds(ValueKinds.Token, count)));
     debugEvent("MetadataStar");
     if (count > 0) {
       discard(count - 1);
@@ -339,7 +343,7 @@
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) return;
 
-    final StackListener listener =
+    final StackListenerImpl listener =
         createFunctionListener(lookupBuilder(beginToken, getOrSet, name));
     buildFunctionBody(listener, bodyToken, metadata, MemberKind.TopLevelMethod);
   }
@@ -380,12 +384,12 @@
   @override
   void handleQualified(Token period) {
     assert(checkState(period, [
-      /*suffix*/ ValueKind.NameOrParserRecovery,
+      /*suffix*/ ValueKinds.NameOrParserRecovery,
       /*prefix*/ unionOfKinds([
-        ValueKind.Name,
-        ValueKind.Generator,
-        ValueKind.ParserRecovery,
-        ValueKind.QualifiedName,
+        ValueKinds.Name,
+        ValueKinds.Generator,
+        ValueKinds.ParserRecovery,
+        ValueKinds.QualifiedName,
       ]),
     ]));
     debugEvent("handleQualified");
@@ -666,7 +670,7 @@
             : MemberKind.NonStaticMethod);
   }
 
-  StackListener createListener(ModifierBuilder builder, Scope memberScope,
+  StackListenerImpl createListener(ModifierBuilder builder, Scope memberScope,
       {bool isDeclarationInstanceMember,
       VariableDeclaration extensionThis,
       List<TypeParameter> extensionTypeParameters,
@@ -694,7 +698,7 @@
         constantContext);
   }
 
-  StackListener createListenerInternal(
+  StackListenerImpl createListenerInternal(
       ModifierBuilder builder,
       Scope memberScope,
       Scope formalParameterScope,
@@ -719,7 +723,7 @@
       ..constantContext = constantContext;
   }
 
-  StackListener createFunctionListener(FunctionBuilderImpl builder) {
+  StackListenerImpl createFunctionListener(FunctionBuilderImpl builder) {
     final Scope typeParameterScope =
         builder.computeTypeParameterScope(memberScope);
     final Scope formalParameterScope =
@@ -736,7 +740,7 @@
 
   void buildRedirectingFactoryMethod(
       Token token, FunctionBuilder builder, MemberKind kind, Token metadata) {
-    final StackListener listener = createFunctionListener(builder);
+    final StackListenerImpl listener = createFunctionListener(builder);
     try {
       Parser parser = new Parser(listener);
       if (metadata != null) {
@@ -797,9 +801,9 @@
   @override
   void beginClassOrMixinBody(DeclarationKind kind, Token token) {
     assert(checkState(token, [
-      ValueKind.Token,
-      ValueKind.NameOrParserRecovery,
-      ValueKind.TokenOrNull
+      ValueKinds.Token,
+      ValueKinds.NameOrParserRecovery,
+      ValueKinds.TokenOrNull
     ]));
     debugEvent("beginClassOrMixinBody");
     Token beginToken = pop();
@@ -884,14 +888,14 @@
     checkEmpty(beginToken.charOffset);
   }
 
-  AsyncMarker getAsyncMarker(StackListener listener) => listener.pop();
+  AsyncMarker getAsyncMarker(StackListenerImpl listener) => listener.pop();
 
   /// Invokes the listener's [finishFunction] method.
   ///
   /// This is a separate method so that it may be overridden by a derived class
   /// if more computation must be done before finishing the function.
   void listenerFinishFunction(
-      StackListener listener,
+      StackListenerImpl listener,
       Token token,
       MemberKind kind,
       dynamic formals,
@@ -904,12 +908,12 @@
   ///
   /// This is a separate method so that it may be overridden by a derived class
   /// if more computation must be done before finishing the function.
-  void listenerFinishFields(StackListener listener, Token startToken,
+  void listenerFinishFields(StackListenerImpl listener, Token startToken,
       Token metadata, bool isTopLevel) {
     listener.finishFields();
   }
 
-  void buildFunctionBody(StackListener listener, Token startToken,
+  void buildFunctionBody(StackListenerImpl listener, Token startToken,
       Token metadata, MemberKind kind) {
     Token token = startToken;
     try {
@@ -939,7 +943,7 @@
     }
   }
 
-  void parseFields(StackListener listener, Token startToken, Token metadata,
+  void parseFields(StackListenerImpl listener, Token startToken, Token metadata,
       bool isTopLevel) {
     Token token = startToken;
     Parser parser = new Parser(listener);
@@ -1051,7 +1055,7 @@
   List<Expression> parseMetadata(
       ModifierBuilder builder, Token metadata, TreeNode parent) {
     if (metadata != null) {
-      StackListener listener = createListener(builder, memberScope,
+      StackListenerImpl listener = createListener(builder, memberScope,
           isDeclarationInstanceMember: false);
       Parser parser = new Parser(listener);
       parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
diff --git a/pkg/front_end/lib/src/fasta/source/directive_listener.dart b/pkg/front_end/lib/src/fasta/source/directive_listener.dart
index 416c577..f912c9e 100644
--- a/pkg/front_end/lib/src/fasta/source/directive_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/directive_listener.dart
@@ -7,10 +7,10 @@
 library front_end.src.fasta.source.directive_listener;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-import '../fasta_codes.dart' show messageExpectedBlockToSkip;
 import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
 import 'package:_fe_analyzer_shared/src/parser/listener.dart';
-import '../quote.dart';
+import 'package:_fe_analyzer_shared/src/parser/quote.dart';
+import '../fasta_codes.dart' show messageExpectedBlockToSkip;
 
 /// Listener that records imports, exports, and part directives.
 ///
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index ea75e1c..b27bedc 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -14,6 +14,13 @@
         MemberKind,
         optional;
 
+import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
+
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
+    show FixedNullableList, NullValue, ParserRecovery;
+
+import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
 
 import 'package:kernel/ast.dart' show InvalidType, ProcedureKind, Variance;
@@ -93,8 +100,6 @@
 
 import '../problems.dart' show unhandled;
 
-import '../quote.dart' show unescapeString;
-
 import 'source_library_builder.dart'
     show
         TypeParameterScopeBuilder,
@@ -102,13 +107,7 @@
         FieldInfo,
         SourceLibraryBuilder;
 
-import 'stack_listener.dart'
-    show
-        FixedNullableList,
-        NullValue,
-        ParserRecovery,
-        StackListener,
-        offsetForToken;
+import 'stack_listener_impl.dart';
 
 import 'value_kinds.dart';
 
@@ -118,7 +117,7 @@
   RedirectingFactoryBody,
 }
 
-class OutlineBuilder extends StackListener {
+class OutlineBuilder extends StackListenerImpl {
   final SourceLibraryBuilder library;
 
   final bool enableNative;
@@ -426,11 +425,14 @@
   @override
   void handleQualified(Token period) {
     assert(checkState(period, [
-      /*suffix offset*/ ValueKind.Integer,
-      /*suffix*/ ValueKind.NameOrParserRecovery,
-      /*prefix offset*/ ValueKind.Integer,
-      /*prefix*/ unionOfKinds(
-          [ValueKind.Name, ValueKind.ParserRecovery, ValueKind.QualifiedName]),
+      /*suffix offset*/ ValueKinds.Integer,
+      /*suffix*/ ValueKinds.NameOrParserRecovery,
+      /*prefix offset*/ ValueKinds.Integer,
+      /*prefix*/ unionOfKinds([
+        ValueKinds.Name,
+        ValueKinds.ParserRecovery,
+        ValueKinds.QualifiedName
+      ]),
     ]));
     debugEvent("handleQualified");
     int suffixOffset = pop();
@@ -494,7 +496,7 @@
   void beginClassOrMixinBody(DeclarationKind kind, Token token) {
     if (kind == DeclarationKind.Extension) {
       assert(checkState(token, [
-        unionOfKinds([ValueKind.ParserRecovery, ValueKind.TypeBuilder])
+        unionOfKinds([ValueKinds.ParserRecovery, ValueKinds.TypeBuilder])
       ]));
       Object extensionThisType = peek();
       if (extensionThisType is TypeBuilder) {
@@ -646,7 +648,7 @@
 
   @override
   void beginExtensionDeclarationPrelude(Token extensionKeyword) {
-    assert(checkState(extensionKeyword, [ValueKind.MetadataListOrNull]));
+    assert(checkState(extensionKeyword, [ValueKinds.MetadataListOrNull]));
     debugEvent("beginExtensionDeclaration");
     library.beginNestedDeclaration(
         TypeParameterScopeKind.extensionDeclaration, "extension");
@@ -655,7 +657,7 @@
   @override
   void beginExtensionDeclaration(Token extensionKeyword, Token nameToken) {
     assert(checkState(extensionKeyword,
-        [ValueKind.TypeVariableListOrNull, ValueKind.MetadataListOrNull]));
+        [ValueKinds.TypeVariableListOrNull, ValueKinds.MetadataListOrNull]));
     debugEvent("beginExtensionDeclaration");
     List<TypeVariableBuilder> typeVariables = pop();
     int offset = nameToken?.charOffset ?? extensionKeyword.charOffset;
@@ -673,11 +675,11 @@
   void endExtensionDeclaration(
       Token extensionKeyword, Token onKeyword, Token endToken) {
     assert(checkState(extensionKeyword, [
-      unionOfKinds([ValueKind.ParserRecovery, ValueKind.TypeBuilder]),
-      ValueKind.TypeVariableListOrNull,
-      ValueKind.Integer,
-      ValueKind.NameOrNull,
-      ValueKind.MetadataListOrNull
+      unionOfKinds([ValueKinds.ParserRecovery, ValueKinds.TypeBuilder]),
+      ValueKinds.TypeVariableListOrNull,
+      ValueKinds.Integer,
+      ValueKinds.NameOrNull,
+      ValueKinds.MetadataListOrNull
     ]));
     debugEvent("endExtensionDeclaration");
     String documentationComment = getDocumentationComment(extensionKeyword);
@@ -862,7 +864,7 @@
   @override
   void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
       Token beginInitializers, Token endToken) {
-    assert(checkState(beginToken, [ValueKind.MethodBody]));
+    assert(checkState(beginToken, [ValueKinds.MethodBody]));
     debugEvent("Method");
     MethodBody bodyKind = pop();
     if (bodyKind == MethodBody.RedirectingFactoryBody) {
@@ -870,20 +872,20 @@
       pop();
     }
     assert(checkState(beginToken, [
-      ValueKind.FormalsOrNull,
-      ValueKind.Integer, // formals offset
-      ValueKind.TypeVariableListOrNull,
-      ValueKind.Integer, // name offset
+      ValueKinds.FormalsOrNull,
+      ValueKinds.Integer, // formals offset
+      ValueKinds.TypeVariableListOrNull,
+      ValueKinds.Integer, // name offset
       unionOfKinds([
-        ValueKind.Name,
-        ValueKind.QualifiedName,
-        ValueKind.Operator,
-        ValueKind.ParserRecovery,
+        ValueKinds.Name,
+        ValueKinds.QualifiedName,
+        ValueKinds.Operator,
+        ValueKinds.ParserRecovery,
       ]),
-      ValueKind.TypeBuilderOrNull,
-      ValueKind.ModifiersOrNull,
-      ValueKind.Integer, // var/final/const offset
-      ValueKind.MetadataListOrNull,
+      ValueKinds.TypeBuilderOrNull,
+      ValueKinds.ModifiersOrNull,
+      ValueKinds.Integer, // var/final/const offset
+      ValueKinds.MetadataListOrNull,
     ]));
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
diff --git a/pkg/front_end/lib/src/fasta/source/scope_listener.dart b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
index bfc1c29..29bbad1 100644
--- a/pkg/front_end/lib/src/fasta/source/scope_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
@@ -6,13 +6,15 @@
 
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart' show BlockKind;
 
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
+    show NullValue;
+
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import '../scope.dart' show Scope;
+import 'stack_listener_impl.dart';
 
-import 'stack_listener.dart' show NullValue, StackListener;
-
-export 'stack_listener.dart'
+export 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
     show FixedNullableList, GrowableList, NullValue, ParserRecovery;
 
 enum JumpTargetKind {
@@ -21,7 +23,7 @@
   Goto, // Continue label in switch.
 }
 
-abstract class ScopeListener<J> extends StackListener {
+abstract class ScopeListener<J> extends StackListenerImpl {
   Scope scope;
 
   J breakTarget;
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 34cfbf5..9198824 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -10,11 +10,10 @@
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/constructor_reference_builder.dart';
-import '../builder/field_builder.dart';
-import '../builder/function_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/metadata_builder.dart';
+import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
@@ -121,19 +120,15 @@
             unexpected(fullNameForErrors, declaration.parent?.fullNameForErrors,
                 charOffset, fileUri);
           }
-        } else if (declaration is FieldBuilder) {
-          // TODO(ahe): It would be nice to have a common interface for the
-          // build method to avoid duplicating these two cases.
-          Member field = declaration.build(library);
-          if (!declaration.isPatch && declaration.next == null) {
-            cls.addMember(field);
-          }
-        } else if (declaration is FunctionBuilder) {
-          Member member = declaration.build(library);
-          member.parent = cls;
-          if (!declaration.isPatch && declaration.next == null) {
-            cls.addMember(member);
-          }
+        } else if (declaration is MemberBuilderImpl) {
+          MemberBuilderImpl memberBuilder = declaration;
+          memberBuilder.buildMembers(library,
+              (Member member, BuiltMemberKind memberKind) {
+            member.parent = cls;
+            if (!memberBuilder.isPatch && !memberBuilder.isDuplicate) {
+              cls.addMember(member);
+            }
+          });
         } else {
           unhandled("${declaration.runtimeType}", "buildBuilders",
               declaration.charOffset, declaration.fileUri);
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index be48777..b5b5959 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -11,10 +11,9 @@
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/extension_builder.dart';
-import '../builder/field_builder.dart';
 import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
 import '../builder/metadata_builder.dart';
-import '../builder/procedure_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
 
@@ -97,55 +96,53 @@
             unexpected(fullNameForErrors, declaration.parent?.fullNameForErrors,
                 charOffset, fileUri);
           }
-        } else if (declaration is FieldBuilder) {
-          Field field = declaration.build(libraryBuilder);
-          if (addMembersToLibrary && declaration.next == null) {
-            libraryBuilder.library.addMember(field);
-            extension.members.add(new ExtensionMemberDescriptor(
-                name: new Name(declaration.name, libraryBuilder.library),
-                member: field.reference,
-                isStatic: declaration.isStatic,
-                kind: ExtensionMemberKind.Field));
-          }
-        } else if (declaration is ProcedureBuilder) {
-          Member function = declaration.build(libraryBuilder);
-          if (addMembersToLibrary &&
-              !declaration.isPatch &&
-              declaration.next == null) {
-            libraryBuilder.library.addMember(function);
-            ExtensionMemberKind kind;
-            switch (declaration.kind) {
-              case ProcedureKind.Method:
-                kind = ExtensionMemberKind.Method;
-                break;
-              case ProcedureKind.Getter:
-                kind = ExtensionMemberKind.Getter;
-                break;
-              case ProcedureKind.Setter:
-                kind = ExtensionMemberKind.Setter;
-                break;
-              case ProcedureKind.Operator:
-                kind = ExtensionMemberKind.Operator;
-                break;
-              case ProcedureKind.Factory:
-                unsupported("Extension method kind: ${declaration.kind}",
-                    declaration.charOffset, declaration.fileUri);
+        } else if (declaration is MemberBuilderImpl) {
+          MemberBuilderImpl memberBuilder = declaration;
+          memberBuilder.buildMembers(libraryBuilder,
+              (Member member, BuiltMemberKind memberKind) {
+            if (addMembersToLibrary &&
+                !memberBuilder.isPatch &&
+                !memberBuilder.isDuplicate) {
+              ExtensionMemberKind kind;
+              switch (memberKind) {
+                case BuiltMemberKind.Constructor:
+                case BuiltMemberKind.RedirectingFactory:
+                case BuiltMemberKind.Field:
+                case BuiltMemberKind.Method:
+                  unhandled(
+                      "${member.runtimeType}:${memberKind}",
+                      "buildMembers",
+                      declaration.charOffset,
+                      declaration.fileUri);
+                  break;
+                case BuiltMemberKind.ExtensionField:
+                  kind = ExtensionMemberKind.Field;
+                  break;
+                case BuiltMemberKind.ExtensionMethod:
+                  kind = ExtensionMemberKind.Method;
+                  break;
+                case BuiltMemberKind.ExtensionGetter:
+                  kind = ExtensionMemberKind.Getter;
+                  break;
+                case BuiltMemberKind.ExtensionSetter:
+                  kind = ExtensionMemberKind.Setter;
+                  break;
+                case BuiltMemberKind.ExtensionOperator:
+                  kind = ExtensionMemberKind.Operator;
+                  break;
+                case BuiltMemberKind.ExtensionTearOff:
+                  kind = ExtensionMemberKind.TearOff;
+                  break;
+              }
+              assert(kind != null);
+              libraryBuilder.library.addMember(member);
+              extension.members.add(new ExtensionMemberDescriptor(
+                  name: new Name(memberBuilder.name, libraryBuilder.library),
+                  member: member.reference,
+                  isStatic: declaration.isStatic,
+                  kind: kind));
             }
-            extension.members.add(new ExtensionMemberDescriptor(
-                name: new Name(declaration.name, libraryBuilder.library),
-                member: function.reference,
-                isStatic: declaration.isStatic,
-                kind: kind));
-            Procedure tearOff = declaration.extensionTearOff;
-            if (tearOff != null) {
-              libraryBuilder.library.addMember(tearOff);
-              _extension.members.add(new ExtensionMemberDescriptor(
-                  name: new Name(declaration.name, libraryBuilder.library),
-                  member: tearOff.reference,
-                  isStatic: false,
-                  kind: ExtensionMemberKind.TearOff));
-            }
-          }
+          });
         } else {
           unhandled("${declaration.runtimeType}", "buildBuilders",
               declaration.charOffset, declaration.fileUri);
@@ -156,7 +153,7 @@
 
     scope.forEach(buildBuilders);
 
-    scope.forEachLocalSetter((String name, Builder setter) {
+    scope.forEachLocalSetter((String name, MemberBuilder setter) {
       Builder member = scopeBuilder[name];
       if (member == null) {
         // Setter without getter.
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 56fabe0..739d4fb 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
@@ -318,6 +318,13 @@
   bool postponedProblemsIssued = false;
   List<PostponedProblem> postponedProblems;
 
+  /// List of [PrefixBuilder]s for imports with prefixes.
+  List<PrefixBuilder> _prefixBuilders;
+
+  /// Set of extension declarations in scope. This is computed lazily in
+  /// [forEachExtensionInScope].
+  Set<ExtensionBuilder> _extensionsInScope;
+
   SourceLibraryBuilder.internal(SourceLoader loader, Uri fileUri, Scope scope,
       SourceLibraryBuilder actualOrigin, Library library, Library nameOrigin)
       : this.fromScopes(
@@ -729,6 +736,10 @@
       // by name or by resolution and the remaining are dropped for the output.
       currentTypeParameterScopeBuilder.extensions.add(declaration);
     }
+    if (declaration is PrefixBuilder) {
+      _prefixBuilders ??= <PrefixBuilder>[];
+      _prefixBuilders.add(declaration);
+    }
     return members[name] = declaration;
   }
 
@@ -2060,23 +2071,54 @@
   }
 
   void buildBuilder(Builder declaration, LibraryBuilder coreLibrary) {
-    Class cls;
-    Extension extension;
-    Member member;
-    Typedef typedef;
+    String findDuplicateSuffix(Builder declaration) {
+      if (declaration.next != null) {
+        int count = 0;
+        Builder current = declaration.next;
+        while (current != null) {
+          count++;
+          current = current.next;
+        }
+        return "#$count";
+      }
+      return "";
+    }
+
     if (declaration is SourceClassBuilder) {
-      cls = declaration.build(this, coreLibrary);
+      Class cls = declaration.build(this, coreLibrary);
+      if (!declaration.isPatch) {
+        cls.name += findDuplicateSuffix(declaration);
+        library.addClass(cls);
+      }
     } else if (declaration is SourceExtensionBuilder) {
-      extension = declaration.build(this, coreLibrary,
-          addMembersToLibrary: declaration.next == null);
-    } else if (declaration is FieldBuilder) {
-      member = declaration.build(this)..isStatic = true;
-    } else if (declaration is ProcedureBuilder) {
-      member = declaration.build(this)..isStatic = true;
+      Extension extension = declaration.build(this, coreLibrary,
+          addMembersToLibrary: !declaration.isDuplicate);
+      if (!declaration.isPatch && !declaration.isDuplicate) {
+        library.addExtension(extension);
+      }
+    } else if (declaration is MemberBuilderImpl) {
+      declaration.buildMembers(this,
+          (Member member, BuiltMemberKind memberKind) {
+        if (member is Field) {
+          member.isStatic = true;
+        } else if (member is Procedure) {
+          member.isStatic = true;
+        }
+        if (!declaration.isPatch && !declaration.isDuplicate) {
+          library.addMember(member);
+        }
+      });
     } else if (declaration is TypeAliasBuilder) {
-      typedef = declaration.build(this);
+      Typedef typedef = declaration.build(this);
+      if (!declaration.isPatch && !declaration.isDuplicate) {
+        library.addTypedef(typedef);
+      }
     } else if (declaration is EnumBuilder) {
-      cls = declaration.build(this, coreLibrary);
+      Class cls = declaration.build(this, coreLibrary);
+      if (!declaration.isPatch) {
+        cls.name += findDuplicateSuffix(declaration);
+        library.addClass(cls);
+      }
     } else if (declaration is PrefixBuilder) {
       // Ignored. Kernel doesn't represent prefixes.
       return;
@@ -2088,38 +2130,6 @@
           declaration.charOffset, declaration.fileUri);
       return;
     }
-    if (declaration.isPatch) {
-      // The kernel node of a patch is shared with the origin declaration. We
-      // have two builders: the origin, and the patch, but only one kernel node
-      // (which corresponds to the final output). Consequently, the node
-      // shouldn't be added to its apparent kernel parent as this would create
-      // a duplicate entry in the parent's list of children/members.
-      return;
-    }
-    if (cls != null) {
-      if (declaration.next != null) {
-        int count = 0;
-        Builder current = declaration.next;
-        while (current != null) {
-          count++;
-          current = current.next;
-        }
-        cls.name += "#$count";
-      }
-      library.addClass(cls);
-    } else if (extension != null) {
-      if (declaration.next == null) {
-        library.addExtension(extension);
-      }
-    } else if (member != null) {
-      if (declaration.next == null) {
-        library.addMember(member);
-      }
-    } else if (typedef != null) {
-      if (declaration.next == null) {
-        library.addTypedef(typedef);
-      }
-    }
   }
 
   void addNativeDependency(String nativeImportPath) {
@@ -2795,7 +2805,8 @@
     if (node.arguments.types.isEmpty) return;
     Constructor constructor = node.target;
     Class klass = constructor.enclosingClass;
-    DartType constructedType = new InterfaceType(klass, node.arguments.types);
+    DartType constructedType =
+        new InterfaceType(klass, Nullability.legacy, node.arguments.types);
     checkBoundsInType(
         constructedType, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: false);
@@ -2808,7 +2819,8 @@
     Procedure factory = node.target;
     assert(factory.isFactory);
     Class klass = factory.enclosingClass;
-    DartType constructedType = new InterfaceType(klass, node.arguments.types);
+    DartType constructedType =
+        new InterfaceType(klass, Nullability.legacy, node.arguments.types);
     checkBoundsInType(
         constructedType, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: false);
@@ -2833,7 +2845,7 @@
     if (issues != null) {
       DartType targetReceiver;
       if (klass != null) {
-        targetReceiver = new InterfaceType(klass);
+        targetReceiver = new InterfaceType(klass, Nullability.legacy);
       }
       String targetName = node.target.name.name;
       reportTypeArgumentIssues(issues, fileUri, node.fileOffset,
@@ -2885,8 +2897,8 @@
     for (int i = 0; i < instantiatedMethodParameters.length; ++i) {
       instantiatedMethodParameters[i] =
           new TypeParameter(methodParameters[i].name);
-      substitutionMap[methodParameters[i]] =
-          new TypeParameterType(instantiatedMethodParameters[i]);
+      substitutionMap[methodParameters[i]] = new TypeParameterType(
+          instantiatedMethodParameters[i], Nullability.legacy);
     }
     for (int i = 0; i < instantiatedMethodParameters.length; ++i) {
       instantiatedMethodParameters[i].bound =
@@ -2924,6 +2936,19 @@
     implicitlyTypedFields = null;
     return result;
   }
+
+  void forEachExtensionInScope(void Function(ExtensionBuilder) f) {
+    if (_extensionsInScope == null) {
+      _extensionsInScope = <ExtensionBuilder>{};
+      scope.forEachExtension(_extensionsInScope.add);
+      if (_prefixBuilders != null) {
+        for (PrefixBuilder prefix in _prefixBuilders) {
+          prefix.exportScope.forEachExtension(_extensionsInScope.add);
+        }
+      }
+    }
+    _extensionsInScope.forEach(f);
+  }
 }
 
 // The kind of type parameter scope built by a [TypeParameterScopeBuilder]
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 212600d..085b89a 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -37,6 +37,7 @@
         InterfaceType,
         Library,
         LibraryDependency,
+        Nullability,
         ProcedureKind,
         Supertype,
         TreeNode;
@@ -114,7 +115,7 @@
 
 import '../problems.dart' show internalProblem;
 
-import '../source/stack_listener.dart' show offsetForToken;
+import '../source/stack_listener_impl.dart' show offsetForToken;
 
 import '../type_inference/type_inference_engine.dart';
 
@@ -878,12 +879,12 @@
   void computeCoreTypes(Component component) {
     coreTypes = new CoreTypes(component);
 
-    futureOfBottom = new InterfaceType(
-        coreTypes.futureClass, <DartType>[const BottomType()]);
-    iterableOfBottom = new InterfaceType(
-        coreTypes.iterableClass, <DartType>[const BottomType()]);
-    streamOfBottom = new InterfaceType(
-        coreTypes.streamClass, <DartType>[const BottomType()]);
+    futureOfBottom = new InterfaceType(coreTypes.futureClass,
+        Nullability.legacy, <DartType>[const BottomType()]);
+    iterableOfBottom = new InterfaceType(coreTypes.iterableClass,
+        Nullability.legacy, <DartType>[const BottomType()]);
+    streamOfBottom = new InterfaceType(coreTypes.streamClass,
+        Nullability.legacy, <DartType>[const BottomType()]);
 
     ticker.logMs("Computed core types");
   }
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
new file mode 100644
index 0000000..4bd5619
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.stack_listener_impl;
+
+import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
+
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import 'package:kernel/ast.dart'
+    show AsyncMarker, Expression, FunctionNode, TreeNode;
+
+import '../problems.dart' as problems
+    show internalProblem, unhandled, unsupported;
+
+abstract class StackListenerImpl extends StackListener {
+  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
+  // and ast_builder.dart.
+  void finishFunction(
+      covariant formals, AsyncMarker asyncModifier, covariant body) {
+    return problems.unsupported("finishFunction", -1, uri);
+  }
+
+  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
+  // and ast_builder.dart.
+  dynamic finishFields() {
+    return problems.unsupported("finishFields", -1, uri);
+  }
+
+  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
+  // and ast_builder.dart.
+  List<Expression> finishMetadata(TreeNode parent) {
+    return problems.unsupported("finishMetadata", -1, uri);
+  }
+
+  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
+  // and ast_builder.dart.
+  void exitLocalScope() => problems.unsupported("exitLocalScope", -1, uri);
+
+  // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart.
+  dynamic parseSingleExpression(
+      Parser parser, Token token, FunctionNode parameters) {
+    return problems.unsupported("finishSingleExpression", -1, uri);
+  }
+
+  /// Used to report an internal error encountered in the stack listener.
+  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+    return problems.internalProblem(message, charOffset, uri);
+  }
+
+  /// Used to report an unexpected situation encountered in the stack
+  /// listener.
+  dynamic unhandled(String what, String where, int charOffset, Uri uri) {
+    return problems.unhandled(what, where, charOffset, uri);
+  }
+}
+
+/// A null-aware alternative to `token.offset`.  If [token] is `null`, returns
+/// `TreeNode.noOffset`.
+int offsetForToken(Token token) {
+  return token == null ? TreeNode.noOffset : token.offset;
+}
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
deleted file mode 100644
index 91cdbaa..0000000
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ /dev/null
@@ -1,1427 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.type_promotion_look_ahead_listener;
-
-import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
-import 'package:_fe_analyzer_shared/src/parser/parser.dart'
-    show
-        Assert,
-        BlockKind,
-        DeclarationKind,
-        FormalParameterKind,
-        IdentifierContext,
-        Listener,
-        MemberKind;
-
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
-import '../builder/builder.dart';
-
-import '../messages.dart' show LocatedMessage, Message, MessageCode;
-
-import '../problems.dart' as problems show unhandled;
-
-import '../scope.dart' show Scope;
-
-final NoArguments noArgumentsSentinel = new NoArguments();
-
-abstract class TypePromotionState {
-  final Uri uri;
-
-  final List<Scope> scopes = <Scope>[new Scope.top(isModifiable: true)];
-
-  final List<Builder> stack = <Builder>[];
-
-  TypePromotionState(this.uri);
-
-  Scope get currentScope => scopes.last;
-
-  void enterScope(String debugName) {
-    scopes.add(new Scope.nested(currentScope, "block"));
-  }
-
-  Scope exitScope(Token token) {
-    return scopes.removeLast();
-  }
-
-  void declareIdentifier(Token token) {
-    String name = token.lexeme;
-    LocatedMessage error = currentScope.declare(
-        name, new UnspecifiedDeclaration(name, uri, token.charOffset), uri);
-    if (error != null) {
-      report(error, Severity.error);
-    }
-    pushNull(token.lexeme, token);
-  }
-
-  void registerWrite(UnspecifiedDeclaration declaration, Token token) {}
-
-  void registerPromotionCandidate(
-      UnspecifiedDeclaration declaration, Token token) {}
-
-  void pushReference(Token token) {
-    String name = token.lexeme;
-    Builder declaration = currentScope.lookup(name, token.charOffset, uri);
-    stack.add(declaration);
-  }
-
-  Builder pop() => stack.removeLast();
-
-  void push(Builder declaration) {
-    stack.add(declaration);
-  }
-
-  Builder popPushNull(String name, Token token) {
-    int last = stack.length - 1;
-    Builder declaration = stack[last];
-    stack[last] = nullValue(name, token);
-    return declaration;
-  }
-
-  void discard(int count) {
-    stack.length = stack.length - count;
-  }
-
-  void pushNull(String name, Token token) {
-    stack.add(nullValue(name, token));
-  }
-
-  Builder nullValue(String name, Token token) => null;
-
-  void report(LocatedMessage message, Severity severity,
-      {List<LocatedMessage> context});
-
-  void trace(String message, Token token) {}
-
-  void checkEmpty(Token token) {}
-}
-
-class UnspecifiedDeclaration extends BuilderImpl {
-  final String name;
-
-  @override
-  final Uri fileUri;
-
-  @override
-  int charOffset;
-
-  UnspecifiedDeclaration(this.name, this.fileUri, this.charOffset);
-
-  @override
-  Builder get parent => null;
-
-  @override
-  String get fullNameForErrors => name;
-
-  @override
-  String toString() => "UnspecifiedDeclaration($name)";
-}
-
-class NoArguments extends BuilderImpl {
-  NoArguments();
-
-  @override
-  Uri get fileUri => null;
-
-  @override
-  int get charOffset => -1;
-
-  @override
-  Builder get parent => null;
-
-  @override
-  String get fullNameForErrors => "<<no arguments>>";
-
-  @override
-  String toString() => fullNameForErrors;
-}
-
-class TypePromotionLookAheadListener extends Listener {
-  final TypePromotionState state;
-
-  TypePromotionLookAheadListener(this.state);
-
-  Uri get uri => state.uri;
-
-  void logEvent(String name) {
-    throw new UnimplementedError(name);
-  }
-
-  void debugEvent(String name, Token token) {
-    // state.trace(name, token);
-  }
-
-  @override
-  void endArguments(int count, Token beginToken, Token endToken) {
-    debugEvent("Arguments", beginToken);
-    state.discard(count);
-    state.pushNull("%Arguments%", endToken);
-  }
-
-  @override
-  void handleNoArguments(Token token) {
-    debugEvent("NoArguments", token);
-    state.push(noArgumentsSentinel);
-  }
-
-  @override
-  void handleAsOperator(Token operator) {
-    debugEvent("AsOperator", operator);
-    state.popPushNull(operator.lexeme, operator);
-  }
-
-  @override
-  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
-    debugEvent("Assert", assertKeyword);
-    if (commaToken != null) {
-      state.pop(); // Message.
-    }
-    state.pop(); // Condition.
-    switch (kind) {
-      case Assert.Expression:
-        state.pushNull("%AssertExpression%", assertKeyword);
-        break;
-
-      case Assert.Initializer:
-        state.pushNull("%AssertInitializer%", assertKeyword);
-        break;
-
-      case Assert.Statement:
-        break;
-    }
-  }
-
-  @override
-  void handleAssignmentExpression(Token token) {
-    debugEvent("AssignmentExpression", token);
-    state.pop(); // Right-hand side.
-    Builder lhs = state.popPushNull(token.lexeme, token);
-    if (lhs is UnspecifiedDeclaration) {
-      state.registerWrite(lhs, token);
-    }
-  }
-
-  @override
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
-    debugEvent("AsyncModifier", asyncToken);
-  }
-
-  @override
-  void endAwaitExpression(Token beginToken, Token endToken) {
-    debugEvent("AwaitExpression", beginToken);
-    state.popPushNull(beginToken.lexeme, beginToken); // Expression.
-  }
-
-  @override
-  void endInvalidAwaitExpression(
-      Token beginToken, Token endToken, MessageCode errorCode) {
-    debugEvent("InvalidAwaitExpression", beginToken);
-    state.popPushNull(beginToken.lexeme, beginToken); // Expression.
-  }
-
-  @override
-  void endBinaryExpression(Token token) {
-    debugEvent("BinaryExpression", token);
-    state.pop(); // Right-hand side.
-    state.popPushNull(token.lexeme, token); // Left-hand side.
-  }
-
-  @override
-  void beginBlock(Token token, BlockKind blockKind) {
-    debugEvent("beginBlock", token);
-    state.enterScope("block");
-  }
-
-  @override
-  void endBlock(
-      int count, Token beginToken, Token endToken, BlockKind blockKind) {
-    debugEvent("Block", beginToken);
-    state.exitScope(endToken);
-  }
-
-  @override
-  void beginBlockFunctionBody(Token token) {
-    debugEvent("beginBlockFunctionBody", token);
-    state.enterScope("block-function-body");
-  }
-
-  @override
-  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
-    debugEvent("BlockFunctionBody", beginToken);
-    state.exitScope(endToken);
-  }
-
-  @override
-  void handleBreakStatement(
-      bool hasTarget, Token breakKeyword, Token endToken) {
-    debugEvent("BreakStatement", breakKeyword);
-    if (hasTarget) {
-      state.pop(); // Target.
-    }
-  }
-
-  @override
-  void endCascade() {
-    debugEvent("Cascade", null);
-    state.popPushNull("%Cascade%", null);
-  }
-
-  @override
-  void endCaseExpression(Token colon) {
-    debugEvent("CaseExpression", colon);
-    state.pop(); // Expression.
-  }
-
-  @override
-  void handleCaseMatch(Token caseKeyword, Token colon) {
-    debugEvent("CaseMatch", caseKeyword);
-  }
-
-  @override
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
-    debugEvent("CatchBlock", catchKeyword);
-  }
-
-  @override
-  void endCatchClause(Token token) {
-    debugEvent("CatchClause", token);
-  }
-
-  @override
-  void endClassDeclaration(Token beginToken, Token endToken) {
-    debugEvent("ClassDeclaration", beginToken);
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleClassExtends(Token extendsKeyword) {
-    debugEvent("ClassExtends", extendsKeyword);
-  }
-
-  @override
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
-    debugEvent("ClassHeader", begin);
-    state.pop(); // Class name.
-    state.checkEmpty(classKeyword);
-  }
-
-  @override
-  void handleClassNoWithClause() {
-    debugEvent("ClassNoWithClause", null);
-  }
-
-  @override
-  void endClassOrMixinBody(
-      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
-    debugEvent("ClassOrMixinBody", beginToken);
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
-    debugEvent("ClassOrMixinImplements", implementsKeyword);
-  }
-
-  @override
-  void handleClassWithClause(Token withKeyword) {
-    debugEvent("ClassWithClause", withKeyword);
-  }
-
-  @override
-  void endCombinators(int count) {
-    debugEvent("Combinators", null);
-  }
-
-  @override
-  void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {
-    debugEvent("CommentReference", newKeyword);
-    unhandled("CommentReference", newKeyword);
-  }
-
-  @override
-  void handleNoCommentReference() {
-    debugEvent("NoCommentReference", null);
-    unhandled("NoCommentReference", null);
-  }
-
-  @override
-  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
-    debugEvent("CommentReferenceText", null);
-    unhandled("CommentReferenceText", null);
-  }
-
-  @override
-  void endCompilationUnit(int count, Token token) {
-    debugEvent("CompilationUnit", token);
-    print(state.stack);
-  }
-
-  @override
-  void endConditionalExpression(Token question, Token colon) {
-    debugEvent("ConditionalExpression", question);
-    state.pop(); // Otherwise expression.
-    state.pop(); // Then expression.
-    state.popPushNull(question.lexeme, question); // Condition.
-  }
-
-  @override
-  void handleConditionalExpressionColon() {
-    debugEvent("ConditionalExpressionColon", null);
-    // TODO(ahe): Rename this event. This is not handling any colons as it
-    // isn't being passed a colon. One alternative is
-    // handleConditionalThenExpression, but check the specification for naming
-    // conventions. Kernel uses "then" and "otherwise".
-  }
-
-  @override
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
-    debugEvent("ConditionalUri", ifKeyword);
-    unhandled("ConditionalUri", ifKeyword);
-  }
-
-  @override
-  void endConditionalUris(int count) {
-    debugEvent("ConditionalUris", null);
-  }
-
-  @override
-  void endConstExpression(Token token) {
-    debugEvent("ConstExpression", token);
-    doConstuctorInvocation(token, true);
-  }
-
-  @override
-  void endForControlFlow(Token token) {
-    // TODO(danrubel) add support for for control flow collection entries
-    // but for now this is ignored and an error reported in the body builder.
-  }
-
-  @override
-  void endForInControlFlow(Token token) {
-    // TODO(danrubel) add support for for control flow collection entries
-    // but for now this is ignored and an error reported in the body builder.
-  }
-
-  @override
-  void handleElseControlFlow(Token token) {}
-
-  @override
-  void endIfControlFlow(Token token) {
-    state.pop(); // Element.
-    state.pop(); // Condition.
-    state.pushNull("%IfControlFlow%", token);
-  }
-
-  @override
-  void endIfElseControlFlow(Token token) {
-    state.pop(); // Else element.
-    state.pop(); // Then element.
-    state.pop(); // Condition.
-    state.pushNull("%IfElseControlFlow%", token);
-  }
-
-  @override
-  void handleSpreadExpression(Token spreadToken) {
-    // TODO(danrubel) add support for spread collections
-    // but for now this is ignored and an error reported in the body builder.
-    // The top of stack is the spread collection expression.
-  }
-
-  void doConstuctorInvocation(Token token, bool isConst) {
-    state.pop(); // Arguments.
-    state.popPushNull(token.lexeme, token); // Constructor reference.
-  }
-
-  @override
-  void endConstLiteral(Token token) {
-    debugEvent("ConstLiteral", token);
-    state.popPushNull("%ConstLiteral%", token);
-  }
-
-  @override
-  void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
-    debugEvent("ConstructorReference", start);
-    if (periodBeforeName != null) {
-      state.pop(); // Prefix.
-    }
-    state.popPushNull("%ConstructorReference%", start);
-  }
-
-  @override
-  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
-    debugEvent("NoConstructorReferenceContinuationAfterTypeArguments", token);
-  }
-
-  @override
-  void handleContinueStatement(
-      bool hasTarget, Token continueKeyword, Token endToken) {
-    debugEvent("ContinueStatement", continueKeyword);
-    if (hasTarget) {
-      state.pop(); // Target.
-    }
-  }
-
-  @override
-  void handleDirectivesOnly() {
-    debugEvent("DirectivesOnly", null);
-    unhandled("DirectivesOnly", null);
-  }
-
-  @override
-  void endDoWhileStatement(
-      Token doKeyword, Token whileKeyword, Token endToken) {
-    debugEvent("DoWhileStatement", doKeyword);
-    state.pop(); // Condition.
-  }
-
-  @override
-  void endDoWhileStatementBody(Token token) {
-    debugEvent("DoWhileStatementBody", token);
-  }
-
-  @override
-  void handleDottedName(int count, Token firstIdentifier) {
-    debugEvent("DottedName", firstIdentifier);
-    unhandled("DottedName", firstIdentifier);
-  }
-
-  @override
-  void endElseStatement(Token token) {
-    debugEvent("ElseStatement", token);
-  }
-
-  @override
-  void handleEmptyFunctionBody(Token semicolon) {
-    debugEvent("EmptyFunctionBody", semicolon);
-  }
-
-  @override
-  void handleEmptyStatement(Token token) {
-    debugEvent("EmptyStatement", token);
-  }
-
-  @override
-  void beginEnum(Token enumKeyword) {
-    debugEvent("beginEnum", enumKeyword);
-    state.checkEmpty(enumKeyword);
-  }
-
-  @override
-  void endEnum(Token enumKeyword, Token leftBrace, int count) {
-    debugEvent("endEnum", enumKeyword);
-    state.discard(count); // Enum values.
-    state.pop(); // Enum name.
-    state.checkEmpty(enumKeyword);
-  }
-
-  @override
-  void endExport(Token exportKeyword, Token semicolon) {
-    debugEvent("Export", exportKeyword);
-    state.pop(); // Export URI.
-    state.checkEmpty(semicolon);
-  }
-
-  @override
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
-    debugEvent("ExpressionFunctionBody", arrowToken);
-    state.pop();
-  }
-
-  @override
-  void handleExpressionStatement(Token token) {
-    debugEvent("ExpressionStatement", token);
-    state.pop();
-  }
-
-  @override
-  void handleExtraneousExpression(Token token, Message message) {
-    debugEvent("ExtraneousExpression", token);
-    unhandled("ExtraneousExpression", token);
-  }
-
-  @override
-  void endClassFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    debugEvent("ClassFactoryMethod", beginToken);
-    state.pop(); // Name.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void endFieldInitializer(Token assignment, Token token) {
-    debugEvent("FieldInitializer", assignment);
-    state.pop(); // Initializer.
-  }
-
-  @override
-  void handleNoFieldInitializer(Token token) {
-    debugEvent("NoFieldInitializer", token);
-  }
-
-  @override
-  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    debugEvent("Fields", staticToken);
-    state.discard(count); // Field names.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleFinallyBlock(Token finallyKeyword) {
-    debugEvent("FinallyBlock", finallyKeyword);
-  }
-
-  @override
-  void endForIn(Token endToken) {
-    debugEvent("ForIn", endToken);
-  }
-
-  @override
-  void endForInBody(Token token) {
-    debugEvent("ForInBody", token);
-  }
-
-  @override
-  void endForInExpression(Token token) {
-    debugEvent("ForInExpression", token);
-    state.pop(); // Expression.
-  }
-
-  @override
-  void handleForInitializerEmptyStatement(Token token) {
-    debugEvent("ForInitializerEmptyStatement", token);
-  }
-
-  @override
-  void handleForInitializerExpressionStatement(Token token, bool forIn) {
-    debugEvent("ForInitializerExpressionStatement", token);
-    state.pop(); // Expression.
-  }
-
-  @override
-  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
-    debugEvent("ForInitializerLocalVariableDeclaration", token);
-  }
-
-  @override
-  void handleForLoopParts(Token forKeyword, Token leftParen,
-      Token leftSeparator, int updateExpressionCount) {
-    debugEvent("handleForLoopParts", forKeyword);
-    state.discard(updateExpressionCount);
-  }
-
-  @override
-  void endForStatement(Token endToken) {
-    debugEvent("ForStatement", endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    debugEvent("ForStatementBody", token);
-  }
-
-  @override
-  void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
-      Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
-      FormalParameterKind kind,
-      MemberKind memberKind) {
-    debugEvent("FormalParameter", thisKeyword);
-    state.pop(); // Parameter name.
-  }
-
-  @override
-  void endFormalParameterDefaultValueExpression() {
-    debugEvent("FormalParameterDefaultValueExpression", null);
-    state.pop();
-  }
-
-  @override
-  void handleFormalParameterWithoutValue(Token token) {
-    debugEvent("FormalParameterWithoutValue", token);
-  }
-
-  @override
-  void endFormalParameters(
-      int count, Token beginToken, Token endToken, MemberKind kind) {
-    debugEvent("FormalParameters", beginToken);
-  }
-
-  @override
-  void handleNoFormalParameters(Token token, MemberKind kind) {
-    debugEvent("NoFormalParameters", token);
-  }
-
-  @override
-  void handleNoFunctionBody(Token token) {
-    debugEvent("NoFunctionBody", token);
-    unhandled("NoFunctionBody", token);
-  }
-
-  @override
-  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
-    debugEvent("FunctionBodySkipped", token);
-    unhandled("FunctionBodySkipped", token);
-  }
-
-  @override
-  void endFunctionExpression(Token beginToken, Token token) {
-    debugEvent("FunctionExpression", beginToken);
-    state.pushNull("%function%", token);
-  }
-
-  @override
-  void endFunctionName(Token beginToken, Token token) {
-    debugEvent("FunctionName", beginToken);
-  }
-
-  @override
-  void endFunctionType(Token functionToken, Token questionMark) {
-    debugEvent("FunctionType", functionToken);
-  }
-
-  @override
-  void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
-    debugEvent("FunctionTypeAlias", typedefKeyword);
-    state.pop(); // Name.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
-    debugEvent("FunctionTypedFormalParameter", nameToken);
-  }
-
-  @override
-  void endHide(Token hideKeyword) {
-    debugEvent("Hide", hideKeyword);
-  }
-
-  @override
-  void handleIdentifier(Token token, IdentifierContext context) {
-    debugEvent("Identifier ${context}", token);
-    if (context.inSymbol) {
-      // Do nothing.
-    } else if (context.inDeclaration) {
-      if (identical(IdentifierContext.localVariableDeclaration, context) ||
-          identical(IdentifierContext.formalParameterDeclaration, context)) {
-        state.declareIdentifier(token);
-      } else {
-        state.pushNull(token.lexeme, token);
-      }
-    } else if (context.isContinuation) {
-      state.pushNull(token.lexeme, token);
-    } else if (context.isScopeReference) {
-      state.pushReference(token);
-    } else {
-      state.pushNull(token.lexeme, token);
-    }
-  }
-
-  @override
-  void handleIdentifierList(int count) {
-    debugEvent("IdentifierList", null);
-    state.discard(count);
-  }
-
-  @override
-  void endIfStatement(Token ifToken, Token elseToken) {
-    debugEvent("IfStatement", ifToken);
-    state.pop(); // Condition.
-  }
-
-  @override
-  void endImplicitCreationExpression(Token token) {
-    debugEvent("ImplicitCreationExpression", token);
-    doConstuctorInvocation(token, false);
-  }
-
-  @override
-  void endImport(Token importKeyword, Token semicolon) {
-    debugEvent("Import", importKeyword);
-    state.pop(); // Import URI.
-    state.checkEmpty(semicolon);
-  }
-
-  @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    debugEvent("ImportPrefix", deferredKeyword);
-    if (asKeyword != null) {
-      state.pop(); // Prefix name.
-    }
-  }
-
-  @override
-  void handleIndexedExpression(
-      Token openSquareBracket, Token closeSquareBracket) {
-    debugEvent("IndexedExpression", openSquareBracket);
-    state.pop(); // Index.
-    state.popPushNull("%indexed%", closeSquareBracket); // Expression.
-  }
-
-  @override
-  void endInitializedIdentifier(Token nameToken) {
-    debugEvent("InitializedIdentifier", nameToken);
-  }
-
-  @override
-  void endInitializer(Token token) {
-    debugEvent("Initializer", token);
-    state.pop(); // Initializer.
-  }
-
-  @override
-  void endInitializers(int count, Token beginToken, Token endToken) {
-    debugEvent("Initializers", beginToken);
-  }
-
-  @override
-  void handleNoInitializers() {
-    debugEvent("NoInitializers", null);
-  }
-
-  @override
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
-    debugEvent("InterpolationExpression", leftBracket);
-    state.popPushNull(r"$", leftBracket);
-  }
-
-  @override
-  void handleInvalidExpression(Token token) {
-    // TODO(ahe): The parser doesn't generate this event anymore.
-    debugEvent("InvalidExpression", token);
-    unhandled("InvalidExpression", token);
-  }
-
-  @override
-  void handleInvalidFunctionBody(Token token) {
-    debugEvent("InvalidFunctionBody", token);
-  }
-
-  @override
-  void handleInvalidMember(Token endToken) {
-    debugEvent("InvalidMember", endToken);
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
-    debugEvent("InvalidOperatorName", operatorKeyword);
-    state.checkEmpty(operatorKeyword);
-  }
-
-  @override
-  void handleInvalidStatement(Token token, Message message) {
-    debugEvent("InvalidStatement", token);
-  }
-
-  @override
-  void handleInvalidTopLevelBlock(Token token) {
-    debugEvent("InvalidTopLevelBlock", token);
-    state.checkEmpty(token);
-  }
-
-  @override
-  void handleInvalidTopLevelDeclaration(Token endToken) {
-    debugEvent("InvalidTopLevelDeclaration", endToken);
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleInvalidTypeArguments(Token token) {
-    debugEvent("InvalidTypeArguments", token);
-  }
-
-  @override
-  void handleInvalidTypeReference(Token token) {
-    debugEvent("InvalidTypeReference", token);
-    unhandled("InvalidTypeReference", token);
-  }
-
-  @override
-  void handleIsOperator(Token isOperator, Token not) {
-    debugEvent("IsOperator", isOperator);
-    Builder lhs = state.popPushNull(isOperator.lexeme, isOperator);
-    if (not == null && lhs is UnspecifiedDeclaration) {
-      state.registerPromotionCandidate(lhs, isOperator);
-    }
-  }
-
-  @override
-  void handleLabel(Token token) {
-    debugEvent("Label", token);
-    state.pop(); // Label.
-  }
-
-  @override
-  void endLabeledStatement(int labelCount) {
-    debugEvent("LabeledStatement", null);
-  }
-
-  @override
-  void endLibraryName(Token libraryKeyword, Token semicolon) {
-    debugEvent("LibraryName", libraryKeyword);
-    state.pop(); // Library name.
-    state.checkEmpty(semicolon);
-  }
-
-  @override
-  void handleLiteralBool(Token token) {
-    debugEvent("LiteralBool", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void handleLiteralDouble(Token token) {
-    debugEvent("LiteralDouble", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void handleLiteralInt(Token token) {
-    debugEvent("LiteralInt", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void handleLiteralList(
-      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
-    debugEvent("LiteralList", leftBracket);
-    state.discard(count);
-    state.pushNull("[]", leftBracket);
-  }
-
-  @override
-  void handleLiteralSetOrMap(
-    int count,
-    Token leftBrace,
-    Token constKeyword,
-    Token rightBrace,
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry,
-  ) {
-    debugEvent("LiteralSetOrMap", leftBrace);
-    state.discard(count);
-    state.pushNull("{}", leftBrace);
-  }
-
-  @override
-  void handleLiteralMapEntry(Token colon, Token endToken) {
-    debugEvent("LiteralMapEntry", colon);
-    state.pop(); // Value.
-    state.popPushNull("%LiteralMapEntry%", colon); // Key.
-  }
-
-  @override
-  void handleLiteralNull(Token token) {
-    debugEvent("LiteralNull", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void beginLiteralString(Token token) {
-    debugEvent("beginLiteralString", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void endLiteralString(int interpolationCount, Token endToken) {
-    debugEvent("LiteralString", endToken);
-    state.discard(interpolationCount * 2);
-    state.popPushNull("%string%", endToken);
-  }
-
-  @override
-  void endLiteralSymbol(Token hashToken, int identifierCount) {
-    debugEvent("LiteralSymbol", hashToken);
-    state.pushNull(hashToken.lexeme, hashToken);
-  }
-
-  @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    debugEvent("LocalFunctionDeclaration", endToken);
-    state.pop(); // Function name.
-  }
-
-  @override
-  void endMember() {
-    debugEvent("Member", null);
-    state.checkEmpty(null);
-  }
-
-  @override
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
-    debugEvent("Metadata", beginToken);
-    state.pop(); // Arguments.
-    if (periodBeforeName != null) {
-      state.pop(); // Suffix.
-    }
-    state.pop(); // Qualifier.
-  }
-
-  @override
-  void endMetadataStar(int count) {
-    debugEvent("MetadataStar", null);
-  }
-
-  @override
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {
-    debugEvent("beginMethod", name);
-    state.checkEmpty(name);
-  }
-
-  @override
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    debugEvent("endMethod", endToken);
-    state.pop(); // Method name.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
-    debugEvent("MixinDeclaration", mixinKeyword);
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleMixinHeader(Token mixinKeyword) {
-    debugEvent("MixinHeader", mixinKeyword);
-    state.pop(); // Mixin name.
-    state.checkEmpty(mixinKeyword);
-  }
-
-  @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
-    debugEvent("MixinOn", onKeyword);
-  }
-
-  @override
-  void handleNoName(Token token) {
-    debugEvent("NoName", token);
-    state.pushNull("%NoName%", token);
-  }
-
-  @override
-  void handleNamedArgument(Token colon) {
-    debugEvent("NamedArgument", colon);
-    state.pop(); // Expression.
-    state.popPushNull("%NamedArgument%", colon); // Identifier.
-  }
-
-  @override
-  void endNamedFunctionExpression(Token endToken) {
-    debugEvent("NamedFunctionExpression", endToken);
-    state.popPushNull(
-        "%named function expression%", endToken); // Function name.
-  }
-
-  @override
-  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
-    debugEvent("NamedMixinApplication", begin);
-    state.pop(); // Mixin application name.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void handleNamedMixinApplicationWithClause(Token withKeyword) {
-    debugEvent("NamedMixinApplicationWithClause", withKeyword);
-  }
-
-  @override
-  void handleNativeClause(Token nativeToken, bool hasName) {
-    debugEvent("NativeClause", nativeToken);
-    if (hasName) {
-      state.pop(); // Name.
-    }
-  }
-
-  @override
-  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
-    debugEvent("NativeFunctionBody", nativeToken);
-  }
-
-  @override
-  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
-    debugEvent("NativeFunctionBodyIgnored", nativeToken);
-  }
-
-  @override
-  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
-    debugEvent("NativeFunctionBodySkipped", nativeToken);
-  }
-
-  @override
-  void endNewExpression(Token token) {
-    debugEvent("NewExpression", token);
-    doConstuctorInvocation(token, false);
-  }
-
-  @override
-  void handleOperator(Token token) {
-    debugEvent("Operator", token);
-    unhandled("Operator", token);
-  }
-
-  @override
-  void handleOperatorName(Token operatorKeyword, Token token) {
-    debugEvent("OperatorName", operatorKeyword);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void endOptionalFormalParameters(
-      int count, Token beginToken, Token endToken) {
-    debugEvent("OptionalFormalParameters", beginToken);
-  }
-
-  @override
-  void handleParenthesizedCondition(Token token) {
-    debugEvent("ParenthesizedCondition", token);
-  }
-
-  @override
-  void handleParenthesizedExpression(Token token) {
-    debugEvent("ParenthesizedExpression", token);
-    state.popPushNull("%(expr)%", token);
-  }
-
-  @override
-  void endPart(Token partKeyword, Token semicolon) {
-    debugEvent("Part", partKeyword);
-    state.pop(); // URI.
-    state.checkEmpty(semicolon);
-  }
-
-  @override
-  void endPartOf(
-      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
-    debugEvent("PartOf", partKeyword);
-    state.pop(); // Name or URI.
-    state.checkEmpty(semicolon);
-  }
-
-  @override
-  void handleQualified(Token period) {
-    debugEvent("Qualified", period);
-    state.pop(); // Suffix.
-    state.popPushNull("%Qualified%", period); // Qualifier.
-  }
-
-  @override
-  void handleRecoverClassHeader() {
-    debugEvent("RecoverClassHeader", null);
-    state.checkEmpty(null);
-  }
-
-  @override
-  void handleRecoverImport(Token semicolon) {
-    debugEvent("RecoverImport", semicolon);
-    unhandled("RecoverImport", semicolon);
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    debugEvent("RecoverMixinHeader", null);
-    state.checkEmpty(null);
-  }
-
-  @override
-  void handleRecoverableError(
-      Message message, Token startToken, Token endToken) {
-    debugEvent("RecoverableError ${message.message}", startToken);
-  }
-
-  @override
-  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
-    debugEvent("RedirectingFactoryBody", beginToken);
-    state.pop(); // Constructor reference.
-  }
-
-  @override
-  void endRethrowStatement(Token rethrowToken, Token endToken) {
-    debugEvent("RethrowStatement", rethrowToken);
-  }
-
-  @override
-  void endReturnStatement(
-      bool hasExpression, Token beginToken, Token endToken) {
-    debugEvent("ReturnStatement", beginToken);
-    if (hasExpression) {
-      state.pop(); // Expression.
-    }
-  }
-
-  @override
-  void handleScript(Token token) {
-    debugEvent("Script", token);
-    unhandled("Script", token);
-  }
-
-  @override
-  void handleSend(Token beginToken, Token endToken) {
-    debugEvent("Send", beginToken);
-    Builder arguments = state.pop();
-    if (identical(arguments, noArgumentsSentinel)) {
-      // Leave the receiver on the stack.
-    } else {
-      state.popPushNull("%send%", beginToken);
-    }
-  }
-
-  @override
-  void endShow(Token showKeyword) {
-    debugEvent("Show", showKeyword);
-  }
-
-  @override
-  void handleStringJuxtaposition(int literalCount) {
-    debugEvent("StringJuxtaposition", null);
-    state.discard(literalCount);
-    state.pushNull("%StringJuxtaposition%", null);
-  }
-
-  @override
-  void handleStringPart(Token token) {
-    debugEvent("StringPart", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void handleSuperExpression(Token token, IdentifierContext context) {
-    debugEvent("SuperExpression", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
-    debugEvent("SwitchBlock", beginToken);
-    state.pop(); // Expression.
-  }
-
-  @override
-  void endSwitchCase(
-      int labelCount,
-      int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
-      int statementCount,
-      Token firstToken,
-      Token endToken) {
-    debugEvent("SwitchCase", defaultKeyword);
-  }
-
-  @override
-  void endSwitchStatement(Token switchKeyword, Token endToken) {
-    debugEvent("SwitchStatement", switchKeyword);
-  }
-
-  @override
-  void handleSymbolVoid(Token token) {
-    debugEvent("SymbolVoid", token);
-    unhandled("SymbolVoid", token);
-  }
-
-  @override
-  void endThenStatement(Token token) {
-    debugEvent("ThenStatement", token);
-  }
-
-  @override
-  void handleThisExpression(Token token, IdentifierContext context) {
-    debugEvent("ThisExpression", token);
-    state.pushNull(token.lexeme, token);
-  }
-
-  @override
-  void handleThrowExpression(Token throwToken, Token endToken) {
-    debugEvent("ThrowExpression", throwToken);
-    state.popPushNull(throwToken.lexeme, throwToken);
-  }
-
-  @override
-  void endTopLevelDeclaration(Token token) {
-    debugEvent("TopLevelDeclaration", token);
-    state.checkEmpty(token);
-  }
-
-  @override
-  void endTopLevelFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    debugEvent("TopLevelFields", staticToken);
-    state.discard(count); // Field names.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
-    debugEvent("beginTopLevelMethod", lastConsumed.next);
-    state.checkEmpty(lastConsumed.next);
-  }
-
-  @override
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
-    debugEvent("endTopLevelMethod", beginToken);
-    state.pop(); // Method name.
-    state.checkEmpty(endToken);
-  }
-
-  @override
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
-    debugEvent("TryStatement", tryKeyword);
-  }
-
-  @override
-  void handleType(Token beginToken, Token questionMark) {
-    debugEvent("Type", beginToken);
-    state.pop();
-  }
-
-  @override
-  void handleNoType(Token lastConsumed) {
-    debugEvent("NoType", lastConsumed);
-  }
-
-  @override
-  void endTypeArguments(int count, Token beginToken, Token endToken) {
-    debugEvent("TypeArguments", beginToken);
-  }
-
-  @override
-  void handleNoTypeArguments(Token token) {
-    debugEvent("NoTypeArguments", token);
-  }
-
-  @override
-  void endTypeList(int count) {
-    debugEvent("TypeList", null);
-  }
-
-  @override
-  void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
-    debugEvent("TypeVariable", token);
-    state.pop(); // Name.
-  }
-
-  @override
-  void endTypeVariables(Token beginToken, Token endToken) {
-    debugEvent("TypeVariables", beginToken);
-  }
-
-  @override
-  void handleNoTypeVariables(Token token) {
-    debugEvent("NoTypeVariables", token);
-  }
-
-  @override
-  void handleTypeVariablesDefined(Token token, int count) {
-    debugEvent("TypeVariablesDefined", token);
-  }
-
-  @override
-  void handleUnaryPostfixAssignmentExpression(Token token) {
-    debugEvent("UnaryPostfixAssignmentExpression", token);
-    Builder expr = state.popPushNull(token.lexeme, token);
-    if (expr is UnspecifiedDeclaration) {
-      state.registerWrite(expr, token);
-    }
-  }
-
-  @override
-  void handleUnaryPrefixAssignmentExpression(Token token) {
-    debugEvent("UnaryPrefixAssignmentExpression", token);
-    Builder expr = state.popPushNull(token.lexeme, token);
-    if (expr is UnspecifiedDeclaration) {
-      state.registerWrite(expr, token);
-    }
-  }
-
-  @override
-  void handleUnaryPrefixExpression(Token token) {
-    debugEvent("UnaryPrefixExpression", token);
-    state.popPushNull("%UnaryPrefixExpression%", token);
-  }
-
-  @override
-  void handleNonNullAssertExpression(Token token) {
-    debugEvent("NonNullAssertExpression", token);
-    state.popPushNull("%NonNullAssertExpression%", token);
-  }
-
-  @override
-  void handleUnescapeError(
-      Message message, Token location, int stringOffset, int length) {
-    debugEvent("UnescapeError", location);
-    unhandled("UnescapeError", location);
-  }
-
-  @override
-  void handleValuedFormalParameter(Token equals, Token token) {
-    debugEvent("ValuedFormalParameter", equals);
-  }
-
-  @override
-  void endVariableInitializer(Token assignmentOperator) {
-    debugEvent("VariableInitializer", assignmentOperator);
-    state.pop(); // Initializer.
-  }
-
-  @override
-  void handleNoVariableInitializer(Token token) {
-    debugEvent("NoVariableInitializer", token);
-  }
-
-  @override
-  void endVariablesDeclaration(int count, Token endToken) {
-    debugEvent("VariablesDeclaration", endToken);
-    state.discard(count); // Variable names.
-  }
-
-  @override
-  void handleVoidKeyword(Token token) {
-    debugEvent("VoidKeyword", token);
-  }
-
-  @override
-  void endWhileStatement(Token whileKeyword, Token endToken) {
-    debugEvent("WhileStatement", whileKeyword);
-    state.pop(); // Condition.
-  }
-
-  @override
-  void endWhileStatementBody(Token token) {
-    debugEvent("WhileStatementBody", token);
-  }
-
-  @override
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
-    debugEvent("YieldStatement", yieldToken);
-    state.pop(); // Expression.
-  }
-
-  void unhandled(String event, Token token) {
-    problems.unhandled(
-        event, "TypePromotionLookAheadListener", token?.charOffset ?? -1, uri);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index dde97c4..1268e81 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
@@ -2,6 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
+    show NullValue;
+
+import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart' as type;
+
+import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as type
     show Token;
 
@@ -46,137 +53,60 @@
 
 import '../source/outline_builder.dart' as type;
 
-import 'stack_listener.dart' show NullValue;
-
-import 'stack_listener.dart' as type;
-
-/// [ValueKind] is used in [StackListener.checkState] to document and check the
-/// expected values of the stack.
-///
-/// Add new value kinds as needed for documenting and checking the various stack
-/// listener implementations.
-abstract class ValueKind {
-  const ValueKind();
-
-  /// Checks the [value] an returns `true` if the value is of the expected kind.
-  bool check(Object value);
-
-  static const ValueKind Arguments = const _SingleValueKind<type.Arguments>();
+class ValueKinds {
+  static const ValueKind Arguments = const SingleValueKind<type.Arguments>();
   static const ValueKind ArgumentsOrNull =
-      const _SingleValueKind<type.Arguments>(NullValue.Arguments);
-  static const ValueKind Expression = const _SingleValueKind<type.Expression>();
+      const SingleValueKind<type.Arguments>(NullValue.Arguments);
+  static const ValueKind Expression = const SingleValueKind<type.Expression>();
   static const ValueKind ExpressionOrNull =
-      const _SingleValueKind<type.Expression>(NullValue.Expression);
-  static const ValueKind Identifier = const _SingleValueKind<type.Identifier>();
+      const SingleValueKind<type.Expression>(NullValue.Expression);
+  static const ValueKind Identifier = const SingleValueKind<type.Identifier>();
   static const ValueKind IdentifierOrNull =
-      const _SingleValueKind<type.Identifier>(NullValue.Identifier);
-  static const ValueKind Integer = const _SingleValueKind<int>();
+      const SingleValueKind<type.Identifier>(NullValue.Identifier);
+  static const ValueKind Integer = const SingleValueKind<int>();
   static const ValueKind Formals =
-      const _SingleValueKind<List<type.FormalParameterBuilder>>();
+      const SingleValueKind<List<type.FormalParameterBuilder>>();
   static const ValueKind FormalsOrNull =
-      const _SingleValueKind<List<type.FormalParameterBuilder>>(
+      const SingleValueKind<List<type.FormalParameterBuilder>>(
           NullValue.FormalParameters);
-  static const ValueKind Generator = const _SingleValueKind<type.Generator>();
+  static const ValueKind Generator = const SingleValueKind<type.Generator>();
   static const ValueKind Initializer =
-      const _SingleValueKind<type.Initializer>();
-  static const ValueKind MethodBody = const _SingleValueKind<type.MethodBody>();
+      const SingleValueKind<type.Initializer>();
+  static const ValueKind MethodBody = const SingleValueKind<type.MethodBody>();
   static const ValueKind Modifiers =
-      const _SingleValueKind<List<type.Modifier>>();
+      const SingleValueKind<List<type.Modifier>>();
   static const ValueKind ModifiersOrNull =
-      const _SingleValueKind<List<type.Modifier>>(NullValue.Modifiers);
-  static const ValueKind Name = const _SingleValueKind<String>();
+      const SingleValueKind<List<type.Modifier>>(NullValue.Modifiers);
+  static const ValueKind Name = const SingleValueKind<String>();
   static const ValueKind NameOrNull =
-      const _SingleValueKind<String>(NullValue.Name);
+      const SingleValueKind<String>(NullValue.Name);
   static const ValueKind NameOrOperator =
-      const _UnionValueKind([Name, Operator]);
+      const UnionValueKind([Name, Operator]);
   static const ValueKind NameOrQualifiedNameOrOperator =
-      const _UnionValueKind([Name, QualifiedName, Operator]);
+      const UnionValueKind([Name, QualifiedName, Operator]);
   static const ValueKind NameOrParserRecovery =
-      const _UnionValueKind([Name, ParserRecovery]);
+      const UnionValueKind([Name, ParserRecovery]);
   static const ValueKind MetadataListOrNull =
-      const _SingleValueKind<List<type.MetadataBuilder>>(NullValue.Metadata);
-  static const ValueKind ObjectList = const _SingleValueKind<List<Object>>();
-  static const ValueKind Operator = const _SingleValueKind<type.Operator>();
+      const SingleValueKind<List<type.MetadataBuilder>>(NullValue.Metadata);
+  static const ValueKind ObjectList = const SingleValueKind<List<Object>>();
+  static const ValueKind Operator = const SingleValueKind<type.Operator>();
   static const ValueKind ParserRecovery =
-      const _SingleValueKind<type.ParserRecovery>();
+      const SingleValueKind<type.ParserRecovery>();
   static const ValueKind ProblemBuilder =
-      const _SingleValueKind<type.ProblemBuilder>();
+      const SingleValueKind<type.ProblemBuilder>();
   static const ValueKind QualifiedName =
-      const _SingleValueKind<type.QualifiedName>();
-  static const ValueKind Statement = const _SingleValueKind<type.Statement>();
-  static const ValueKind Token = const _SingleValueKind<type.Token>();
+      const SingleValueKind<type.QualifiedName>();
+  static const ValueKind Statement = const SingleValueKind<type.Statement>();
+  static const ValueKind Token = const SingleValueKind<type.Token>();
   static const ValueKind TokenOrNull =
-      const _SingleValueKind<type.Token>(NullValue.Token);
+      const SingleValueKind<type.Token>(NullValue.Token);
   static const ValueKind TypeArgumentsOrNull =
-      const _SingleValueKind<List<type.UnresolvedType>>(
-          NullValue.TypeArguments);
+      const SingleValueKind<List<type.UnresolvedType>>(NullValue.TypeArguments);
   static const ValueKind TypeBuilder =
-      const _SingleValueKind<type.TypeBuilder>();
+      const SingleValueKind<type.TypeBuilder>();
   static const ValueKind TypeBuilderOrNull =
-      const _SingleValueKind<type.TypeBuilder>(NullValue.Type);
+      const SingleValueKind<type.TypeBuilder>(NullValue.Type);
   static const ValueKind TypeVariableListOrNull =
-      const _SingleValueKind<List<type.TypeVariableBuilder>>(
+      const SingleValueKind<List<type.TypeVariableBuilder>>(
           NullValue.TypeVariables);
 }
-
-/// A [ValueKind] for a particular type [T], optionally with a recognized
-/// [NullValue].
-class _SingleValueKind<T> implements ValueKind {
-  final NullValue nullValue;
-
-  const _SingleValueKind([this.nullValue]);
-
-  @override
-  bool check(Object value) {
-    if (nullValue != null && value == nullValue) {
-      return true;
-    }
-    return value is T;
-  }
-
-  String toString() {
-    if (nullValue != null) {
-      return '$T or $nullValue';
-    }
-    return '$T';
-  }
-}
-
-/// A [ValueKind] for the union of a list of [ValueKind]s.
-class _UnionValueKind implements ValueKind {
-  final List<ValueKind> kinds;
-
-  const _UnionValueKind(this.kinds);
-
-  @override
-  bool check(Object value) {
-    for (ValueKind kind in kinds) {
-      if (kind.check(value)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    String or = '';
-    for (ValueKind kind in kinds) {
-      sb.write(or);
-      sb.write(kind);
-      or = ' or ';
-    }
-    return sb.toString();
-  }
-}
-
-/// Helper method for creating a list of [ValueKind]s of the given length
-/// [count].
-List<ValueKind> repeatedKinds(ValueKind kind, int count) {
-  return new List.generate(count, (_) => kind);
-}
-
-/// Helper method for creating a union of a list of [ValueKind]s.
-ValueKind unionOfKinds(List<ValueKind> kinds) {
-  return new _UnionValueKind(kinds);
-}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
index f7e9751..6b1f45a 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
@@ -111,14 +111,15 @@
       if (type2 is InterfaceType) {
         if (type2.classNode == futureOrClass) {
           // GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
-          return new InterfaceType(futureOrClass, <DartType>[
+          return new InterfaceType(
+              futureOrClass, Nullability.legacy, <DartType>[
             getStandardLowerBound(
                 type1.typeArguments[0], type2.typeArguments[0])
           ]);
         }
         if (type2.classNode == futureClass) {
           // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
-          return new InterfaceType(futureClass, <DartType>[
+          return new InterfaceType(futureClass, Nullability.legacy, <DartType>[
             getStandardLowerBound(
                 type1.typeArguments[0], type2.typeArguments[0])
           ]);
@@ -135,7 +136,7 @@
     if (type2 is InterfaceType && type2.classNode == futureOrClass) {
       if (type1 is InterfaceType && type1.classNode == futureClass) {
         // GLB(Future<A>, FutureOr<B>) == Future<GLB(B, A)>
-        return new InterfaceType(futureClass, <DartType>[
+        return new InterfaceType(futureClass, Nullability.legacy, <DartType>[
           getStandardLowerBound(type2.typeArguments[0], type1.typeArguments[0])
         ]);
       }
@@ -316,7 +317,8 @@
 
     // Calculate the SLB of the return type.
     DartType returnType = getStandardLowerBound(f.returnType, g.returnType);
-    return new FunctionType(positionalParameters, returnType,
+    return new FunctionType(
+        positionalParameters, returnType, Nullability.legacy,
         namedParameters: namedParameters,
         requiredParameterCount: requiredParameterCount);
   }
@@ -343,7 +345,7 @@
     //   SUB(([int]) -> void, (int) -> void) = (int) -> void
     if (f.requiredParameterCount != g.requiredParameterCount) {
       return new InterfaceType(
-          functionClass, const <DynamicType>[], Nullability.legacy);
+          functionClass, Nullability.legacy, const <DynamicType>[]);
     }
     int requiredParameterCount = f.requiredParameterCount;
 
@@ -390,7 +392,8 @@
 
     // Calculate the SUB of the return type.
     DartType returnType = getStandardUpperBound(f.returnType, g.returnType);
-    return new FunctionType(positionalParameters, returnType,
+    return new FunctionType(
+        positionalParameters, returnType, Nullability.legacy,
         namedParameters: namedParameters,
         requiredParameterCount: requiredParameterCount);
   }
@@ -450,7 +453,7 @@
           tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
         }
       }
-      return new InterfaceType(type1.classNode, tArgs);
+      return new InterfaceType(type1.classNode, Nullability.legacy, tArgs);
     }
     return getLegacyLeastUpperBound(type1, type2);
   }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 42b0696..691ecdb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -16,6 +16,7 @@
         Procedure,
         TypeParameter,
         TypeParameterType,
+        Variance,
         VoidType;
 
 import 'package:kernel/type_algebra.dart' show substitute, Substitution;
@@ -209,9 +210,25 @@
         getTypeAsInstanceOf(subtype, supertype.classNode);
     if (matchingSupertypeOfSubtype == null) return false;
     for (int i = 0; i < supertype.classNode.typeParameters.length; i++) {
-      if (!_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
-          supertype.typeArguments[i])) {
-        return false;
+      // Generate constraints and subtype match with respect to variance.
+      int parameterVariance = supertype.classNode.typeParameters[i].variance;
+      if (parameterVariance == Variance.contravariant) {
+        if (!_isSubtypeMatch(supertype.typeArguments[i],
+            matchingSupertypeOfSubtype.typeArguments[i])) {
+          return false;
+        }
+      } else if (parameterVariance == Variance.invariant) {
+        if (!_isSubtypeMatch(supertype.typeArguments[i],
+                matchingSupertypeOfSubtype.typeArguments[i]) ||
+            !_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
+                supertype.typeArguments[i])) {
+          return false;
+        }
+      } else {
+        if (!_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
+            supertype.typeArguments[i])) {
+          return false;
+        }
       }
     }
     return true;
@@ -401,7 +418,8 @@
     for (int i = 0; i < params1.length; ++i) {
       TypeParameter pFresh = new TypeParameter(params2[i].name);
       freshTypeVariables.add(pFresh);
-      DartType variableFresh = new TypeParameterType(pFresh);
+      DartType variableFresh =
+          new TypeParameterType(pFresh, Nullability.legacy);
       substitution1[params1[i]] = variableFresh;
       substitution2[params2[i]] = variableFresh;
       DartType bound1 = substitute(params1[i].bound, substitution1);
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 9fbaded..696f7a4 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
@@ -20,7 +20,8 @@
         TypeParameter,
         TypeParameterType,
         TypedefType,
-        VariableDeclaration;
+        VariableDeclaration,
+        Variance;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -43,32 +44,15 @@
 
 import 'type_schema_environment.dart' show TypeSchemaEnvironment;
 
-enum Variance {
-  covariant,
-  contravariant,
-  invariant,
-}
-
-Variance invertVariance(Variance variance) {
-  switch (variance) {
-    case Variance.covariant:
-      return Variance.contravariant;
-    case Variance.contravariant:
-      return Variance.covariant;
-    case Variance.invariant:
-  }
-  return variance;
-}
-
 /// Visitor to check whether a given type mentions any of a class's type
 /// parameters in a non-covariant fashion.
 class IncludesTypeParametersNonCovariantly extends DartTypeVisitor<bool> {
-  Variance _variance;
+  int _variance;
 
   final List<TypeParameter> _typeParametersToSearchFor;
 
   IncludesTypeParametersNonCovariantly(this._typeParametersToSearchFor,
-      {Variance initialVariance})
+      {int initialVariance})
       : _variance = initialVariance;
 
   @override
@@ -77,12 +61,12 @@
   @override
   bool visitFunctionType(FunctionType node) {
     if (node.returnType.accept(this)) return true;
-    Variance oldVariance = _variance;
+    int oldVariance = _variance;
     _variance = Variance.invariant;
     for (TypeParameter parameter in node.typeParameters) {
       if (parameter.bound.accept(this)) return true;
     }
-    _variance = invertVariance(oldVariance);
+    _variance = Variance.combine(Variance.contravariant, oldVariance);
     for (DartType parameter in node.positionalParameters) {
       if (parameter.accept(this)) return true;
     }
@@ -95,9 +79,13 @@
 
   @override
   bool visitInterfaceType(InterfaceType node) {
-    for (DartType argument in node.typeArguments) {
-      if (argument.accept(this)) return true;
+    int oldVariance = _variance;
+    for (int i = 0; i < node.typeArguments.length; i++) {
+      _variance = Variance.combine(
+          node.classNode.typeParameters[i].variance, oldVariance);
+      if (node.typeArguments[i].accept(this)) return true;
     }
+    _variance = oldVariance;
     return false;
   }
 
@@ -108,7 +96,7 @@
 
   @override
   bool visitTypeParameterType(TypeParameterType node) {
-    return _variance != Variance.covariant &&
+    return !Variance.greaterThanOrEqual(_variance, node.parameter.variance) &&
         _typeParametersToSearchFor.contains(node.parameter);
   }
 }
@@ -307,10 +295,15 @@
   DartType variableType(VariableDeclaration variable) => variable.type;
 
   @override
-  DartType tryPromoteToType(DartType from, DartType to) {
-    if (from is TypeParameterType) {
-      return new TypeParameterType(from.parameter, to, from.nullability);
+  DartType tryPromoteToType(DartType to, DartType from) {
+    if (isSubtypeOf(to, from)) {
+      return to;
     }
-    return to;
+    if (from is TypeParameterType) {
+      if (isSubtypeOf(to, from.promotedBound ?? from.bound)) {
+        return new TypeParameterType(from.parameter, from.nullability, to);
+      }
+    }
+    return from;
   }
 }
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 5480c6c..ec83820 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
@@ -8,7 +8,7 @@
 
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
 
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -298,7 +298,10 @@
 
   void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
       ExpressionInferenceResult expressionResult) {
-    if (!isGenerator) return;
+    if (!isGenerator) {
+      node.expression = expressionResult.expression..parent = node;
+      return;
+    }
     DartType expectedType = node.isYieldStar
         ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
         : returnOrYieldContext;
@@ -406,7 +409,7 @@
 
   /// Performs type inference on the given function body.
   void inferFunctionBody(InferenceHelper helper, DartType returnType,
-      AsyncMarker asyncMarker, Statement body);
+      AsyncMarker asyncMarker, FunctionNode function, Statement body);
 
   /// Performs type inference on the given constructor initializer.
   void inferInitializer(InferenceHelper helper, Initializer initializer);
@@ -432,7 +435,7 @@
   /// Marker object to indicate that a function takes an unknown number
   /// of arguments.
   static final FunctionType unknownFunction =
-      new FunctionType(const [], const DynamicType());
+      new FunctionType(const [], const DynamicType(), Nullability.legacy);
 
   final TypeInferenceEngine engine;
 
@@ -782,7 +785,7 @@
 
       ExtensionAccessCandidate bestSoFar;
       List<ExtensionAccessCandidate> noneMoreSpecific = [];
-      library.scope.forEachExtension((ExtensionBuilder extensionBuilder) {
+      library.forEachExtensionInScope((ExtensionBuilder extensionBuilder) {
         MemberBuilder thisBuilder =
             extensionBuilder.lookupLocalMemberByName(name, setter: setter);
         MemberBuilder otherBuilder = extensionBuilder
@@ -834,8 +837,10 @@
                         !thisBuilder.isField &&
                         !thisBuilder.isStatic
                     ? new ObjectAccessTarget.extensionMember(
-                        thisBuilder.procedure,
-                        thisBuilder.extensionTearOff,
+                        setter
+                            ? thisBuilder.writeTarget
+                            : thisBuilder.invokeTarget,
+                        thisBuilder.readTarget,
                         thisBuilder.kind,
                         inferredTypeArguments)
                     : const ObjectAccessTarget.missing(),
@@ -944,6 +949,7 @@
             return substitution.substituteType(new FunctionType(
                 functionType.positionalParameters.skip(1).toList(),
                 functionType.returnType,
+                Nullability.legacy,
                 namedParameters: functionType.namedParameters,
                 typeParameters: functionType.typeParameters
                     .skip(target.inferredExtensionTypeArguments.length)
@@ -1441,6 +1447,8 @@
     ExpressionInferenceResult result;
     if (expression is ExpressionJudgment) {
       result = expression.acceptInference(visitor, typeContext);
+    } else if (expression is InternalExpression) {
+      result = expression.acceptInference(visitor, typeContext);
     } else {
       result = expression.accept1(visitor, typeContext);
     }
@@ -1477,10 +1485,18 @@
 
   @override
   void inferFunctionBody(InferenceHelper helper, DartType returnType,
-      AsyncMarker asyncMarker, Statement body) {
+      AsyncMarker asyncMarker, FunctionNode function, Statement body) {
     assert(closureContext == null);
     this.helper = helper;
     closureContext = new ClosureContext(this, asyncMarker, returnType, false);
+    if (function != null) {
+      for (VariableDeclaration parameter in function.positionalParameters) {
+        flowAnalysis.initialize(parameter);
+      }
+      for (VariableDeclaration parameter in function.namedParameters) {
+        flowAnalysis.initialize(parameter);
+      }
+    }
     inferStatement(body);
     closureContext = null;
     this.helper = null;
@@ -1538,7 +1554,9 @@
       bool isConst: false,
       bool isImplicitExtensionMember: false}) {
     FunctionType extensionFunctionType = new FunctionType(
-        [calleeType.positionalParameters.first], const DynamicType(),
+        [calleeType.positionalParameters.first],
+        const DynamicType(),
+        Nullability.legacy,
         requiredParameterCount: 1,
         typeParameters: calleeType.typeParameters
             .take(extensionTypeParameterCount)
@@ -1560,7 +1578,9 @@
           calleeType.typeParameters.skip(extensionTypeParameterCount).toList();
     }
     FunctionType targetFunctionType = new FunctionType(
-        calleeType.positionalParameters.skip(1).toList(), calleeType.returnType,
+        calleeType.positionalParameters.skip(1).toList(),
+        calleeType.returnType,
+        Nullability.legacy,
         requiredParameterCount: calleeType.requiredParameterCount - 1,
         namedParameters: calleeType.namedParameters,
         typeParameters: targetTypeParameters);
@@ -1841,6 +1861,7 @@
           function.positionalParameters;
       for (int i = 0; i < positionalParameters.length; i++) {
         VariableDeclaration parameter = positionalParameters[i];
+        flowAnalysis.initialize(parameter);
         inferMetadataKeepingHelper(parameter, parameter.annotations);
         if (parameter.initializer != null) {
           ExpressionInferenceResult initializerResult = inferExpression(
@@ -1850,6 +1871,7 @@
         }
       }
       for (VariableDeclaration parameter in function.namedParameters) {
+        flowAnalysis.initialize(parameter);
         inferMetadataKeepingHelper(parameter, parameter.annotations);
         ExpressionInferenceResult initializerResult =
             inferExpression(parameter.initializer, parameter.type, !isTopLevel);
@@ -1899,7 +1921,7 @@
       for (int i = 0; i < typeContext.typeParameters.length; i++) {
         substitutionMap[typeContext.typeParameters[i]] =
             i < typeParameters.length
-                ? new TypeParameterType(typeParameters[i])
+                ? new TypeParameterType(typeParameters[i], Nullability.legacy)
                 : const DynamicType();
       }
       substitution = Substitution.fromMap(substitutionMap);
@@ -1994,14 +2016,14 @@
     }
   }
 
-  StaticInvocation transformExtensionMethodInvocation(ObjectAccessTarget target,
-      Expression expression, Expression receiver, Arguments arguments) {
+  StaticInvocation transformExtensionMethodInvocation(int fileOffset,
+      ObjectAccessTarget target, Expression receiver, Arguments arguments) {
     assert(target.isExtensionMember);
     Procedure procedure = target.member;
     return engine.forest.createStaticInvocation(
-        expression.fileOffset,
+        fileOffset,
         target.member,
-        arguments = engine.forest.createArgumentsForExtensionMethod(
+        engine.forest.createArgumentsForExtensionMethod(
             arguments.fileOffset,
             target.inferredExtensionTypeArguments.length,
             procedure.function.typeParameters.length -
@@ -2084,7 +2106,7 @@
     Arguments arguments = node.arguments;
     if (target.isExtensionMember) {
       StaticInvocation staticInvocation = transformExtensionMethodInvocation(
-          target, node, receiver, node.arguments);
+          node.fileOffset, target, receiver, node.arguments);
       arguments = staticInvocation.arguments;
       replacement = staticInvocation;
     } else {
@@ -2396,18 +2418,19 @@
     }
     // TODO(paulberry): If [type] is a subtype of `Future`, should we just
     // return it unmodified?
-    return new InterfaceType(
-        coreTypes.futureOrClass, <DartType>[type ?? const DynamicType()]);
+    return new InterfaceType(coreTypes.futureOrClass, Nullability.legacy,
+        <DartType>[type ?? const DynamicType()]);
   }
 
   DartType wrapFutureType(DartType type) {
     DartType typeWithoutFutureOr = type ?? const DynamicType();
-    return new InterfaceType(
-        coreTypes.futureClass, <DartType>[typeWithoutFutureOr]);
+    return new InterfaceType(coreTypes.futureClass, Nullability.legacy,
+        <DartType>[typeWithoutFutureOr]);
   }
 
   DartType wrapType(DartType type, Class class_) {
-    return new InterfaceType(class_, <DartType>[type ?? const DynamicType()]);
+    return new InterfaceType(
+        class_, Nullability.legacy, <DartType>[type ?? const DynamicType()]);
   }
 
   Member _getInterfaceMember(
@@ -2577,6 +2600,7 @@
 
   Expression createMissingBinary(int fileOffset, Expression left,
       DartType leftType, Name binaryName, Expression right) {
+    assert(binaryName != equalsName);
     if (isTopLevel) {
       return engine.forest.createMethodInvocation(fileOffset, left, binaryName,
           engine.forest.createArguments(fileOffset, <Expression>[right]));
@@ -2588,6 +2612,20 @@
           binaryName.name.length);
     }
   }
+
+  Expression createMissingUnary(int fileOffset, Expression expression,
+      DartType expressionType, Name unaryName) {
+    if (isTopLevel) {
+      return new UnaryExpression(unaryName, expression)
+        ..fileOffset = fileOffset;
+    } else {
+      return helper.buildProblem(
+          templateUndefinedMethod.withArguments(
+              unaryName.name, resolveTypeParameter(expressionType)),
+          fileOffset,
+          unaryName.name == unaryMinusName.name ? 1 : unaryName.name.length);
+    }
+  }
 }
 
 abstract class MixinInferrer {
@@ -2721,7 +2759,9 @@
     // substitute them before calling instantiate to bounds.
     Substitution substitution = Substitution.fromPairs(
         mixinClass.typeParameters,
-        parameters.map((p) => new TypeParameterType(p)).toList());
+        parameters
+            .map((p) => new TypeParameterType(p, Nullability.legacy))
+            .toList());
     for (TypeParameter p in parameters) {
       p.bound = substitution.substituteType(p.bound);
     }
@@ -2975,7 +3015,8 @@
 
   ExtensionAccessCandidate(
       this.onType, this.onTypeInstantiateToBounds, this.target,
-      {this.isPlatform});
+      {this.isPlatform})
+      : assert(isPlatform != null);
 
   bool isMoreSpecificThan(TypeSchemaEnvironment typeSchemaEnvironment,
       ExtensionAccessCandidate other) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index bb90d9d..ef4c2a6 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
@@ -695,7 +695,7 @@
       // The type we are checking against is a subtype of the bound of the
       // previous type of the variable; we can promote the bound.
       return new TypeParameterType(
-          previousType.parameter, checkedType, previousType.nullability);
+          previousType.parameter, previousType.nullability, checkedType);
     } else {
       // The types aren't sufficiently related; we can't promote.
       return previousPromotedType;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
index d89869f..dc1b1be 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
@@ -88,11 +88,11 @@
       return new FunctionType(
           newPositionalParameters ?? node.positionalParameters,
           newReturnType ?? node.returnType,
+          node.nullability,
           namedParameters: newNamedParameters ?? node.namedParameters,
           typeParameters: node.typeParameters,
           requiredParameterCount: node.requiredParameterCount,
-          typedefType: typedefType,
-          nullability: node.nullability);
+          typedefType: typedefType);
     }
   }
 
@@ -111,7 +111,7 @@
       return null;
     } else {
       return new InterfaceType(
-          node.classNode, newTypeArguments, node.nullability);
+          node.classNode, node.nullability, newTypeArguments);
     }
   }
 
@@ -135,8 +135,8 @@
     if (node.promotedBound != null) {
       DartType newPromotedBound = node.promotedBound.accept(this);
       if (newPromotedBound != null) {
-        return new TypeParameterType(node.parameter, newPromotedBound,
-            node.typeParameterTypeNullability);
+        return new TypeParameterType(node.parameter,
+            node.typeParameterTypeNullability, newPromotedBound);
       }
     }
     return null;
@@ -157,7 +157,7 @@
       return null;
     } else {
       return new TypedefType(
-          node.typedefNode, newTypeArguments, node.nullability);
+          node.typedefNode, node.nullability, newTypeArguments);
     }
   }
 
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 eeecd4f..16cd881 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
@@ -10,6 +10,7 @@
         FunctionType,
         InterfaceType,
         NamedType,
+        Nullability,
         Procedure,
         TypeParameter;
 
@@ -41,6 +42,7 @@
   return new FunctionType(
       type.positionalParameters.map(substitution.substituteType).toList(),
       substitution.substituteType(type.returnType),
+      Nullability.legacy,
       namedParameters: type.namedParameters
           .map((named) => new NamedType(
               named.name, substitution.substituteType(named.type),
@@ -246,7 +248,7 @@
       }
 
       TypeConstraint constraint = constraints[typeParam];
-      if (downwardsInferPhase) {
+      if (downwardsInferPhase || !typeParam.isLegacyCovariant) {
         inferredTypes[i] =
             _inferTypeParameterFromContext(constraint, extendsConstraint);
       } else {
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 956b470..d69c809 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -75,6 +75,7 @@
 
     Set<Uri> externalLibs(Component component) {
       return component.libraries
+          // ignore: DEPRECATED_MEMBER_USE
           .where((lib) => lib.isExternal)
           .map((lib) => lib.importUri)
           .toSet();
@@ -102,6 +103,7 @@
     // All summaries are considered external and shouldn't include source-info.
     dillTarget.loader.libraries.forEach((lib) {
       // TODO(ahe): Don't do this, and remove [external_state_snapshot.dart].
+      // ignore: DEPRECATED_MEMBER_USE
       lib.isExternal = true;
     });
 
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index c95f2ec..01bc058 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -35,11 +35,17 @@
 /// Test configuration used for testing CFE in its default state.
 const TestConfig defaultCfeConfig = const TestConfig(cfeMarker, 'cfe');
 
-/// Test configuration used for testing CFE with nnbd.
+/// Test configuration used for testing CFE with nnbd in addition to the
+/// default state.
 const TestConfig cfeNonNullableConfig = const TestConfig(
     cfeWithNnbdMarker, 'cfe with nnbd',
     experimentalFlags: const {ExperimentalFlag.nonNullable: true});
 
+/// Test configuration used for testing CFE with nnbd as the default state.
+const TestConfig cfeNonNullableOnlyConfig = const TestConfig(
+    cfeMarker, 'cfe with nnbd',
+    experimentalFlags: const {ExperimentalFlag.nonNullable: true});
+
 class TestConfig {
   final String marker;
   final String name;
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 7b85105..ae993e2 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -233,17 +233,59 @@
 
 /// Returns a textual representation of the constant [node] to be used in
 /// testing.
-String constantToText(Constant node, {bool isNonNullableByDefault: false}) {
+String constantToText(Constant node,
+    {TypeRepresentation typeRepresentation: TypeRepresentation.legacy}) {
   StringBuffer sb = new StringBuffer();
-  new ConstantToTextVisitor(sb, isNonNullableByDefault).visit(node);
+  new ConstantToTextVisitor(sb, typeRepresentation).visit(node);
   return sb.toString();
 }
 
+enum TypeRepresentation {
+  legacy,
+  explicit,
+  implicitUndetermined,
+  nonNullableByDefault,
+}
+
 /// Returns a textual representation of the type [node] to be used in
 /// testing.
-String typeToText(DartType node, {bool isNonNullableByDefault: false}) {
+String typeToText(DartType node,
+    [TypeRepresentation typeRepresentation = TypeRepresentation.legacy]) {
   StringBuffer sb = new StringBuffer();
-  new DartTypeToTextVisitor(sb, isNonNullableByDefault).visit(node);
+  new DartTypeToTextVisitor(sb, typeRepresentation).visit(node);
+  return sb.toString();
+}
+
+Set<Class> computeAllSuperclasses(Class node) {
+  Set<Class> set = <Class>{};
+  _getAllSuperclasses(node, set);
+  return set;
+}
+
+void _getAllSuperclasses(Class node, Set<Class> set) {
+  if (set.add(node)) {
+    if (node.supertype != null) {
+      _getAllSuperclasses(node.supertype.classNode, set);
+    }
+    if (node.mixedInType != null) {
+      _getAllSuperclasses(node.mixedInType.classNode, set);
+    }
+    for (Supertype interface in node.implementedTypes) {
+      _getAllSuperclasses(interface.classNode, set);
+    }
+  }
+}
+
+String supertypeToText(Supertype node,
+    [TypeRepresentation typeRepresentation = TypeRepresentation.legacy]) {
+  StringBuffer sb = new StringBuffer();
+  sb.write(node.classNode.name);
+  if (node.typeArguments.isNotEmpty) {
+    sb.write('<');
+    new DartTypeToTextVisitor(sb, typeRepresentation)
+        .visitList(node.typeArguments);
+    sb.write('>');
+  }
   return sb.toString();
 }
 
@@ -251,8 +293,8 @@
   final StringBuffer sb;
   final DartTypeToTextVisitor typeToText;
 
-  ConstantToTextVisitor(this.sb, bool isNonNullableByDefault)
-      : typeToText = new DartTypeToTextVisitor(sb, isNonNullableByDefault);
+  ConstantToTextVisitor(this.sb, TypeRepresentation typeRepresentation)
+      : typeToText = new DartTypeToTextVisitor(sb, typeRepresentation);
 
   void visit(Constant node) => node.accept(this);
 
@@ -375,9 +417,9 @@
 
 class DartTypeToTextVisitor implements DartTypeVisitor<void> {
   final StringBuffer sb;
-  final bool isNonNullableByDefault;
+  final TypeRepresentation typeRepresentation;
 
-  DartTypeToTextVisitor(this.sb, this.isNonNullableByDefault);
+  DartTypeToTextVisitor(this.sb, this.typeRepresentation);
 
   void visit(DartType node) => node.accept(this);
 
@@ -421,8 +463,7 @@
       sb.write('>');
     }
     if (!isNull(node)) {
-      sb.write(nullabilityToText(node.nullability,
-          isNonNullableByDefault: isNonNullableByDefault));
+      sb.write(nullabilityToText(node.nullability, typeRepresentation));
     }
   }
 
@@ -454,18 +495,16 @@
       sb.write('}');
     }
     sb.write(')');
-    sb.write(nullabilityToText(node.nullability,
-        isNonNullableByDefault: isNonNullableByDefault));
+    sb.write(nullabilityToText(node.nullability, typeRepresentation));
     sb.write('->');
     visit(node.returnType);
   }
 
   void visitTypeParameterType(TypeParameterType node) {
     sb.write(node.parameter.name);
-    sb.write(nullabilityToText(node.nullability,
-        isNonNullableByDefault: isNonNullableByDefault));
+    sb.write(nullabilityToText(node.nullability, typeRepresentation));
     if (node.promotedBound != null) {
-      sb.write(' extends ');
+      sb.write(' & ');
       visit(node.promotedBound);
     }
   }
@@ -477,8 +516,7 @@
       visitList(node.typeArguments);
       sb.write('>');
     }
-    sb.write(nullabilityToText(node.nullability,
-        isNonNullableByDefault: isNonNullableByDefault));
+    sb.write(nullabilityToText(node.nullability, typeRepresentation));
   }
 }
 
@@ -546,8 +584,12 @@
 }
 
 /// Returns a textual representation of [errors] to be used in testing.
-String errorsToText(List<FormattedMessage> errors) {
-  return errors.map((m) => m.message).join(',');
+String errorsToText(List<FormattedMessage> errors, {bool useCodes: false}) {
+  if (useCodes) {
+    return errors.map((m) => m.code).join(',');
+  } else {
+    return errors.map((m) => m.message).join(',');
+  }
 }
 
 /// Returns a textual representation of [descriptor] to be used in testing.
@@ -588,18 +630,39 @@
 }
 
 /// Returns a textual representation of [nullability] to be used in testing.
-String nullabilityToText(Nullability nullability,
-    {bool isNonNullableByDefault}) {
-  assert(isNonNullableByDefault != null);
+String nullabilityToText(
+    Nullability nullability, TypeRepresentation typeRepresentation) {
   switch (nullability) {
     case Nullability.nonNullable:
-      return isNonNullableByDefault ? '' : '!';
+      switch (typeRepresentation) {
+        case TypeRepresentation.explicit:
+        case TypeRepresentation.legacy:
+        case TypeRepresentation.implicitUndetermined:
+          return '!';
+        case TypeRepresentation.nonNullableByDefault:
+          return '';
+      }
+      break;
     case Nullability.nullable:
       return '?';
     case Nullability.undetermined:
-      return '%';
+      switch (typeRepresentation) {
+        case TypeRepresentation.implicitUndetermined:
+          return '';
+        default:
+          return '%';
+      }
+      break;
     case Nullability.legacy:
-      return isNonNullableByDefault ? '*' : '';
+      switch (typeRepresentation) {
+        case TypeRepresentation.legacy:
+          return '';
+        case TypeRepresentation.explicit:
+        case TypeRepresentation.nonNullableByDefault:
+        case TypeRepresentation.implicitUndetermined:
+          return '*';
+      }
+      break;
   }
   throw new UnsupportedError('Unexpected nullability: $nullability.');
 }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 59c95bc..9901425 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -130,6 +130,8 @@
 CyclicClassHierarchy/script2: Fail # We report an error for each class involved in the cycle.
 CyclicTypedef/example: Fail
 DeferredAfterPrefix/example: Fail
+DeferredExtensionImport/analyzerCode: Fail
+DeferredExtensionImport/part_wrapped_script: Fail
 DeferredPrefixDuplicated/example: Fail
 DeferredTypeAnnotation/example: Fail
 DillOutlineSummary/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index fcdaead..670a401 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -3708,6 +3708,13 @@
 ExplicitExtensionAsLvalue:
   template: "Explicit extension application cannot be a target for assignment."
 
+DeferredExtensionImport:
+  template: "Extension '#name' cannot be imported through a deferred import."
+  tip: "Try adding the `hide #name` to the import."
+  script:
+    main.dart: "import 'lib.dart' deferred as prefix;"
+    lib.dart: "extension Extension on void {}"
+
 MultipleVarianceModifiers:
   index: 97
   template: "Each type parameter can have at most one variance modifier."
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart
new file mode 100644
index 0000000..70bdad5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart
@@ -0,0 +1 @@
+() async => a b < c $? >
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
new file mode 100644
index 0000000..a38a1ad
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
@@ -0,0 +1,80 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39202.crash:1:1: Expected a declaration, but got '('.
+() async => a b < c $? >
+^
+
+parser_test/error_recovery/issue_39202.crash:1:2: Expected a declaration, but got ')'.
+() async => a b < c $? >
+ ^
+
+parser_test/error_recovery/issue_39202.crash:1:4: A function declaration needs an explicit list of parameters.
+() async => a b < c $? >
+   ^^^^^
+
+parser_test/error_recovery/issue_39202.crash:1:13: Expected ';' after this.
+() async => a b < c $? >
+            ^
+
+parser_test/error_recovery/issue_39202.crash:1:19: Expected '>' after this.
+() async => a b < c $? >
+                  ^
+
+parser_test/error_recovery/issue_39202.crash:1:25: Expected an identifier, but got ''.
+() async => a b < c $? >
+                        ^...
+
+parser_test/error_recovery/issue_39202.crash:1:25: Expected ';' after this.
+() async => a b < c $? >
+                        ^...
+
+beginCompilationUnit(()
+  beginMetadataStar(()
+  endMetadataStar(0)
+  beginTopLevelMember(()
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {token: (}], (, ()
+    handleInvalidTopLevelDeclaration(()
+  endTopLevelDeclaration())
+  beginMetadataStar())
+  endMetadataStar(0)
+  beginTopLevelMember())
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {token: )}], ), ))
+    handleInvalidTopLevelDeclaration())
+  endTopLevelDeclaration(async)
+  beginMetadataStar(async)
+  endMetadataStar(0)
+  beginTopLevelMember(async)
+    beginTopLevelMethod(), null)
+      handleNoType())
+      handleIdentifier(async, topLevelFunctionDeclaration)
+      handleNoTypeVariables(=>)
+      handleRecoverableError(MissingFunctionParameters, async, async)
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      handleIdentifier(a, expression)
+      handleNoTypeArguments(b)
+      handleNoArguments(b)
+      handleSend(a, b)
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+      handleExpressionFunctionBody(=>, ;)
+    endTopLevelMethod(async, null, ;)
+  endTopLevelDeclaration(b)
+  beginMetadataStar(b)
+  endMetadataStar(0)
+  beginTopLevelMember(b)
+    handleIdentifier(b, typeReference)
+    beginTypeArguments(<)
+      handleIdentifier(c, typeReference)
+      handleNoTypeArguments($)
+      handleType(c, null)
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], c, c)
+    endTypeArguments(1, <, >)
+    handleType(b, null)
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+    handleIdentifier(, topLevelVariableDeclaration)
+    handleNoFieldInitializer()
+    handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+  endTopLevelFields(null, null, null, null, 1, b, ;)
+endTopLevelDeclaration()
+endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
new file mode 100644
index 0000000..7698ac7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
@@ -0,0 +1,103 @@
+parseUnit(()
+  skipErrorTokens(()
+  listener: beginCompilationUnit(()
+  syntheticPreviousToken(()
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(()
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember(()
+    parseInvalidTopLevelDeclaration()
+      reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {token: (}], (, ()
+      listener: handleInvalidTopLevelDeclaration(()
+  listener: endTopLevelDeclaration())
+  parseTopLevelDeclarationImpl((, Instance of 'DirectiveContext')
+    parseMetadataStar(()
+      listener: beginMetadataStar())
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember())
+    parseInvalidTopLevelDeclaration(()
+      reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {token: )}], ), ))
+      listener: handleInvalidTopLevelDeclaration())
+  listener: endTopLevelDeclaration(async)
+  parseTopLevelDeclarationImpl(), Instance of 'DirectiveContext')
+    parseMetadataStar())
+      listener: beginMetadataStar(async)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl())
+      listener: beginTopLevelMember(async)
+      parseTopLevelMethod(), null, ), Instance of 'NoType', null, async)
+        listener: beginTopLevelMethod(), null)
+        listener: handleNoType())
+        ensureIdentifier(), topLevelFunctionDeclaration)
+          listener: handleIdentifier(async, topLevelFunctionDeclaration)
+        parseMethodTypeVar(async)
+          listener: handleNoTypeVariables(=>)
+        parseGetterOrFormalParameters(async, async, false, MemberKind.TopLevelMethod)
+          missingParameterMessage(MemberKind.TopLevelMethod)
+          reportRecoverableError(async, MissingFunctionParameters)
+            listener: handleRecoverableError(MissingFunctionParameters, async, async)
+          rewriter()
+          parseFormalParametersRest((, MemberKind.TopLevelMethod)
+            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          parseExpressionFunctionBody(=>, false)
+            parseExpression(=>)
+              parsePrecedenceExpression(=>, 1, true)
+                parseUnaryExpression(=>, true)
+                  parsePrimary(=>, expression)
+                    parseSendOrFunctionLiteral(=>, expression)
+                      parseSend(=>, expression)
+                        ensureIdentifier(=>, expression)
+                          listener: handleIdentifier(a, expression)
+                        listener: handleNoTypeArguments(b)
+                        parseArgumentsOpt(a)
+                          listener: handleNoArguments(b)
+                        listener: handleSend(a, b)
+            ensureSemicolon(a)
+              reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+              rewriter()
+            listener: handleExpressionFunctionBody(=>, ;)
+            inGenerator()
+        listener: endTopLevelMethod(async, null, ;)
+  listener: endTopLevelDeclaration(b)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(b)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(b)
+      parseFields(;, null, null, null, null, null, ;, Instance of 'ComplexTypeInfo', $, DeclarationKind.TopLevel)
+        ensureIdentifier(;, typeReference)
+          listener: handleIdentifier(b, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(c, typeReference)
+        listener: handleNoTypeArguments($)
+        listener: handleType(c, null)
+        reportRecoverableError(c, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
+          listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], c, c)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(b, null)
+        ensureIdentifier(>, topLevelVariableDeclaration)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+            rewriter()
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, DeclarationKind.TopLevel)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, 1, b, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(()
+  listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.parser.expect
new file mode 100644
index 0000000..7ea04bc
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+() async ()=> a ;b < c $? >;
+
+([BeginToken])[SimpleToken] async[KeywordToken] ([SyntheticBeginToken])[SyntheticToken]=>[SimpleToken] a[StringToken] ;[SyntheticToken]b[StringToken] <[BeginToken] c[StringToken] $[StringToken]?[SimpleToken] >[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.scanner.expect
new file mode 100644
index 0000000..f6ab542
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+() async => a b < c $? >
+
+([BeginToken])[SimpleToken] async[KeywordToken] =>[SimpleToken] a[StringToken] b[StringToken] <[BeginToken] c[StringToken] $[StringToken]?[SimpleToken] >[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart
new file mode 100644
index 0000000..b3588d2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart
@@ -0,0 +1,5 @@
+class C {
+  C()
+    /
+    : super();
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
new file mode 100644
index 0000000..4d40dc0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
@@ -0,0 +1,70 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39230.crash:3:5: Expected a function body, but got '/'.
+    /
+    ^
+
+parser_test/error_recovery/issue_39230.crash:3:5: Operator declarations must be preceded by the keyword 'operator'.
+    /
+    ^
+
+parser_test/error_recovery/issue_39230.crash:3:5: A method declaration needs an explicit list of parameters.
+    /
+    ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(C, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, C)
+      handleNoType(C)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, C)
+            handleNoType({)
+            handleIdentifier(C, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+            handleInvalidFunctionBody({)
+          endClassConstructor(null, C, (, null, })
+        endMember()
+        beginMetadataStar(/)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(MissingOperatorKeyword, /, /)
+          beginMethod(null, null, null, null, null, operator)
+            handleNoType(})
+            handleOperatorName(operator, /)
+            handleNoTypeVariables(:)
+            handleRecoverableError(MissingMethodParameters, /, /)
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(super)
+                handleSuperExpression(super, expression)
+                handleNoTypeArguments(()
+                beginArguments(()
+                endArguments(0, (, ))
+                handleSend(super, ;)
+              endInitializer(;)
+            endInitializers(1, :, ;)
+            handleAsyncModifier(null, null)
+            handleEmptyFunctionBody(;)
+          endClassMethod(null, operator, (, :, ;)
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 2, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect
new file mode 100644
index 0000000..1712509
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect
@@ -0,0 +1,124 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(class)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(C, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, C)
+        parseClass(C, class, class, C)
+          parseClassHeaderOpt(C, class, class)
+            parseClassExtendsOpt(C)
+              listener: handleNoType(C)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(C)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(C)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(C, DeclarationKind.Class, C)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, C)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, C)
+              parseMetadataStar({)
+                listener: beginMetadataStar(C)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, {, Instance of 'NoType', null, C, DeclarationKind.Class, C)
+                listener: beginMethod(null, null, null, null, null, C)
+                listener: handleNoType({)
+                ensureIdentifier({, methodDeclaration)
+                  listener: handleIdentifier(C, methodDeclaration)
+                parseQualifiedRestOpt(C, methodDeclarationContinuation)
+                parseMethodTypeVar(C)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(C, C, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(C, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+                    insertBlock())
+                      rewriter()
+                      rewriter()
+                  listener: handleInvalidFunctionBody({)
+                listener: endClassConstructor(null, C, (, null, })
+              listener: endMember()
+            notEofOrValue(}, /)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, C)
+              parseMetadataStar(})
+                listener: beginMetadataStar(/)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(}, }, null, null, null, null, null, }, Instance of 'NoType', null, DeclarationKind.Class, C)
+                parseInvalidOperatorDeclaration(}, null, null, null, null, null, }, DeclarationKind.Class, C)
+                  reportRecoverableError(/, MissingOperatorKeyword)
+                    listener: handleRecoverableError(MissingOperatorKeyword, /, /)
+                  rewriter()
+                  parseMethod(}, null, null, null, null, null, }, Instance of 'NoType', null, operator, DeclarationKind.Class, C)
+                    listener: beginMethod(null, null, null, null, null, operator)
+                    listener: handleNoType(})
+                    parseOperatorName(})
+                      listener: handleOperatorName(operator, /)
+                    parseMethodTypeVar(/)
+                      listener: handleNoTypeVariables(:)
+                    parseGetterOrFormalParameters(/, operator, false, MemberKind.NonStaticMethod)
+                      missingParameterMessage(MemberKind.NonStaticMethod)
+                      reportRecoverableError(/, MissingMethodParameters)
+                        listener: handleRecoverableError(MissingMethodParameters, /, /)
+                      rewriter()
+                      parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                        listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                        listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                    parseInitializersOpt())
+                      parseInitializers(:)
+                        listener: beginInitializers(:)
+                        parseInitializer(:)
+                          listener: beginInitializer(super)
+                          parseSuperInitializerExpression(:)
+                            parseInitializerExpressionRest(:)
+                              parseExpression(:)
+                                parsePrecedenceExpression(:, 1, true)
+                                  parseUnaryExpression(:, true)
+                                    parsePrimary(:, expression)
+                                      parseSuperExpression(:, expression)
+                                        listener: handleSuperExpression(super, expression)
+                                        listener: handleNoTypeArguments(()
+                                        parseArguments(super)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            listener: endArguments(0, (, ))
+                                        listener: handleSend(super, ;)
+                              listener: endInitializer(;)
+                        listener: endInitializers(1, :, ;)
+                    parseAsyncModifierOpt())
+                      listener: handleAsyncModifier(null, null)
+                      inPlainSync()
+                    inPlainSync()
+                    parseFunctionBody(), false, true)
+                      listener: handleEmptyFunctionBody(;)
+                    listener: endClassMethod(null, operator, (, :, ;)
+                  listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 2, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.parser.expect
new file mode 100644
index 0000000..1be4be4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.parser.expect
@@ -0,0 +1,15 @@
+NOTICE: Stream was rewritten by parser!
+
+class C {
+C()
+{}operator/
+(): super();
+}
+
+
+class[KeywordToken] C[StringToken] {[BeginToken]
+C[StringToken]([BeginToken])[SimpleToken]
+{[SyntheticBeginToken]}[SyntheticToken]operator[SyntheticKeywordToken]/[SimpleToken]
+([SyntheticBeginToken])[SyntheticToken]:[SimpleToken] super[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.scanner.expect
new file mode 100644
index 0000000..448d455
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.scanner.expect
@@ -0,0 +1,13 @@
+class C {
+C()
+/
+: super();
+}
+
+
+class[KeywordToken] C[StringToken] {[BeginToken]
+C[StringToken]([BeginToken])[SimpleToken]
+/[SimpleToken]
+:[SimpleToken] super[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286.dart b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart
new file mode 100644
index 0000000..6654bf6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart
@@ -0,0 +1,3 @@
+void test(C x) {
+  x..f()!.g()..h();
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.expect
new file mode 100644
index 0000000..afb33dd
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.expect
@@ -0,0 +1,53 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null)
+      handleVoidKeyword(void)
+      handleIdentifier(test, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(C, typeReference)
+          handleNoTypeArguments(x)
+          handleType(C, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(..)
+        handleNoArguments(..)
+        handleSend(x, ..)
+        beginCascade(..)
+          handleIdentifier(f, expressionContinuation)
+          handleNoTypeArguments(()
+          beginArguments(()
+          endArguments(0, (, ))
+          handleSend(f, !)
+        endBinaryExpression(..)
+        handleNonNullAssertExpression(!)
+        handleIdentifier(g, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(g, ..)
+      endBinaryExpression(.)
+    endCascade()
+    beginCascade(..)
+      handleIdentifier(h, expressionContinuation)
+      handleNoTypeArguments(()
+      beginArguments(()
+      endArguments(0, (, ))
+      handleSend(h, ;)
+    endBinaryExpression(..)
+  endCascade()
+  handleExpressionStatement(;)
+endBlockFunctionBody(1, {, })
+endTopLevelMethod(void, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.intertwined.expect
new file mode 100644
index 0000000..f60f894
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.intertwined.expect
@@ -0,0 +1,109 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, , Instance of 'VoidType', null, test)
+        listener: beginTopLevelMethod(, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifier(void, topLevelFunctionDeclaration)
+          listener: handleIdentifier(test, topLevelFunctionDeclaration)
+        parseMethodTypeVar(test)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(test, test, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(test, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(C)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(C, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(C, null)
+                ensureIdentifier(C, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, x)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(x)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(x, expression)
+                              listener: handleNoTypeArguments(..)
+                              parseArgumentsOpt(x)
+                                listener: handleNoArguments(..)
+                              listener: handleSend(x, ..)
+                      parseCascadeExpression(x)
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(f, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(f)
+                            parseArguments(f)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(f, !)
+                        listener: endBinaryExpression(..)
+                        listener: handleNonNullAssertExpression(!)
+                        parseArgumentOrIndexStar(!, Instance of 'NoTypeParamOrArg')
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(g, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(g)
+                            parseArguments(g)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(g, ..)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                      parseCascadeExpression())
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(h, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(h)
+                            parseArguments(h)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(h, ;)
+                        listener: endBinaryExpression(..)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.parser.expect
new file mode 100644
index 0000000..1fc6db3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.parser.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f()!.g()..h();
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.scanner.expect
new file mode 100644
index 0000000..1fc6db3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286.dart.scanner.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f()!.g()..h();
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart
new file mode 100644
index 0000000..91b5943
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart
@@ -0,0 +1,3 @@
+void test(C x) {
+  x..f()!.g()['Hi!']!..h()!.y = 2;
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.expect
new file mode 100644
index 0000000..a71a466
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.expect
@@ -0,0 +1,65 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null)
+      handleVoidKeyword(void)
+      handleIdentifier(test, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(C, typeReference)
+          handleNoTypeArguments(x)
+          handleType(C, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(..)
+        handleNoArguments(..)
+        handleSend(x, ..)
+        beginCascade(..)
+          handleIdentifier(f, expressionContinuation)
+          handleNoTypeArguments(()
+          beginArguments(()
+          endArguments(0, (, ))
+          handleSend(f, !)
+        endBinaryExpression(..)
+        handleNonNullAssertExpression(!)
+        handleIdentifier(g, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(g, [)
+      endBinaryExpression(.)
+      beginLiteralString('Hi!')
+      endLiteralString(0, ])
+      handleIndexedExpression([, ])
+      handleNonNullAssertExpression(!)
+    endCascade()
+    beginCascade(..)
+      handleIdentifier(h, expressionContinuation)
+      handleNoTypeArguments(()
+      beginArguments(()
+      endArguments(0, (, ))
+      handleSend(h, !)
+    endBinaryExpression(..)
+    handleNonNullAssertExpression(!)
+    handleIdentifier(y, expressionContinuation)
+    handleNoTypeArguments(=)
+    handleNoArguments(=)
+    handleSend(y, =)
+  endBinaryExpression(.)
+  handleLiteralInt(2)
+  handleAssignmentExpression(=)
+endCascade()
+handleExpressionStatement(;)
+endBlockFunctionBody(1, {, })
+endTopLevelMethod(void, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.intertwined.expect
new file mode 100644
index 0000000..8f51899
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.intertwined.expect
@@ -0,0 +1,138 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, , Instance of 'VoidType', null, test)
+        listener: beginTopLevelMethod(, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifier(void, topLevelFunctionDeclaration)
+          listener: handleIdentifier(test, topLevelFunctionDeclaration)
+        parseMethodTypeVar(test)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(test, test, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(test, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(C)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(C, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(C, null)
+                ensureIdentifier(C, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, x)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(x)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(x, expression)
+                              listener: handleNoTypeArguments(..)
+                              parseArgumentsOpt(x)
+                                listener: handleNoArguments(..)
+                              listener: handleSend(x, ..)
+                      parseCascadeExpression(x)
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(f, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(f)
+                            parseArguments(f)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(f, !)
+                        listener: endBinaryExpression(..)
+                        listener: handleNonNullAssertExpression(!)
+                        parseArgumentOrIndexStar(!, Instance of 'NoTypeParamOrArg')
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(g, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(g)
+                            parseArguments(g)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(g, [)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                          parseExpression([)
+                            parsePrecedenceExpression([, 1, true)
+                              parseUnaryExpression([, true)
+                                parsePrimary([, expression)
+                                  parseLiteralString([)
+                                    parseSingleLiteralString([)
+                                      listener: beginLiteralString('Hi!')
+                                      listener: endLiteralString(0, ])
+                          listener: handleIndexedExpression([, ])
+                        listener: handleNonNullAssertExpression(!)
+                        parseArgumentOrIndexStar(!, Instance of 'NoTypeParamOrArg')
+                        parseArgumentOrIndexStar(!, Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                      parseCascadeExpression(!)
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(h, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(h)
+                            parseArguments(h)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(h, !)
+                        listener: endBinaryExpression(..)
+                        listener: handleNonNullAssertExpression(!)
+                        parseArgumentOrIndexStar(!, Instance of 'NoTypeParamOrArg')
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(y, expressionContinuation)
+                          listener: handleNoTypeArguments(=)
+                          parseArgumentsOpt(y)
+                            listener: handleNoArguments(=)
+                          listener: handleSend(y, =)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(y, Instance of 'NoTypeParamOrArg')
+                        parseArgumentOrIndexStar(y, Instance of 'NoTypeParamOrArg')
+                        parseExpressionWithoutCascade(=)
+                          parsePrecedenceExpression(=, 1, false)
+                            parseUnaryExpression(=, false)
+                              parsePrimary(=, expression)
+                                parseLiteralInt(=)
+                                  listener: handleLiteralInt(2)
+                        listener: handleAssignmentExpression(=)
+                        listener: endCascade()
+                  ensureSemicolon(2)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.parser.expect
new file mode 100644
index 0000000..e51c80d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.parser.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f()!.g()['Hi!']!..h()!.y = 2;
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken][[BeginToken]'Hi!'[StringToken]][SimpleToken]![SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]y[StringToken] =[SimpleToken] 2[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.scanner.expect
new file mode 100644
index 0000000..e51c80d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2.dart.scanner.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f()!.g()['Hi!']!..h()!.y = 2;
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken][[BeginToken]'Hi!'[StringToken]][SimpleToken]![SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken]![SimpleToken].[SimpleToken]y[StringToken] =[SimpleToken] 2[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart
new file mode 100644
index 0000000..a5914bb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart
@@ -0,0 +1,3 @@
+void test(C x) {
+  x..f().g()['Hi!']..h().y = 2;
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.expect
new file mode 100644
index 0000000..9af77f2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.expect
@@ -0,0 +1,62 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null)
+      handleVoidKeyword(void)
+      handleIdentifier(test, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(C, typeReference)
+          handleNoTypeArguments(x)
+          handleType(C, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(..)
+        handleNoArguments(..)
+        handleSend(x, ..)
+        beginCascade(..)
+          handleIdentifier(f, expressionContinuation)
+          handleNoTypeArguments(()
+          beginArguments(()
+          endArguments(0, (, ))
+          handleSend(f, .)
+        endBinaryExpression(..)
+        handleIdentifier(g, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(g, [)
+      endBinaryExpression(.)
+      beginLiteralString('Hi!')
+      endLiteralString(0, ])
+      handleIndexedExpression([, ])
+    endCascade()
+    beginCascade(..)
+      handleIdentifier(h, expressionContinuation)
+      handleNoTypeArguments(()
+      beginArguments(()
+      endArguments(0, (, ))
+      handleSend(h, .)
+    endBinaryExpression(..)
+    handleIdentifier(y, expressionContinuation)
+    handleNoTypeArguments(=)
+    handleNoArguments(=)
+    handleSend(y, =)
+  endBinaryExpression(.)
+  handleLiteralInt(2)
+  handleAssignmentExpression(=)
+endCascade()
+handleExpressionStatement(;)
+endBlockFunctionBody(1, {, })
+endTopLevelMethod(void, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.intertwined.expect
new file mode 100644
index 0000000..7e37571
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.intertwined.expect
@@ -0,0 +1,132 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, , Instance of 'VoidType', null, test)
+        listener: beginTopLevelMethod(, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifier(void, topLevelFunctionDeclaration)
+          listener: handleIdentifier(test, topLevelFunctionDeclaration)
+        parseMethodTypeVar(test)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(test, test, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(test, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(C)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(C, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(C, null)
+                ensureIdentifier(C, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, x)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(x)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(x, expression)
+                              listener: handleNoTypeArguments(..)
+                              parseArgumentsOpt(x)
+                                listener: handleNoArguments(..)
+                              listener: handleSend(x, ..)
+                      parseCascadeExpression(x)
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(f, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(f)
+                            parseArguments(f)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(f, .)
+                        listener: endBinaryExpression(..)
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(g, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(g)
+                            parseArguments(g)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(g, [)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                          parseExpression([)
+                            parsePrecedenceExpression([, 1, true)
+                              parseUnaryExpression([, true)
+                                parsePrimary([, expression)
+                                  parseLiteralString([)
+                                    parseSingleLiteralString([)
+                                      listener: beginLiteralString('Hi!')
+                                      listener: endLiteralString(0, ])
+                          listener: handleIndexedExpression([, ])
+                        parseArgumentOrIndexStar(], Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                      parseCascadeExpression(])
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(h, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(h)
+                            parseArguments(h)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(h, .)
+                        listener: endBinaryExpression(..)
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(y, expressionContinuation)
+                          listener: handleNoTypeArguments(=)
+                          parseArgumentsOpt(y)
+                            listener: handleNoArguments(=)
+                          listener: handleSend(y, =)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(y, Instance of 'NoTypeParamOrArg')
+                        parseArgumentOrIndexStar(y, Instance of 'NoTypeParamOrArg')
+                        parseExpressionWithoutCascade(=)
+                          parsePrecedenceExpression(=, 1, false)
+                            parseUnaryExpression(=, false)
+                              parsePrimary(=, expression)
+                                parseLiteralInt(=)
+                                  listener: handleLiteralInt(2)
+                        listener: handleAssignmentExpression(=)
+                        listener: endCascade()
+                  ensureSemicolon(2)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.parser.expect
new file mode 100644
index 0000000..1739363
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.parser.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f().g()['Hi!']..h().y = 2;
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken][[BeginToken]'Hi!'[StringToken]][SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken].[SimpleToken]y[StringToken] =[SimpleToken] 2[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.scanner.expect
new file mode 100644
index 0000000..1739363
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_2_prime.dart.scanner.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f().g()['Hi!']..h().y = 2;
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken][[BeginToken]'Hi!'[StringToken]][SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken].[SimpleToken]y[StringToken] =[SimpleToken] 2[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart
new file mode 100644
index 0000000..738829b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart
@@ -0,0 +1,3 @@
+void test(C x) {
+  x..f().g()..h();
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.expect
new file mode 100644
index 0000000..fc20249
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.expect
@@ -0,0 +1,52 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null)
+      handleVoidKeyword(void)
+      handleIdentifier(test, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(C, typeReference)
+          handleNoTypeArguments(x)
+          handleType(C, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(..)
+        handleNoArguments(..)
+        handleSend(x, ..)
+        beginCascade(..)
+          handleIdentifier(f, expressionContinuation)
+          handleNoTypeArguments(()
+          beginArguments(()
+          endArguments(0, (, ))
+          handleSend(f, .)
+        endBinaryExpression(..)
+        handleIdentifier(g, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(g, ..)
+      endBinaryExpression(.)
+    endCascade()
+    beginCascade(..)
+      handleIdentifier(h, expressionContinuation)
+      handleNoTypeArguments(()
+      beginArguments(()
+      endArguments(0, (, ))
+      handleSend(h, ;)
+    endBinaryExpression(..)
+  endCascade()
+  handleExpressionStatement(;)
+endBlockFunctionBody(1, {, })
+endTopLevelMethod(void, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.intertwined.expect
new file mode 100644
index 0000000..478a8f6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.intertwined.expect
@@ -0,0 +1,107 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, , Instance of 'VoidType', null, test)
+        listener: beginTopLevelMethod(, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifier(void, topLevelFunctionDeclaration)
+          listener: handleIdentifier(test, topLevelFunctionDeclaration)
+        parseMethodTypeVar(test)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(test, test, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(test, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(C)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(C, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(C, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(C, null)
+                ensureIdentifier(C, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, x)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(x)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(x, expression)
+                              listener: handleNoTypeArguments(..)
+                              parseArgumentsOpt(x)
+                                listener: handleNoArguments(..)
+                              listener: handleSend(x, ..)
+                      parseCascadeExpression(x)
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(f, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(f)
+                            parseArguments(f)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(f, .)
+                        listener: endBinaryExpression(..)
+                        parseSend(., expressionContinuation)
+                          ensureIdentifier(., expressionContinuation)
+                            listener: handleIdentifier(g, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(g)
+                            parseArguments(g)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(g, ..)
+                        listener: endBinaryExpression(.)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                      parseCascadeExpression())
+                        listener: beginCascade(..)
+                        parseSend(.., expressionContinuation)
+                          ensureIdentifier(.., expressionContinuation)
+                            listener: handleIdentifier(h, expressionContinuation)
+                          listener: handleNoTypeArguments(()
+                          parseArgumentsOpt(h)
+                            parseArguments(h)
+                              parseArgumentsRest(()
+                                listener: beginArguments(()
+                                listener: endArguments(0, (, ))
+                          listener: handleSend(h, ;)
+                        listener: endBinaryExpression(..)
+                        parseArgumentOrIndexStar(), Instance of 'NoTypeParamOrArg')
+                        listener: endCascade()
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.parser.expect
new file mode 100644
index 0000000..7ee59bd
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.parser.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f().g()..h();
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.scanner.expect
new file mode 100644
index 0000000..7ee59bd
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39286_prime.dart.scanner.expect
@@ -0,0 +1,9 @@
+void test(C x) {
+x..f().g()..h();
+}
+
+
+void[KeywordToken] test[StringToken]([BeginToken]C[StringToken] x[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]..[SimpleToken]f[StringToken]([BeginToken])[SimpleToken].[SimpleToken]g[StringToken]([BeginToken])[SimpleToken]..[SimpleToken]h[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39326.dart b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart
new file mode 100644
index 0000000..e00ed60
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart
@@ -0,0 +1,4 @@
+main() {
+  var c;
+  c?.[1] = 42;
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.expect
new file mode 100644
index 0000000..6a23a5b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.expect
@@ -0,0 +1,34 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleNoType(var)
+        beginVariablesDeclaration(c, null, var)
+          handleIdentifier(c, localVariableDeclaration)
+          beginInitializedIdentifier(c)
+            handleNoVariableInitializer(;)
+          endInitializedIdentifier(c)
+        endVariablesDeclaration(1, ;)
+        handleIdentifier(c, expression)
+        handleNoTypeArguments(?.[)
+        handleNoArguments(?.[)
+        handleSend(c, ?.[)
+        handleLiteralInt(1)
+        handleIndexedExpression(?.[, ])
+        handleLiteralInt(42)
+        handleAssignmentExpression(=)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(2, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.intertwined.expect
new file mode 100644
index 0000000..337ef55
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.intertwined.expect
@@ -0,0 +1,86 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, var)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, {, null, var, null, false)
+                looksLikeLocalFunction(c)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                listener: handleNoType(var)
+                listener: beginVariablesDeclaration(c, null, var)
+                parseVariablesDeclarationRest(var, true)
+                  parseOptionallyInitializedIdentifier(var)
+                    ensureIdentifier(var, localVariableDeclaration)
+                      listener: handleIdentifier(c, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(c)
+                    parseVariableInitializerOpt(c)
+                      listener: handleNoVariableInitializer(;)
+                    listener: endInitializedIdentifier(c)
+                  ensureSemicolon(c)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, c)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                looksLikeLocalFunction(c)
+                parseExpressionStatement(;)
+                  parseExpression(;)
+                    parsePrecedenceExpression(;, 1, true)
+                      parseUnaryExpression(;, true)
+                        parsePrimary(;, expression)
+                          parseSendOrFunctionLiteral(;, expression)
+                            parseSend(;, expression)
+                              ensureIdentifier(;, expression)
+                                listener: handleIdentifier(c, expression)
+                              listener: handleNoTypeArguments(?.[)
+                              parseArgumentsOpt(c)
+                                listener: handleNoArguments(?.[)
+                              listener: handleSend(c, ?.[)
+                      parseArgumentOrIndexStar(c, Instance of 'NoTypeParamOrArg')
+                        parseExpression(?.[)
+                          parsePrecedenceExpression(?.[, 1, true)
+                            parseUnaryExpression(?.[, true)
+                              parsePrimary(?.[, expression)
+                                parseLiteralInt(?.[)
+                                  listener: handleLiteralInt(1)
+                        listener: handleIndexedExpression(?.[, ])
+                      parsePrecedenceExpression(=, 1, true)
+                        parseUnaryExpression(=, true)
+                          parsePrimary(=, expression)
+                            parseLiteralInt(=)
+                              listener: handleLiteralInt(42)
+                      listener: handleAssignmentExpression(=)
+                  ensureSemicolon(42)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(2, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.parser.expect
new file mode 100644
index 0000000..0eb00a3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+var c;
+c?.[1] = 42;
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] c[StringToken];[SimpleToken]
+c[StringToken]?.[[BeginToken]1[StringToken]][SimpleToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.scanner.expect
new file mode 100644
index 0000000..0eb00a3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39326.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+var c;
+c?.[1] = 42;
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] c[StringToken];[SimpleToken]
+c[StringToken]?.[[BeginToken]1[StringToken]][SimpleToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart
new file mode 100644
index 0000000..e00ed60
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart
@@ -0,0 +1,4 @@
+main() {
+  var c;
+  c?.[1] = 42;
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.expect
new file mode 100644
index 0000000..db563cb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.expect
@@ -0,0 +1,36 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleNoType(var)
+        beginVariablesDeclaration(c, null, var)
+          handleIdentifier(c, localVariableDeclaration)
+          beginInitializedIdentifier(c)
+            handleNoVariableInitializer(;)
+          endInitializedIdentifier(c)
+        endVariablesDeclaration(1, ;)
+        handleIdentifier(c, expression)
+        handleNoTypeArguments(?.)
+        handleNoArguments(?.)
+        handleSend(c, ?.)
+        handleNoTypeArguments([)
+        handleLiteralInt(1)
+        handleLiteralList(1, [, null, ])
+      endBinaryExpression(?.)
+      handleLiteralInt(42)
+      handleAssignmentExpression(=)
+      handleExpressionStatement(;)
+    endBlockFunctionBody(2, {, })
+  endTopLevelMethod(main, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.intertwined.expect
new file mode 100644
index 0000000..d5b5a6b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.intertwined.expect
@@ -0,0 +1,89 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, var)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, {, null, var, null, false)
+                looksLikeLocalFunction(c)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                listener: handleNoType(var)
+                listener: beginVariablesDeclaration(c, null, var)
+                parseVariablesDeclarationRest(var, true)
+                  parseOptionallyInitializedIdentifier(var)
+                    ensureIdentifier(var, localVariableDeclaration)
+                      listener: handleIdentifier(c, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(c)
+                    parseVariableInitializerOpt(c)
+                      listener: handleNoVariableInitializer(;)
+                    listener: endInitializedIdentifier(c)
+                  ensureSemicolon(c)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, c)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                looksLikeLocalFunction(c)
+                parseExpressionStatement(;)
+                  parseExpression(;)
+                    parsePrecedenceExpression(;, 1, true)
+                      parseUnaryExpression(;, true)
+                        parsePrimary(;, expression)
+                          parseSendOrFunctionLiteral(;, expression)
+                            parseSend(;, expression)
+                              ensureIdentifier(;, expression)
+                                listener: handleIdentifier(c, expression)
+                              listener: handleNoTypeArguments(?.)
+                              parseArgumentsOpt(c)
+                                listener: handleNoArguments(?.)
+                              listener: handleSend(c, ?.)
+                      parsePrimary(?., expressionContinuation)
+                        listener: handleNoTypeArguments([)
+                        parseLiteralListSuffix(?., null)
+                          parseExpression([)
+                            parsePrecedenceExpression([, 1, true)
+                              parseUnaryExpression([, true)
+                                parsePrimary([, expression)
+                                  parseLiteralInt([)
+                                    listener: handleLiteralInt(1)
+                          listener: handleLiteralList(1, [, null, ])
+                      listener: endBinaryExpression(?.)
+                      parsePrecedenceExpression(=, 1, true)
+                        parseUnaryExpression(=, true)
+                          parsePrimary(=, expression)
+                            parseLiteralInt(=)
+                              listener: handleLiteralInt(42)
+                      listener: handleAssignmentExpression(=)
+                  ensureSemicolon(42)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(2, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.parser.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.parser.expect
new file mode 100644
index 0000000..ce9c907
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+var c;
+c?.[1] = 42;
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] c[StringToken];[SimpleToken]
+c[StringToken]?.[SimpleToken][[BeginToken]1[StringToken]][SimpleToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.scanner.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.scanner.expect
new file mode 100644
index 0000000..ce9c907
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_39326.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+var c;
+c?.[1] = 42;
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] c[StringToken];[SimpleToken]
+c[StringToken]?.[SimpleToken][[BeginToken]1[StringToken]][SimpleToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_test.dart
index 89766bd..c6d3fca 100644
--- a/pkg/front_end/test/explicit_creation_test.dart
+++ b/pkg/front_end/test/explicit_creation_test.dart
@@ -28,7 +28,7 @@
 import 'package:front_end/src/fasta/source/diet_listener.dart';
 import 'package:front_end/src/fasta/source/source_library_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
-import 'package:front_end/src/fasta/source/stack_listener.dart';
+import 'package:front_end/src/fasta/source/stack_listener_impl.dart';
 import 'package:front_end/src/fasta/ticker.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
@@ -146,7 +146,7 @@
       : super(library, hierarchy, coreTypes, typeInferenceEngine);
 
   @override
-  StackListener createListenerInternal(
+  StackListenerImpl createListenerInternal(
       ModifierBuilder builder,
       Scope memberScope,
       Scope formalParameterScope,
diff --git a/pkg/front_end/test/extensions/data/as_show/lib.dart b/pkg/front_end/test/extensions/data/as_show/lib.dart
index e89ef0c..cfe2924 100644
--- a/pkg/front_end/test/extensions/data/as_show/lib.dart
+++ b/pkg/front_end/test/extensions/data/as_show/lib.dart
@@ -6,14 +6,14 @@
 
 /*class: Extension1:
  builder-name=Extension1,
- builder-onType=String,
+ builder-onType=int,
  extension-members=[
   method1=Extension1|method1,
   tearoff method1=Extension1|get#method1],
  extension-name=Extension1,
- extension-onType=String
+ extension-onType=int
 */
-extension Extension1 on String {
+extension Extension1 on int {
   /*member: Extension1|method1:
    builder-name=method1,
    builder-params=[#this],
@@ -27,4 +27,4 @@
    builder-params=[#this],
    member-name=Extension1|get#method1,
    member-params=[#this]*/
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/test/extensions/data/as_show/main.dart b/pkg/front_end/test/extensions/data/as_show/main.dart
index 2a7d2d1..a46ead0 100644
--- a/pkg/front_end/test/extensions/data/as_show/main.dart
+++ b/pkg/front_end/test/extensions/data/as_show/main.dart
@@ -13,8 +13,8 @@
 import 'dart:test' show Extension2;
 
 main() {
-  "".method1();
-  Extension1("").method1();
+  0.method1();
+  Extension1(0).method1();
   "".method2();
   Extension2("").method2();
 }
diff --git a/pkg/front_end/test/extensions/data/prefix/lib1.dart b/pkg/front_end/test/extensions/data/prefix/lib1.dart
new file mode 100644
index 0000000..61f96cc
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/prefix/lib1.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: scope=[HiddenExtension1,ShownExtension1]*/
+
+/*class: ShownExtension1:
+ builder-name=ShownExtension1,
+ builder-onType=String,
+ extension-members=[static staticMethod=ShownExtension1|staticMethod],
+ extension-name=ShownExtension1,
+ extension-onType=String
+*/
+extension ShownExtension1 on String {
+  /*member: ShownExtension1|staticMethod:
+   builder-name=staticMethod,
+   member-name=ShownExtension1|staticMethod
+  */
+  static void staticMethod() {}
+}
+
+/*class: HiddenExtension1:
+ builder-name=HiddenExtension1,
+ builder-onType=String,
+ extension-members=[static staticMethod=HiddenExtension1|staticMethod],
+ extension-name=HiddenExtension1,
+ extension-onType=String
+*/
+extension HiddenExtension1 on String {
+  /*member: HiddenExtension1|staticMethod:
+   builder-name=staticMethod,
+   member-name=HiddenExtension1|staticMethod
+  */
+  static void staticMethod() {}
+}
diff --git a/pkg/front_end/test/extensions/data/prefix/lib2.dart b/pkg/front_end/test/extensions/data/prefix/lib2.dart
new file mode 100644
index 0000000..be8c655
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/prefix/lib2.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: scope=[HiddenExtension2,ShownExtension2]*/
+
+/*class: HiddenExtension2:
+ builder-name=HiddenExtension2,
+ builder-onType=String,
+ extension-members=[static staticMethod=HiddenExtension2|staticMethod],
+ extension-name=HiddenExtension2,
+ extension-onType=String
+*/
+extension HiddenExtension2 on String {
+  /*member: HiddenExtension2|staticMethod:
+   builder-name=staticMethod,
+   member-name=HiddenExtension2|staticMethod
+  */
+  static void staticMethod() {}
+}
+
+/*class: ShownExtension2:
+ builder-name=ShownExtension2,
+ builder-onType=String,
+ extension-members=[static staticMethod=ShownExtension2|staticMethod],
+ extension-name=ShownExtension2,
+ extension-onType=String
+*/
+extension ShownExtension2 on String {
+  /*member: ShownExtension2|staticMethod:
+   builder-name=staticMethod,
+   member-name=ShownExtension2|staticMethod
+  */
+  static void staticMethod() {}
+}
diff --git a/pkg/front_end/test/extensions/data/prefix/lib3.dart b/pkg/front_end/test/extensions/data/prefix/lib3.dart
new file mode 100644
index 0000000..26d3b8f
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/prefix/lib3.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: scope=[ShownExtension3]*/
+
+/*class: ShownExtension3:
+ builder-name=ShownExtension3,
+ builder-onType=String,
+ extension-members=[static staticMethod=ShownExtension3|staticMethod],
+ extension-name=ShownExtension3,
+ extension-onType=String
+*/
+extension ShownExtension3 on String {
+  /*member: ShownExtension3|staticMethod:
+   builder-name=staticMethod,
+   member-name=ShownExtension3|staticMethod
+  */
+  static void staticMethod() {}
+}
diff --git a/pkg/front_end/test/extensions/data/prefix/main.dart b/pkg/front_end/test/extensions/data/prefix/main.dart
new file mode 100644
index 0000000..0090c95
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/prefix/main.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: scope=[
+ lib1.dart.ShownExtension1,
+ lib2.dart.ShownExtension2,
+ lib3.dart.ShownExtension3]
+*/
+
+import 'lib1.dart' as lib1 show ShownExtension1;
+import 'lib2.dart' as lib2 hide HiddenExtension2;
+import 'lib3.dart' as lib3;
+
+main() {
+  lib1.ShownExtension1.staticMethod();
+  lib1. /*error: errors=[Getter not found: 'HiddenExtension1'.]*/
+      HiddenExtension1.staticMethod();
+  lib2.ShownExtension2.staticMethod();
+  lib2. /*error: errors=[Getter not found: 'HiddenExtension2'.]*/
+      HiddenExtension2.staticMethod();
+  lib3.ShownExtension3.staticMethod();
+}
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index 6f022ff..4da60ed 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -18,7 +18,7 @@
 import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/builder/type_builder.dart';
 import 'package:front_end/src/fasta/builder/type_variable_builder.dart';
-
+import 'package:front_end/src/fasta/source/source_library_builder.dart';
 import 'package:front_end/src/testing/features.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
@@ -134,9 +134,9 @@
   @override
   Features computeLibraryValue(Id id, Library library) {
     Features features = new Features();
-    LibraryBuilder libraryBuilder =
+    SourceLibraryBuilder libraryBuilder =
         lookupLibraryBuilder(compilerResult, library);
-    libraryBuilder.scope.forEachExtension((ExtensionBuilder extension) {
+    libraryBuilder.forEachExtensionInScope((ExtensionBuilder extension) {
       LibraryBuilder library = extension.parent;
       String libraryPrefix = '';
       if (library != libraryBuilder) {
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index f9e37c9..20fe91b 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -38,7 +38,7 @@
 import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
 
 import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
-    show LoadLibraryBuilder, UnlinkedDeclaration;
+    show LoadLibraryBuilder;
 
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
@@ -143,14 +143,10 @@
         " getter: $uri::myGetter, setter: $uri::mySetter)",
         new SuperPropertyAccessGenerator(helper, token, name, getter, setter));
     check(
-        "IndexedAccessGenerator(offset: 4, receiver: expression, index: index,"
-        " getter: $uri::myGetter, setter: $uri::mySetter)",
-        new IndexedAccessGenerator(
-            helper, token, expression, index, getter, setter));
-    check(
-        "ThisIndexedAccessGenerator(offset: 4, index: index,"
-        " getter: $uri::myGetter, setter: $uri::mySetter)",
-        new ThisIndexedAccessGenerator(helper, token, index, getter, setter));
+        "IndexedAccessGenerator(offset: 4, receiver: expression, index: index)",
+        new IndexedAccessGenerator(helper, token, expression, index));
+    check("ThisIndexedAccessGenerator(offset: 4, index: index)",
+        new ThisIndexedAccessGenerator(helper, token, index));
     check(
         "SuperIndexedAccessGenerator(offset: 4, index: index,"
         " getter: $uri::myGetter, setter: $uri::mySetter)",
@@ -196,10 +192,6 @@
         new TypeUseGenerator(helper, token, declaration, "foo"));
     check("UnresolvedNameGenerator(offset: 4, name: bar)",
         new UnresolvedNameGenerator.internal(helper, token, name));
-    check(
-        "UnlinkedGenerator(offset: 4, name: foo)",
-        new UnlinkedGenerator(
-            helper, token, new UnlinkedDeclaration("foo", false, -1, null)));
     check("PrefixUseGenerator(offset: 4, prefix: myPrefix, deferred: false)",
         prefixUseGenerator);
     check(
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
index 8da59a4..53b52a9c 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
@@ -45,8 +45,10 @@
     component = createMockSdkComponent();
     component.libraries.add(testLib..parent = component);
     coreTypes = new CoreTypes(component);
-    T1 = new TypeParameterType(new TypeParameter('T1', objectType));
-    T2 = new TypeParameterType(new TypeParameter('T2', objectType));
+    T1 = new TypeParameterType(
+        new TypeParameter('T1', objectType), Nullability.legacy);
+    T2 = new TypeParameterType(
+        new TypeParameter('T2', objectType), Nullability.legacy);
     classP = _addClass(_class('P'));
     classQ = _addClass(_class('Q'));
   }
@@ -96,76 +98,93 @@
   }
 
   void test_function_generic() {
-    var T = new TypeParameterType(new TypeParameter('T', objectType));
-    var U = new TypeParameterType(new TypeParameter('U', objectType));
+    var T = new TypeParameterType(
+        new TypeParameter('T', objectType), Nullability.legacy);
+    var U = new TypeParameterType(
+        new TypeParameter('U', objectType), Nullability.legacy);
     // <T>() -> dynamic <: () -> dynamic, never
     _checkConstraints(
-        new FunctionType([], dynamicType, typeParameters: [T.parameter]),
-        new FunctionType([], dynamicType),
+        new FunctionType([], dynamicType, Nullability.legacy,
+            typeParameters: [T.parameter]),
+        new FunctionType([], dynamicType, Nullability.legacy),
         null);
     // () -> dynamic <: <T>() -> dynamic, never
-    _checkConstraints(new FunctionType([], dynamicType),
-        new FunctionType([], dynamicType, typeParameters: [T.parameter]), null);
+    _checkConstraints(
+        new FunctionType([], dynamicType, Nullability.legacy),
+        new FunctionType([], dynamicType, Nullability.legacy,
+            typeParameters: [T.parameter]),
+        null);
     // <T>(T) -> T <: <U>(U) -> U, always
-    _checkConstraints(new FunctionType([T], T, typeParameters: [T.parameter]),
-        new FunctionType([U], U, typeParameters: [U.parameter]), []);
+    _checkConstraints(
+        new FunctionType([T], T, Nullability.legacy,
+            typeParameters: [T.parameter]),
+        new FunctionType([U], U, Nullability.legacy,
+            typeParameters: [U.parameter]),
+        []);
   }
 
   void test_function_parameter_mismatch() {
     // (P) -> dynamic <: () -> dynamic, never
-    _checkConstraints(new FunctionType([P], dynamicType),
-        new FunctionType([], dynamicType), null);
+    _checkConstraints(new FunctionType([P], dynamicType, Nullability.legacy),
+        new FunctionType([], dynamicType, Nullability.legacy), null);
     // () -> dynamic <: (P) -> dynamic, never
-    _checkConstraints(new FunctionType([], dynamicType),
-        new FunctionType([P], dynamicType), null);
+    _checkConstraints(new FunctionType([], dynamicType, Nullability.legacy),
+        new FunctionType([P], dynamicType, Nullability.legacy), null);
     // ([P]) -> dynamic <: () -> dynamic, always
     _checkConstraints(
-        new FunctionType([P], dynamicType, requiredParameterCount: 0),
-        new FunctionType([], dynamicType), []);
+        new FunctionType([P], dynamicType, Nullability.legacy,
+            requiredParameterCount: 0),
+        new FunctionType([], dynamicType, Nullability.legacy),
+        []);
     // () -> dynamic <: ([P]) -> dynamic, never
-    _checkConstraints(new FunctionType([], dynamicType),
-        new FunctionType([P], dynamicType, requiredParameterCount: 0), null);
+    _checkConstraints(
+        new FunctionType([], dynamicType, Nullability.legacy),
+        new FunctionType([P], dynamicType, Nullability.legacy,
+            requiredParameterCount: 0),
+        null);
     // ({x: P}) -> dynamic <: () -> dynamic, always
     _checkConstraints(
-        new FunctionType([], dynamicType,
+        new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('x', P)]),
-        new FunctionType([], dynamicType),
+        new FunctionType([], dynamicType, Nullability.legacy),
         []);
     // () -> dynamic !<: ({x: P}) -> dynamic, never
     _checkConstraints(
-        new FunctionType([], dynamicType),
-        new FunctionType([], dynamicType,
+        new FunctionType([], dynamicType, Nullability.legacy),
+        new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('x', P)]),
         null);
   }
 
   void test_function_parameter_types() {
     // (T1) -> dynamic <: (Q) -> dynamic, under constraint Q <: T1
-    _checkConstraints(new FunctionType([T1], dynamicType),
-        new FunctionType([Q], dynamicType), ['lib::Q* <: T1']);
+    _checkConstraints(
+        new FunctionType([T1], dynamicType, Nullability.legacy),
+        new FunctionType([Q], dynamicType, Nullability.legacy),
+        ['lib::Q* <: T1']);
     // ({x: T1}) -> dynamic <: ({x: Q}) -> dynamic, under constraint Q <: T1
     _checkConstraints(
-        new FunctionType([], dynamicType,
+        new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('x', T1)]),
-        new FunctionType([], dynamicType,
+        new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('x', Q)]),
         ['lib::Q* <: T1']);
   }
 
   void test_function_return_type() {
     // () -> T1 <: () -> Q, under constraint T1 <: Q
-    _checkConstraints(
-        new FunctionType([], T1), new FunctionType([], Q), ['T1 <: lib::Q*']);
+    _checkConstraints(new FunctionType([], T1, Nullability.legacy),
+        new FunctionType([], Q, Nullability.legacy), ['T1 <: lib::Q*']);
     // () -> P <: () -> void, always
-    _checkConstraints(
-        new FunctionType([], P), new FunctionType([], voidType), []);
+    _checkConstraints(new FunctionType([], P, Nullability.legacy),
+        new FunctionType([], voidType, Nullability.legacy), []);
     // () -> void <: () -> P, never
-    _checkConstraints(
-        new FunctionType([], voidType), new FunctionType([], P), null);
+    _checkConstraints(new FunctionType([], voidType, Nullability.legacy),
+        new FunctionType([], P, Nullability.legacy), null);
   }
 
   void test_function_trivial_cases() {
-    var F = new FunctionType([], dynamicType);
+    var F = new FunctionType([], dynamicType, Nullability.legacy);
     // () -> dynamic <: dynamic, always
     _checkConstraints(F, dynamicType, []);
     // () -> dynamic <: Function, always
@@ -175,7 +194,8 @@
   }
 
   void test_nonInferredParameter_subtype_any() {
-    var U = new TypeParameterType(new TypeParameter('U', _list(P)));
+    var U = new TypeParameterType(
+        new TypeParameter('U', _list(P)), Nullability.legacy);
     _checkConstraints(U, _list(T1), ['lib::P* <: T1']);
   }
 
@@ -250,10 +270,11 @@
   }
 
   DartType _iterable(DartType element) =>
-      new InterfaceType(iterableClass, [element]);
+      new InterfaceType(iterableClass, Nullability.legacy, [element]);
 
-  DartType _list(DartType element) => new InterfaceType(listClass, [element]);
+  DartType _list(DartType element) =>
+      new InterfaceType(listClass, Nullability.legacy, [element]);
 
   DartType _map(DartType key, DartType value) =>
-      new InterfaceType(mapClass, [key, value]);
+      new InterfaceType(mapClass, Nullability.legacy, [key, value]);
 }
diff --git a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
index b3c3aba..95452ab 100644
--- a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -18,7 +18,6 @@
   final TypeParameter T = new TypeParameter('T');
   final TypeParameter U = new TypeParameter('U');
   final TypeParameter V = new TypeParameter('V');
-  final Class cls = new Class(name: 'C');
 
   bool check(DartType type, List<TypeParameter> typeParameters) {
     return type.accept(new IncludesTypeParametersNonCovariantly(typeParameters,
@@ -26,81 +25,123 @@
   }
 
   bool checkContravariant(DartType type, List<TypeParameter> typeParameters) {
-    return check(new FunctionType([type], const VoidType()), typeParameters);
+    return check(new FunctionType([type], const VoidType(), Nullability.legacy),
+        typeParameters);
   }
 
   NamedType named(String name, DartType type) => new NamedType(name, type);
 
   void test_function_type() {
-    expect(check(new FunctionType([tpt(T), tpt(U)], const VoidType()), [T]),
-        isFalse);
-    expect(check(new FunctionType([tpt(T), tpt(U)], const VoidType()), [U]),
-        isFalse);
-    expect(check(new FunctionType([tpt(T), tpt(U)], const VoidType()), []),
+    expect(
+        check(
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            [T]),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(),
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            [U]),
+        isFalse);
+    expect(
+        check(
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            []),
+        isFalse);
+    expect(
+        check(
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [T]),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(),
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [U]),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(),
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             []),
         isFalse);
-    expect(check(new FunctionType([], tpt(T)), [T]), isTrue);
-    expect(check(new FunctionType([], tpt(T)), [U]), isFalse);
+    expect(
+        check(new FunctionType([], tpt(T), Nullability.legacy), [T]), isTrue);
+    expect(
+        check(new FunctionType([], tpt(T), Nullability.legacy), [U]), isFalse);
     expect(
         checkContravariant(
-            new FunctionType([tpt(T), tpt(U)], const VoidType()), [T]),
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            [T]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([tpt(T), tpt(U)], const VoidType()), [U]),
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            [U]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([tpt(T), tpt(U)], const VoidType()), []),
+            new FunctionType(
+                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+            []),
         isFalse);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(),
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [T]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(),
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [U]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(),
+            new FunctionType([], const VoidType(), Nullability.legacy,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             []),
         isFalse);
-    expect(checkContravariant(new FunctionType([], tpt(T)), [T]), isFalse);
-    expect(checkContravariant(new FunctionType([], tpt(T)), [U]), isFalse);
+    expect(
+        checkContravariant(
+            new FunctionType([], tpt(T), Nullability.legacy), [T]),
+        isFalse);
+    expect(
+        checkContravariant(
+            new FunctionType([], tpt(T), Nullability.legacy), [U]),
+        isFalse);
   }
 
   void test_interface_type() {
-    expect(check(new InterfaceType(cls, [tpt(T), tpt(U)]), [T]), isTrue);
-    expect(check(new InterfaceType(cls, [tpt(T), tpt(U)]), [U]), isTrue);
-    expect(check(new InterfaceType(cls, [tpt(T), tpt(U)]), []), isFalse);
-    expect(checkContravariant(new InterfaceType(cls, [tpt(T), tpt(U)]), [T]),
+    Class cls = new Class(name: 'C', typeParameters: [T, U]);
+    expect(
+        check(
+            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [T]),
+        isTrue);
+    expect(
+        check(
+            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [U]),
+        isTrue);
+    expect(
+        check(new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), []),
         isFalse);
-    expect(checkContravariant(new InterfaceType(cls, [tpt(T), tpt(U)]), [U]),
+    expect(
+        checkContravariant(
+            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [T]),
         isFalse);
-    expect(checkContravariant(new InterfaceType(cls, [tpt(T), tpt(U)]), []),
+    expect(
+        checkContravariant(
+            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [U]),
+        isFalse);
+    expect(
+        checkContravariant(
+            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), []),
         isFalse);
   }
 
@@ -116,39 +157,74 @@
     expect(checkContravariant(tpt(T), [T, U]), isFalse);
     expect(checkContravariant(tpt(U), [T, U]), isFalse);
     expect(checkContravariant(tpt(V), [T, U]), isFalse);
+
+    // Type parameters with explicit variance do not need contravariant checks
+    // if the variance position is greater or equal to the variance of the
+    // parameter on the [Variance] lattice.
+    expect(check(tpt(T, variance: Variance.covariant), [T, U]), isTrue);
+    expect(check(tpt(T, variance: Variance.contravariant), [T, U]), isFalse);
+    expect(check(tpt(T, variance: Variance.invariant), [T, U]), isFalse);
+    expect(check(tpt(V, variance: Variance.covariant), [T, U]), isFalse);
+    expect(check(tpt(V, variance: Variance.contravariant), [T, U]), isFalse);
+    expect(check(tpt(V, variance: Variance.invariant), [T, U]), isFalse);
+    expect(checkContravariant(tpt(T, variance: Variance.covariant), [T, U]),
+        isFalse);
+    expect(checkContravariant(tpt(T, variance: Variance.contravariant), [T, U]),
+        isTrue);
+    expect(checkContravariant(tpt(T, variance: Variance.invariant), [T, U]),
+        isFalse);
+    expect(checkContravariant(tpt(V, variance: Variance.covariant), [T, U]),
+        isFalse);
+    expect(checkContravariant(tpt(V, variance: Variance.contravariant), [T, U]),
+        isFalse);
+    expect(checkContravariant(tpt(V, variance: Variance.invariant), [T, U]),
+        isFalse);
   }
 
   void test_typedef_type() {
     // typedef U F<T, U>(T x);
-    var typedefNode = new Typedef('F', new FunctionType([tpt(T)], tpt(U)),
+    var typedefNode = new Typedef(
+        'F', new FunctionType([tpt(T)], tpt(U), Nullability.legacy),
         typeParameters: [T, U]);
     expect(
         check(
-            new TypedefType(
-                typedefNode, [const DynamicType(), const DynamicType()]),
+            new TypedefType(typedefNode, Nullability.legacy,
+                [const DynamicType(), const DynamicType()]),
             [V]),
         isFalse);
     expect(
-        check(new TypedefType(typedefNode, [tpt(V), const DynamicType()]), [V]),
+        check(
+            new TypedefType(
+                typedefNode, Nullability.legacy, [tpt(V), const DynamicType()]),
+            [V]),
         isFalse);
     expect(
-        check(new TypedefType(typedefNode, [const DynamicType(), tpt(V)]), [V]),
+        check(
+            new TypedefType(
+                typedefNode, Nullability.legacy, [const DynamicType(), tpt(V)]),
+            [V]),
         isTrue);
     expect(
         checkContravariant(
-            new TypedefType(
-                typedefNode, [const DynamicType(), const DynamicType()]),
+            new TypedefType(typedefNode, Nullability.legacy,
+                [const DynamicType(), const DynamicType()]),
             [V]),
         isFalse);
     expect(
         checkContravariant(
-            new TypedefType(typedefNode, [tpt(V), const DynamicType()]), [V]),
+            new TypedefType(
+                typedefNode, Nullability.legacy, [tpt(V), const DynamicType()]),
+            [V]),
         isTrue);
     expect(
         checkContravariant(
-            new TypedefType(typedefNode, [const DynamicType(), tpt(V)]), [V]),
+            new TypedefType(
+                typedefNode, Nullability.legacy, [const DynamicType(), tpt(V)]),
+            [V]),
         isFalse);
   }
 
-  TypeParameterType tpt(TypeParameter param) => new TypeParameterType(param);
+  TypeParameterType tpt(TypeParameter param, {int variance = null}) =>
+      new TypeParameterType(param, Nullability.legacy)
+        ..parameter.variance = variance;
 }
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
index b6d152f..11792bc 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
@@ -36,11 +36,12 @@
 
   void test_greatestClosure_contravariant() {
     expect(
-        greatestClosure(new FunctionType([unknownType], dynamicType))
+        greatestClosure(new FunctionType(
+                [unknownType], dynamicType, Nullability.legacy))
             .toString(),
         '(dart.core::Null?) →* dynamic');
     expect(
-        greatestClosure(new FunctionType([], dynamicType,
+        greatestClosure(new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('foo', unknownType)])).toString(),
         '({foo: dart.core::Null?}) →* dynamic');
   }
@@ -48,25 +49,27 @@
   void test_greatestClosure_contravariant_contravariant() {
     expect(
         greatestClosure(new FunctionType([
-          new FunctionType([unknownType], dynamicType)
-        ], dynamicType))
+          new FunctionType([unknownType], dynamicType, Nullability.legacy)
+        ], dynamicType, Nullability.legacy))
             .toString(),
         '((dynamic) →* dynamic) →* dynamic');
   }
 
   void test_greatestClosure_covariant() {
-    expect(greatestClosure(new FunctionType([], unknownType)).toString(),
+    expect(
+        greatestClosure(new FunctionType([], unknownType, Nullability.legacy))
+            .toString(),
         '() →* dynamic');
     expect(
-        greatestClosure(new InterfaceType(coreTypes.listClass, [unknownType]))
-            .toString(),
+        greatestClosure(new InterfaceType(
+            coreTypes.listClass, Nullability.legacy, [unknownType])).toString(),
         'dart.core::List<dynamic>*');
   }
 
   void test_greatestClosure_function_multipleUnknown() {
     expect(
         greatestClosure(new FunctionType(
-            [unknownType, unknownType], unknownType,
+            [unknownType, unknownType], unknownType, Nullability.legacy,
             namedParameters: [
               new NamedType('a', unknownType),
               new NamedType('b', unknownType)
@@ -81,10 +84,12 @@
 
   void test_leastClosure_contravariant() {
     expect(
-        leastClosure(new FunctionType([unknownType], dynamicType)).toString(),
+        leastClosure(new FunctionType(
+                [unknownType], dynamicType, Nullability.legacy))
+            .toString(),
         '(dynamic) →* dynamic');
     expect(
-        leastClosure(new FunctionType([], dynamicType,
+        leastClosure(new FunctionType([], dynamicType, Nullability.legacy,
             namedParameters: [new NamedType('foo', unknownType)])).toString(),
         '({foo: dynamic}) →* dynamic');
   }
@@ -92,24 +97,27 @@
   void test_leastClosure_contravariant_contravariant() {
     expect(
         leastClosure(new FunctionType([
-          new FunctionType([unknownType], dynamicType)
-        ], dynamicType))
+          new FunctionType([unknownType], dynamicType, Nullability.legacy)
+        ], dynamicType, Nullability.legacy))
             .toString(),
         '((dart.core::Null?) →* dynamic) →* dynamic');
   }
 
   void test_leastClosure_covariant() {
-    expect(leastClosure(new FunctionType([], unknownType)).toString(),
+    expect(
+        leastClosure(new FunctionType([], unknownType, Nullability.legacy))
+            .toString(),
         '() →* dart.core::Null?');
     expect(
-        leastClosure(new InterfaceType(coreTypes.listClass, [unknownType]))
-            .toString(),
+        leastClosure(new InterfaceType(
+            coreTypes.listClass, Nullability.legacy, [unknownType])).toString(),
         'dart.core::List<dart.core::Null?>*');
   }
 
   void test_leastClosure_function_multipleUnknown() {
     expect(
-        leastClosure(new FunctionType([unknownType, unknownType], unknownType,
+        leastClosure(new FunctionType(
+            [unknownType, unknownType], unknownType, Nullability.legacy,
             namedParameters: [
               new NamedType('a', unknownType),
               new NamedType('b', unknownType)
@@ -137,7 +145,7 @@
 
   _MockCoreTypes() {
     nullType = new InterfaceType(
-        nullClass, const <DynamicType>[], Nullability.nullable);
+        nullClass, Nullability.nullable, const <DynamicType>[]);
     new Library(Uri.parse('dart:core'),
         name: 'dart.core', classes: [listClass, nullClass, objectClass]);
   }
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index c92c98e..3d9d3b1 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -109,59 +109,65 @@
     var env = _makeEnv();
     // GLB(() -> A, () -> B) = () -> B
     expect(
-        env.getStandardLowerBound(
-            new FunctionType([], A), new FunctionType([], B)),
-        new FunctionType([], B));
+        env.getStandardLowerBound(new FunctionType([], A, Nullability.legacy),
+            new FunctionType([], B, Nullability.legacy)),
+        new FunctionType([], B, Nullability.legacy));
     // GLB(() -> void, (A, B) -> void) = ([A, B]) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType), new FunctionType([A, B], voidType)),
-        new FunctionType([A, B], voidType, requiredParameterCount: 0));
+            new FunctionType([], voidType, Nullability.legacy),
+            new FunctionType([A, B], voidType, Nullability.legacy)),
+        new FunctionType([A, B], voidType, Nullability.legacy,
+            requiredParameterCount: 0));
     expect(
         env.getStandardLowerBound(
-            new FunctionType([A, B], voidType), new FunctionType([], voidType)),
-        new FunctionType([A, B], voidType, requiredParameterCount: 0));
+            new FunctionType([A, B], voidType, Nullability.legacy),
+            new FunctionType([], voidType, Nullability.legacy)),
+        new FunctionType([A, B], voidType, Nullability.legacy,
+            requiredParameterCount: 0));
     // GLB((A) -> void, (B) -> void) = (A) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([A], voidType), new FunctionType([B], voidType)),
-        new FunctionType([A], voidType));
+            new FunctionType([A], voidType, Nullability.legacy),
+            new FunctionType([B], voidType, Nullability.legacy)),
+        new FunctionType([A], voidType, Nullability.legacy));
     expect(
         env.getStandardLowerBound(
-            new FunctionType([B], voidType), new FunctionType([A], voidType)),
-        new FunctionType([A], voidType));
+            new FunctionType([B], voidType, Nullability.legacy),
+            new FunctionType([A], voidType, Nullability.legacy)),
+        new FunctionType([A], voidType, Nullability.legacy));
     // GLB(({a: A}) -> void, ({b: B}) -> void) = ({a: A, b: B}) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('b', B)])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', A), new NamedType('b', B)]));
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('b', B)]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', A), new NamedType('b', B)]));
     // GLB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void)
     //     = ({a: A, b: B, c: A, d: B}) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('c', A)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('b', B),
                   new NamedType('d', B)
                 ])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [
               new NamedType('a', A),
               new NamedType('b', B),
@@ -172,53 +178,54 @@
     //     = ({a: A, b: A}) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('b', B)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', B),
                   new NamedType('b', A)
                 ])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', A), new NamedType('b', A)]));
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', B),
                   new NamedType('b', A)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('b', B)
                 ])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', A), new NamedType('b', A)]));
     // GLB((B, {a: A}) -> void, (B) -> void) = (B, {a: A}) -> void
     expect(
         env.getStandardLowerBound(
-            new FunctionType([B], voidType,
+            new FunctionType([B], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType)),
-        new FunctionType([B], voidType,
+            new FunctionType([B], voidType, Nullability.legacy)),
+        new FunctionType([B], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', A)]));
     // GLB(({a: A}) -> void, (B) -> void) = bottom
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType)),
+            new FunctionType([B], voidType, Nullability.legacy)),
         same(bottomType));
     // GLB(({a: A}) -> void, ([B]) -> void) = bottom
     expect(
         env.getStandardLowerBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType, requiredParameterCount: 0)),
+            new FunctionType([B], voidType, Nullability.legacy,
+                requiredParameterCount: 0)),
         same(bottomType));
   }
 
@@ -226,7 +233,10 @@
     var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, A), same(A));
-    expect(env.getStandardLowerBound(new InterfaceType(A.classNode), A), A);
+    expect(
+        env.getStandardLowerBound(
+            new InterfaceType(A.classNode, Nullability.legacy), A),
+        A);
   }
 
   void test_glb_subtype() {
@@ -392,120 +402,129 @@
     var env = _makeEnv();
     // LUB(() -> A, () -> B) = () -> A
     expect(
-        env.getStandardUpperBound(
-            new FunctionType([], A), new FunctionType([], B)),
-        new FunctionType([], A));
+        env.getStandardUpperBound(new FunctionType([], A, Nullability.legacy),
+            new FunctionType([], B, Nullability.legacy)),
+        new FunctionType([], A, Nullability.legacy));
     // LUB(([A]) -> void, (A) -> void) = Function
     expect(
         env.getStandardUpperBound(
-            new FunctionType([A], voidType, requiredParameterCount: 0),
-            new FunctionType([A], voidType)),
+            new FunctionType([A], voidType, Nullability.legacy,
+                requiredParameterCount: 0),
+            new FunctionType([A], voidType, Nullability.legacy)),
         functionType);
     // LUB(() -> void, (A, B) -> void) = Function
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType), new FunctionType([A, B], voidType)),
+            new FunctionType([], voidType, Nullability.legacy),
+            new FunctionType([A, B], voidType, Nullability.legacy)),
         functionType);
     expect(
         env.getStandardUpperBound(
-            new FunctionType([A, B], voidType), new FunctionType([], voidType)),
+            new FunctionType([A, B], voidType, Nullability.legacy),
+            new FunctionType([], voidType, Nullability.legacy)),
         functionType);
     // LUB((A) -> void, (B) -> void) = (B) -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([A], voidType), new FunctionType([B], voidType)),
-        new FunctionType([B], voidType));
+            new FunctionType([A], voidType, Nullability.legacy),
+            new FunctionType([B], voidType, Nullability.legacy)),
+        new FunctionType([B], voidType, Nullability.legacy));
     expect(
         env.getStandardUpperBound(
-            new FunctionType([B], voidType), new FunctionType([A], voidType)),
-        new FunctionType([B], voidType));
+            new FunctionType([B], voidType, Nullability.legacy),
+            new FunctionType([A], voidType, Nullability.legacy)),
+        new FunctionType([B], voidType, Nullability.legacy));
     // LUB(({a: A}) -> void, ({b: B}) -> void) = () -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('b', B)])),
-        new FunctionType([], voidType));
+        new FunctionType([], voidType, Nullability.legacy));
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('b', B)]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)])),
-        new FunctionType([], voidType));
+        new FunctionType([], voidType, Nullability.legacy));
     // LUB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void) = () -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('c', A)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('b', B),
                   new NamedType('d', B)
                 ])),
-        new FunctionType([], voidType));
+        new FunctionType([], voidType, Nullability.legacy));
     // LUB(({a: A, b: B}) -> void, ({a: B, b: A}) -> void)
     //     = ({a: B, b: B}) -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('b', B)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', B),
                   new NamedType('b', A)
                 ])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', B), new NamedType('b', B)]));
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', B),
                   new NamedType('b', A)
                 ]),
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [
                   new NamedType('a', A),
                   new NamedType('b', B)
                 ])),
-        new FunctionType([], voidType,
+        new FunctionType([], voidType, Nullability.legacy,
             namedParameters: [new NamedType('a', B), new NamedType('b', B)]));
     // LUB((B, {a: A}) -> void, (B) -> void) = (B) -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([B], voidType,
+            new FunctionType([B], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType)),
-        new FunctionType([B], voidType));
+            new FunctionType([B], voidType, Nullability.legacy)),
+        new FunctionType([B], voidType, Nullability.legacy));
     // LUB(({a: A}) -> void, (B) -> void) = Function
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType)),
+            new FunctionType([B], voidType, Nullability.legacy)),
         functionType);
     // GLB(({a: A}) -> void, ([B]) -> void) = () -> void
     expect(
         env.getStandardUpperBound(
-            new FunctionType([], voidType,
+            new FunctionType([], voidType, Nullability.legacy,
                 namedParameters: [new NamedType('a', A)]),
-            new FunctionType([B], voidType, requiredParameterCount: 0)),
-        new FunctionType([], voidType));
+            new FunctionType([B], voidType, Nullability.legacy,
+                requiredParameterCount: 0)),
+        new FunctionType([], voidType, Nullability.legacy));
   }
 
   void test_lub_identical() {
     var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardUpperBound(A, A), same(A));
-    expect(env.getStandardUpperBound(new InterfaceType(A.classNode), A), A);
+    expect(
+        env.getStandardUpperBound(
+            new InterfaceType(A.classNode, Nullability.legacy), A),
+        A);
   }
 
   void test_lub_sameClass() {
@@ -545,9 +564,9 @@
   }
 
   void test_lub_typeParameter() {
-    var T = new TypeParameterType(new TypeParameter('T'));
+    var T = new TypeParameterType(new TypeParameter('T'), Nullability.legacy);
     T.parameter.bound = _list(T);
-    var U = new TypeParameterType(new TypeParameter('U'));
+    var U = new TypeParameterType(new TypeParameter('U'), Nullability.legacy);
     U.parameter.bound = _list(bottomType);
     var env = _makeEnv();
     // LUB(T, T) = T
@@ -587,15 +606,17 @@
     // Solve(A<?> <: T <: ?) => A<?>
     expect(
         env.solveTypeConstraint(_makeConstraint(
-            lower: new InterfaceType(A.classNode, [unknownType]))),
-        new InterfaceType(A.classNode, [unknownType]));
+            lower: new InterfaceType(
+                A.classNode, Nullability.legacy, [unknownType]))),
+        new InterfaceType(A.classNode, Nullability.legacy, [unknownType]));
     // Solve(A<?> <: T <: ?, grounded) => A<Null>
     expect(
         env.solveTypeConstraint(
             _makeConstraint(
-                lower: new InterfaceType(A.classNode, [unknownType])),
+                lower: new InterfaceType(
+                    A.classNode, Nullability.legacy, [unknownType])),
             grounded: true),
-        new InterfaceType(A.classNode, [nullType]));
+        new InterfaceType(A.classNode, Nullability.legacy, [nullType]));
     // Solve(? <: T <: A) => A
     expect(env.solveTypeConstraint(_makeConstraint(upper: A)), A);
     // Solve(? <: T <: A, grounded) => A
@@ -604,15 +625,17 @@
     // Solve(? <: T <: A<?>) => A<?>
     expect(
         env.solveTypeConstraint(_makeConstraint(
-            upper: new InterfaceType(A.classNode, [unknownType]))),
-        new InterfaceType(A.classNode, [unknownType]));
+            upper: new InterfaceType(
+                A.classNode, Nullability.legacy, [unknownType]))),
+        new InterfaceType(A.classNode, Nullability.legacy, [unknownType]));
     // Solve(? <: T <: A<?>, grounded) => A<dynamic>
     expect(
         env.solveTypeConstraint(
             _makeConstraint(
-                upper: new InterfaceType(A.classNode, [unknownType])),
+                upper: new InterfaceType(
+                    A.classNode, Nullability.legacy, [unknownType])),
             grounded: true),
-        new InterfaceType(A.classNode, [dynamicType]));
+        new InterfaceType(A.classNode, Nullability.legacy, [dynamicType]));
     // Solve(B <: T <: A) => B
     expect(env.solveTypeConstraint(_makeConstraint(lower: B, upper: A)), B);
     // Solve(B <: T <: A, grounded) => B
@@ -623,41 +646,53 @@
     // Solve(B<?> <: T <: A) => A
     expect(
         env.solveTypeConstraint(_makeConstraint(
-            lower: new InterfaceType(B.classNode, [unknownType]), upper: A)),
+            lower: new InterfaceType(
+                B.classNode, Nullability.legacy, [unknownType]),
+            upper: A)),
         A);
     // Solve(B<?> <: T <: A, grounded) => A
     expect(
         env.solveTypeConstraint(
             _makeConstraint(
-                lower: new InterfaceType(B.classNode, [unknownType]), upper: A),
+                lower: new InterfaceType(
+                    B.classNode, Nullability.legacy, [unknownType]),
+                upper: A),
             grounded: true),
         A);
     // Solve(B <: T <: A<?>) => B
     expect(
         env.solveTypeConstraint(_makeConstraint(
-            lower: B, upper: new InterfaceType(A.classNode, [unknownType]))),
+            lower: B,
+            upper: new InterfaceType(
+                A.classNode, Nullability.legacy, [unknownType]))),
         B);
     // Solve(B <: T <: A<?>, grounded) => B
     expect(
         env.solveTypeConstraint(
             _makeConstraint(
-                lower: B, upper: new InterfaceType(A.classNode, [unknownType])),
+                lower: B,
+                upper: new InterfaceType(
+                    A.classNode, Nullability.legacy, [unknownType])),
             grounded: true),
         B);
     // Solve(B<?> <: T <: A<?>) => B<?>
     expect(
         env.solveTypeConstraint(_makeConstraint(
-            lower: new InterfaceType(B.classNode, [unknownType]),
-            upper: new InterfaceType(A.classNode, [unknownType]))),
-        new InterfaceType(B.classNode, [unknownType]));
+            lower: new InterfaceType(
+                B.classNode, Nullability.legacy, [unknownType]),
+            upper: new InterfaceType(
+                A.classNode, Nullability.legacy, [unknownType]))),
+        new InterfaceType(B.classNode, Nullability.legacy, [unknownType]));
     // Solve(B<?> <: T <: A<?>) => B<Null>
     expect(
         env.solveTypeConstraint(
             _makeConstraint(
-                lower: new InterfaceType(B.classNode, [unknownType]),
-                upper: new InterfaceType(A.classNode, [unknownType])),
+                lower: new InterfaceType(
+                    B.classNode, Nullability.legacy, [unknownType]),
+                upper: new InterfaceType(
+                    A.classNode, Nullability.legacy, [unknownType])),
             grounded: true),
-        new InterfaceType(B.classNode, [nullType]));
+        new InterfaceType(B.classNode, Nullability.legacy, [nullType]));
   }
 
   void test_typeConstraint_default() {
@@ -722,10 +757,10 @@
   }
 
   DartType _iterable(DartType elementType) =>
-      new InterfaceType(iterableClass, [elementType]);
+      new InterfaceType(iterableClass, Nullability.legacy, [elementType]);
 
   DartType _list(DartType elementType) =>
-      new InterfaceType(listClass, [elementType]);
+      new InterfaceType(listClass, Nullability.legacy, [elementType]);
 
   TypeConstraint _makeConstraint(
       {DartType lower: const UnknownType(),
@@ -740,5 +775,5 @@
   }
 
   DartType _map(DartType key, DartType value) =>
-      new InterfaceType(mapClass, [key, value]);
+      new InterfaceType(mapClass, Nullability.legacy, [key, value]);
 }
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_test.dart
index 471b69d..8c6f5a2 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_test.dart
@@ -30,26 +30,36 @@
     expect(isKnown(unknownType), isFalse);
     expect(isKnown(const DynamicType()), isTrue);
     var classA = new Class(name: 'A');
-    var A = new InterfaceType(classA);
+    var A = new InterfaceType(classA, Nullability.legacy);
     var typedefF = new Typedef('F', A);
     expect(isKnown(A), isTrue);
-    expect(isKnown(new InterfaceType(classA, [A])), isTrue);
-    expect(isKnown(new InterfaceType(classA, [unknownType])), isFalse);
-    expect(isKnown(new FunctionType([], const VoidType())), isTrue);
-    expect(isKnown(new FunctionType([], unknownType)), isFalse);
-    expect(isKnown(new FunctionType([A], const VoidType())), isTrue);
-    expect(isKnown(new FunctionType([unknownType], const VoidType())), isFalse);
+    expect(isKnown(new InterfaceType(classA, Nullability.legacy, [A])), isTrue);
     expect(
-        isKnown(new FunctionType([], const VoidType(),
+        isKnown(new InterfaceType(classA, Nullability.legacy, [unknownType])),
+        isFalse);
+    expect(isKnown(new FunctionType([], const VoidType(), Nullability.legacy)),
+        isTrue);
+    expect(isKnown(new FunctionType([], unknownType, Nullability.legacy)),
+        isFalse);
+    expect(isKnown(new FunctionType([A], const VoidType(), Nullability.legacy)),
+        isTrue);
+    expect(
+        isKnown(new FunctionType(
+            [unknownType], const VoidType(), Nullability.legacy)),
+        isFalse);
+    expect(
+        isKnown(new FunctionType([], const VoidType(), Nullability.legacy,
             namedParameters: [new NamedType('x', A)])),
         isTrue);
     expect(
-        isKnown(new FunctionType([], const VoidType(),
+        isKnown(new FunctionType([], const VoidType(), Nullability.legacy,
             namedParameters: [new NamedType('x', unknownType)])),
         isFalse);
-    expect(isKnown(new TypedefType(typedefF)), isTrue);
-    expect(isKnown(new TypedefType(typedefF, [A])), isTrue);
-    expect(isKnown(new TypedefType(typedefF, [unknownType])), isFalse);
+    expect(isKnown(new TypedefType(typedefF, Nullability.legacy)), isTrue);
+    expect(isKnown(new TypedefType(typedefF, Nullability.legacy, [A])), isTrue);
+    expect(
+        isKnown(new TypedefType(typedefF, Nullability.legacy, [unknownType])),
+        isFalse);
   }
 
   void test_ordinary_visitor_noOverrides() {
@@ -88,8 +98,8 @@
     expect(unknownType.toString(), isNot('?'));
     expect(typeSchemaToString(unknownType), '?');
     expect(
-        typeSchemaToString(
-            new FunctionType([unknownType, unknownType], unknownType)),
+        typeSchemaToString(new FunctionType(
+            [unknownType, unknownType], unknownType, Nullability.legacy)),
         '(?, ?) →* ?');
   }
 
diff --git a/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart b/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart
deleted file mode 100644
index 94e56f1..0000000
--- a/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:convert' show jsonDecode;
-
-import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
-import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
-
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
-import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/fasta/builder/builder.dart';
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/messages.dart'
-    show LocatedMessage, templateUnspecified;
-
-import 'package:front_end/src/fasta/source/type_promotion_look_ahead_listener.dart'
-    show
-        TypePromotionLookAheadListener,
-        TypePromotionState,
-        UnspecifiedDeclaration;
-
-import 'package:kernel/ast.dart' show Source;
-
-import 'package:testing/testing.dart'
-    show Chain, ChainContext, ExpectationSet, Future, Result, Step, runMe;
-
-import '../utils/kernel_chain.dart' show MatchContext;
-
-import '../utils/scanner_chain.dart' show Read, Scan, ScannedFile;
-
-const String EXPECTATIONS = '''
-[
-  {
-    "name": "ExpectationFileMismatch",
-    "group": "Fail"
-  },
-  {
-    "name": "ExpectationFileMissing",
-    "group": "Fail"
-  }
-]
-''';
-
-Future<ChainContext> createContext(
-    Chain suite, Map<String, String> environment) async {
-  CompilerContext context =
-      await CompilerContext.runWithOptions<CompilerContext>(
-          new ProcessedOptions(),
-          (CompilerContext context) =>
-              new Future<CompilerContext>.value(context),
-          errorOnMissingInput: false);
-  colors.enableColors = false;
-  return new TypePromotionLookAheadContext(
-      context, environment["updateExpectations"] == "true");
-}
-
-class TypePromotionLookAheadContext extends ChainContext with MatchContext {
-  final CompilerContext context;
-
-  final List<Step> steps = const <Step>[
-    const Read(),
-    const Scan(),
-    const TypePromotionLookAheadStep(),
-    const CheckTypePromotionResult(),
-  ];
-
-  final bool updateExpectations;
-
-  final ExpectationSet expectationSet =
-      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
-
-  TypePromotionLookAheadContext(this.context, this.updateExpectations);
-}
-
-class TypePromotionLookAheadStep extends Step<ScannedFile, TypePromotionResult,
-    TypePromotionLookAheadContext> {
-  const TypePromotionLookAheadStep();
-
-  String get name => "Type Promotion Look Ahead";
-
-  Future<Result<TypePromotionResult>> run(
-      ScannedFile file, TypePromotionLookAheadContext context) async {
-    return context.context
-        .runInContext<Result<TypePromotionResult>>((CompilerContext c) async {
-      Uri uri = file.file.uri;
-      c.uriToSource[uri] =
-          new Source(file.result.lineStarts, file.file.bytes, uri, uri);
-      StringBuffer buffer = new StringBuffer();
-      Parser parser = new Parser(new TestListener(uri, buffer));
-      try {
-        parser.parseUnit(file.result.tokens);
-      } finally {
-        c.uriToSource.remove(uri);
-      }
-      return pass(new TypePromotionResult(uri, "$buffer"));
-    });
-  }
-}
-
-class TestState extends TypePromotionState {
-  final StringBuffer buffer;
-
-  TestState(Uri uri, this.buffer) : super(uri);
-
-  void note(String message, Token token) {
-    buffer.writeln(CompilerContext.current.format(
-        debugMessage(message, uri, token.charOffset, token.lexeme.length),
-        Severity.context));
-  }
-
-  @override
-  void checkEmpty(Token token) {
-    if (stack.isNotEmpty) {
-      throw CompilerContext.current.format(
-          debugMessage("Stack not empty", uri, token?.charOffset ?? -1,
-              token?.length ?? 1),
-          Severity.internalProblem);
-    }
-  }
-
-  @override
-  void declareIdentifier(Token token) {
-    super.declareIdentifier(token);
-    trace("Declared ${token.lexeme}", token);
-  }
-
-  @override
-  Builder nullValue(String name, Token token) {
-    return new DebugDeclaration(name, uri, token?.charOffset ?? -1);
-  }
-
-  @override
-  void registerWrite(UnspecifiedDeclaration declaration, Token token) {
-    note("Write to ${declaration.name}@${declaration.charOffset}", token);
-  }
-
-  @override
-  void registerPromotionCandidate(
-      UnspecifiedDeclaration declaration, Token token) {
-    note("Possible promotion of ${declaration.name}@${declaration.charOffset}",
-        token);
-  }
-
-  @override
-  void report(LocatedMessage message, Severity severity,
-      {List<LocatedMessage> context}) {
-    CompilerContext.current.report(message, severity, context: context);
-  }
-
-  @override
-  void trace(String message, Token token) {
-    report(
-        debugMessage(message, uri, token?.charOffset ?? -1, token?.length ?? 1),
-        Severity.warning);
-    for (Object o in stack) {
-      String s = "  $o";
-      int index = s.indexOf("\n");
-      if (index != -1) {
-        s = s.substring(0, index) + "...";
-      }
-      print(s);
-    }
-    print('------------------\n');
-  }
-}
-
-LocatedMessage debugMessage(String text, Uri uri, int offset, int length) {
-  return templateUnspecified
-      .withArguments(text)
-      .withLocation(uri, offset, length);
-}
-
-class TestListener extends TypePromotionLookAheadListener {
-  TestListener(Uri uri, StringBuffer buffer)
-      : super(new TestState(uri, buffer));
-
-  @override
-  void debugEvent(String name, Token token) {
-    state.trace(name, token);
-  }
-}
-
-class DebugDeclaration extends BuilderImpl {
-  final String name;
-
-  @override
-  final Uri fileUri;
-
-  @override
-  int charOffset;
-
-  DebugDeclaration(this.name, this.fileUri, this.charOffset);
-
-  Builder get parent => null;
-
-  String get fullNameForErrors => name;
-
-  String toString() => "<<$name@$charOffset>>";
-}
-
-class TypePromotionResult {
-  final Uri uri;
-
-  final String trace;
-
-  const TypePromotionResult(this.uri, this.trace);
-}
-
-class CheckTypePromotionResult
-    extends Step<TypePromotionResult, Null, TypePromotionLookAheadContext> {
-  const CheckTypePromotionResult();
-
-  String get name => "Check Type Promotion Result";
-
-  Future<Result<Null>> run(
-      TypePromotionResult result, TypePromotionLookAheadContext context) {
-    return context.match<Null>(
-        ".type_promotion.expect", result.trace, result.uri, null);
-  }
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser.dart b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
index 3ad30a1..d9e5d85 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -178,8 +178,8 @@
       } else if (kernelArguments.length != typeVariables.length) {
         throw "Expected ${typeVariables.length} type arguments: $node";
       }
-      return new InterfaceType(declaration, kernelArguments,
-          interpretParsedNullability(node.parsedNullability));
+      return new InterfaceType(declaration,
+          interpretParsedNullability(node.parsedNullability), kernelArguments);
     } else if (declaration is TypeParameter) {
       if (arguments.isNotEmpty) {
         throw "Type variable can't have arguments (${node.name})";
@@ -189,7 +189,6 @@
           : TypeParameterType.computeNullabilityFromBound(declaration);
       TypeParameterType type = new TypeParameterType(
           declaration,
-          null,
           interpretParsedNullability(node.parsedNullability,
               ifOmitted: nullability));
       // If the nullability was omitted on the type and can't be computed from
@@ -201,8 +200,8 @@
       }
       return type;
     } else if (declaration is Typedef) {
-      return new TypedefType(declaration, kernelArguments,
-          interpretParsedNullability(node.parsedNullability));
+      return new TypedefType(declaration,
+          interpretParsedNullability(node.parsedNullability), kernelArguments);
     } else {
       throw "Unhandled ${declaration.runtimeType}";
     }
@@ -256,12 +255,12 @@
       type = node.type.accept<Node, KernelEnvironment>(this, environment);
       if (type is FunctionType) {
         FunctionType f = type;
-        type = new FunctionType(f.positionalParameters, f.returnType,
+        type = new FunctionType(
+            f.positionalParameters, f.returnType, Nullability.nonNullable,
             namedParameters: f.namedParameters,
             typeParameters: f.typeParameters,
             requiredParameterCount: f.requiredParameterCount,
-            typedefType: def.thisType,
-            nullability: Nullability.nonNullable);
+            typedefType: def.thisType);
       }
     }
     return def..type = type;
@@ -296,10 +295,10 @@
     }
     namedParameters.sort();
     return new FunctionType(positionalParameters, returnType,
+        interpretParsedNullability(node.parsedNullability),
         namedParameters: namedParameters,
         requiredParameterCount: node.arguments.required.length,
-        typeParameters: parameterEnvironment.parameters,
-        nullability: interpretParsedNullability(node.parsedNullability));
+        typeParameters: parameterEnvironment.parameters);
   }
 
   VoidType visitVoidType(ParsedVoidType node, KernelEnvironment environment) {
@@ -316,7 +315,7 @@
     TypeParameterType type =
         node.a.accept<Node, KernelEnvironment>(this, environment);
     DartType bound = node.b.accept<Node, KernelEnvironment>(this, environment);
-    return new TypeParameterType(type.parameter, bound, type.nullability);
+    return new TypeParameterType(type.parameter, type.nullability, bound);
   }
 
   Supertype toSupertype(InterfaceType type) {
@@ -341,7 +340,7 @@
       if (bound == null) {
         typeParameter
           ..bound = new InterfaceType(
-              objectClass, const <DartType>[], Nullability.nullable)
+              objectClass, Nullability.nullable, const <DartType>[])
           ..defaultType = const DynamicType();
       } else {
         DartType type =
diff --git a/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart b/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart
index 4d1aa06..d95d034 100644
--- a/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart
+++ b/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart
@@ -6,7 +6,8 @@
 
 import "package:expect/expect.dart" show Expect;
 
-import "package:kernel/ast.dart" show Class, Component, DartType, InterfaceType;
+import "package:kernel/ast.dart"
+    show Class, Component, DartType, InterfaceType, Nullability;
 
 import "package:kernel/core_types.dart";
 
@@ -82,9 +83,9 @@
     //     {N<C1<String>>, Object} for N<C1<String>> and
     // Object is the most specific type in the intersection of the supertypes.
     checkGetLegacyLeastUpperBound(
-        new InterfaceType(C1, [intType]),
-        new InterfaceType(N, [
-          new InterfaceType(C1, [stringType])
+        new InterfaceType(C1, Nullability.legacy, [intType]),
+        new InterfaceType(N, Nullability.legacy, [
+          new InterfaceType(C1, Nullability.legacy, [stringType])
         ]),
         objectType);
 
@@ -94,9 +95,9 @@
     //     {N<C2<String>>, Object} for N<C2<String>> and
     // Object is the most specific type in the intersection of the supertypes.
     checkGetLegacyLeastUpperBound(
-        new InterfaceType(C2, [intType]),
-        new InterfaceType(N, [
-          new InterfaceType(C2, [stringType])
+        new InterfaceType(C2, Nullability.legacy, [intType]),
+        new InterfaceType(N, Nullability.legacy, [
+          new InterfaceType(C2, Nullability.legacy, [stringType])
         ]),
         objectType);
   }
@@ -119,21 +120,25 @@
     Class f = getClass("F");
 
     checkGetLegacyLeastUpperBound(
-        new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [intType, doubleType]));
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]),
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]),
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]));
     checkGetLegacyLeastUpperBound(
-        new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [intType, boolType]),
-        new InterfaceType(b, [intType]));
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]),
+        new InterfaceType(d, Nullability.legacy, [intType, boolType]),
+        new InterfaceType(b, Nullability.legacy, [intType]));
     checkGetLegacyLeastUpperBound(
-        new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [boolType, doubleType]),
-        new InterfaceType(c, [doubleType]));
-    checkGetLegacyLeastUpperBound(new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [boolType, intType]), coreTypes.legacyRawType(a));
-    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(e),
-        coreTypes.legacyRawType(f), new InterfaceType(b, [intType]));
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]),
+        new InterfaceType(d, Nullability.legacy, [boolType, doubleType]),
+        new InterfaceType(c, Nullability.legacy, [doubleType]));
+    checkGetLegacyLeastUpperBound(
+        new InterfaceType(d, Nullability.legacy, [intType, doubleType]),
+        new InterfaceType(d, Nullability.legacy, [boolType, intType]),
+        coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(
+        coreTypes.legacyRawType(e),
+        coreTypes.legacyRawType(f),
+        new InterfaceType(b, Nullability.legacy, [intType]));
   }
 
   Future<void> test_getLegacyLeastUpperBound_nonGeneric() async {
diff --git a/pkg/front_end/test/fasta/types/shared_type_tests.dart b/pkg/front_end/test/fasta/types/shared_type_tests.dart
index dde84e42..1217c30 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -14,7 +14,7 @@
     T supertype = toType(supertypeString, environment);
     Expect.isTrue(
         isSubtypeImpl(subtype, supertype).isSubtypeWhenUsingNullabilities(),
-        "$subtypeString should be a subtype of $supertypeString.");
+        "$subtypeString should always be a subtype of $supertypeString.");
   }
 
   void isNotSubtype(String subtypeString, String supertypeString,
@@ -24,7 +24,7 @@
     T supertype = toType(supertypeString, environment);
     Expect.isFalse(
         isSubtypeImpl(subtype, supertype).isSubtypeWhenIgnoringNullabilities(),
-        "$subtypeString shouldn't be a subtype of $supertypeString.");
+        "$subtypeString should never be a subtype of $supertypeString.");
   }
 
   /// Checks if a type is a subtype of the other ignoring nullability modifiers.
@@ -33,8 +33,13 @@
     E environment = extend(typeParameters);
     T subtype = toType(subtypeString, environment);
     T supertype = toType(supertypeString, environment);
-    Expect.isTrue(
-        isSubtypeImpl(subtype, supertype).isSubtypeWhenIgnoringNullabilities(),
+    IsSubtypeOf result = isSubtypeImpl(subtype, supertype);
+    Expect.isFalse(
+        result.isSubtypeWhenUsingNullabilities(),
+        "$subtypeString should be a subtype of $supertypeString "
+        "only if the nullability modifiers are ignored.");
+    Expect.isFalse(
+        !result.isSubtypeWhenIgnoringNullabilities(),
         "$subtypeString should be a subtype of $supertypeString "
         "if the nullability modifiers are ignored.");
   }
@@ -135,11 +140,31 @@
     isSubtype('Never', '(int*) -> num*');
     isSubtype('Never', '(int*) ->* num*');
     isSubtype('Never', '(int*) ->? num*');
+    isSubtype('bottom', '(int) -> num');
+    isSubtype('bottom', '(int) ->* num');
+    isSubtype('bottom', '(int) ->? num');
     isSubtype('(num*) ->* num*', 'Object');
     isSubtype('(num*) -> num*', 'Object');
     isObliviousSubtype('(num*) ->? num*', 'Object');
     isObliviousSubtype('Null?', '(int*) -> num*');
     isNotSubtype('(int*) -> num*', 'Never');
+    isNotSubtype('num', '(num) -> num');
+    isNotSubtype('Object', '(num) -> num');
+    isNotSubtype('Object*', '(num) -> num');
+    isNotSubtype('Object?', '(num) -> num');
+    isNotSubtype('dynamic', '(num) -> num');
+
+    isSubtype('(num) -> num', '(num) ->* num');
+    isSubtype('(num) ->* num', '(num) -> num');
+    isSubtype('(num) ->? num', '(num) ->* num');
+    isSubtype('(num) ->* num', '(num) ->? num');
+    isSubtype('(num) -> num', '(num) ->? num');
+    isObliviousSubtype('(num) ->? num', '(num) -> num');
+
+    isSubtype('(num) -> num', '(num) -> num?');
+    isSubtype('(num?) -> num', '(num) -> num');
+    isSubtype('(num?) -> num', '(num) -> num?');
+    isObliviousSubtype('(num) -> num', '(num?) -> num?');
 
     // Tests for non-generic two-argument curried function types.
     isSubtype('(num*) ->* (num*) ->* num*', '(num*) ->* (int*) ->* num*');
@@ -151,6 +176,18 @@
     isSubtype('({num* x}) ->* int*', '({num* x}) ->* num*');
     isNotSubtype('({int* x}) ->* int*', '({num* x}) ->* num*');
 
+    isSubtype('({num x}) -> num', '({num x}) -> num?');
+    isSubtype('({num? x}) -> num', '({num x}) -> num');
+    isSubtype('({num? x}) -> num', '({num x}) -> num?');
+    isObliviousSubtype('({num x}) -> num', '({num? x}) -> num?');
+
+    // Tests for non-generic one-argument function types with optional
+    // positional parameters.
+    isSubtype('([num]) -> num', '([num]) -> num?');
+    isSubtype('([num?]) -> num', '([num]) -> num');
+    isSubtype('([num?]) -> num', '([num]) -> num?');
+    isObliviousSubtype('([num]) -> num', '([num?]) -> num?');
+
     // Tests for function types with type parameters.
     isSubtype('<E>(E) ->* int*', '<E>(E) ->* num*');
     isSubtype('<E>(num*) ->* E', '<E>(int*) ->* E');
@@ -190,6 +227,12 @@
     isNotSubtype(
         '<E>(E,List<Object*>*) ->* E', '<F extends List<F*>*>(F*,F*) ->* void');
 
+    isSubtype('<E extends num>(E) -> E', '<F extends num*>(F*) -> F*');
+    isSubtype('<E extends num*>(E*) -> E*', '<F extends num>(F) -> F');
+    isSubtype('<E extends num?>(E) -> E', '<F extends num*>(F*) -> F*');
+    isSubtype('<E extends num*>(E*) -> E*', '<F extends num?>(F) -> F');
+    isObliviousSubtype('<E extends num>(E) -> E', '<F extends num?>(F) -> F');
+
     // Tests for FutureOr.
     isSubtype('int*', 'FutureOr<int*>*');
     isSubtype('int*', 'FutureOr<num*>*');
@@ -199,6 +242,48 @@
     isSubtype('FutureOr<int*>*', 'FutureOr<int*>*');
     isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
     isSubtype('FutureOr<int*>*', 'Object*');
+    isSubtype('Null?', 'FutureOr<num?>');
+    isSubtype('Null?', 'FutureOr<num>?');
+    isSubtype('num?', 'FutureOr<num?>');
+    isSubtype('num?', 'FutureOr<num>?');
+    isSubtype('Future<num>', 'FutureOr<num?>');
+    isSubtype('Future<num>', 'FutureOr<num>?');
+    isSubtype('Future<num>', 'FutureOr<num?>?');
+    isSubtype('Future<num?>', 'FutureOr<num?>');
+    isObliviousSubtype('Future<num?>', 'FutureOr<num>?');
+    isSubtype('Future<num?>', 'FutureOr<num?>?');
+
+    isSubtype('num?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype('Future<num>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype('Future<Future<num>>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype(
+        'Future<Future<Future<num>>>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
+    isSubtype('Future<num>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype('Future<Future<num>>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype(
+        'Future<Future<Future<num>>>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype('Future<num?>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype('Future<Future<num?>?>?', 'FutureOr<FutureOr<FutureOr<num?>>>');
+    isSubtype('Future<Future<Future<num?>?>?>?',
+        'FutureOr<FutureOr<FutureOr<num?>>>');
+
+    isSubtype('FutureOr<num>?', 'FutureOr<num?>');
+    isObliviousSubtype('FutureOr<num?>', 'FutureOr<num>?');
+
+    isSubtype('dynamic', 'FutureOr<Object?>');
+    isSubtype('dynamic', 'FutureOr<Object>?');
+    isSubtype('void', 'FutureOr<Object?>');
+    isSubtype('void', 'FutureOr<Object>?');
+    isSubtype('Object*', 'FutureOr<Object?>');
+    isSubtype('Object*', 'FutureOr<Object>?');
+    isSubtype('Object?', 'FutureOr<Object?>');
+    isSubtype('Object?', 'FutureOr<Object>?');
+    isSubtype('Object', 'FutureOr<Object?>');
+    isSubtype('Object', 'FutureOr<Object>?');
+    isObliviousSubtype('dynamic', 'FutureOr<Object>');
+    isObliviousSubtype('void', 'FutureOr<Object>');
+    isObliviousSubtype('Object?', 'FutureOr<Object>');
+    isSubtype('Object', 'FutureOr<Object>');
 
     isSubtype('FutureOr<int>', 'Object');
     isSubtype('FutureOr<int>', 'Object*');
@@ -232,15 +317,87 @@
     isNotSubtype('dynamic', 'FutureOr<String*>*');
     isSubtype('void', 'FutureOr<void>*');
     isNotSubtype('void', 'FutureOr<String*>*');
-    isSubtype('E', 'FutureOr<E>*', typeParameters: 'E');
-    isNotSubtype('E', 'FutureOr<String*>*', typeParameters: 'E');
+
+    isSubtype('E*', 'FutureOr<E*>*', typeParameters: 'E extends Object*');
+    isSubtype('E?', 'FutureOr<E>?', typeParameters: 'E extends Object');
+    isSubtype('E?', 'FutureOr<E?>', typeParameters: 'E extends Object');
+    isSubtype('E', 'FutureOr<E>?', typeParameters: 'E extends Object?');
+    isSubtype('E', 'FutureOr<E?>', typeParameters: 'E extends Object?');
+    isObliviousSubtype('E?', 'FutureOr<E>', typeParameters: 'E extends Object');
+    isSubtype('E', 'FutureOr<E>', typeParameters: 'E extends Object?');
+    isNotSubtype('E*', 'FutureOr<String*>*',
+        typeParameters: 'E extends Object*');
+    isSubtype('E?', 'FutureOr<String>?', typeParameters: 'E extends String');
+    isSubtype('E?', 'FutureOr<String?>', typeParameters: 'E extends String');
+    isSubtype('E', 'FutureOr<String>?', typeParameters: 'E extends String?');
+    isSubtype('E', 'FutureOr<String?>', typeParameters: 'E extends String?');
+    isObliviousSubtype('E?', 'FutureOr<String>',
+        typeParameters: 'E extends String');
+    isObliviousSubtype('E', 'FutureOr<String>',
+        typeParameters: 'E extends String?');
+
     isSubtype('() ->* String*', 'FutureOr<() ->* void>*');
+    isSubtype('() -> String', 'FutureOr<() -> void>');
+    isSubtype('() -> String', 'FutureOr<() ->? void>');
+    isSubtype('() -> String', 'FutureOr<() -> void>?');
+    isSubtype('() ->? String', 'FutureOr<() ->? void>');
+    isSubtype('() ->? String', 'FutureOr<() -> void>?');
+    isObliviousSubtype('() ->? String', 'FutureOr<() -> void>');
+    isObliviousSubtype('() ->? String', 'FutureOr<() -> void>');
     isNotSubtype('() ->* void', 'FutureOr<() ->* String>*');
     isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
     isNotSubtype('FutureOr<num*>*', 'FutureOr<int*>*');
-    isSubtype('T & int*', 'FutureOr<num*>*', typeParameters: 'T');
-    isSubtype('T & Future<num*>*', 'FutureOr<num*>*', typeParameters: 'T');
-    isSubtype('T & Future<int*>*', 'FutureOr<num*>*', typeParameters: 'T');
+
+    isSubtype('T* & int*', 'FutureOr<num*>*',
+        typeParameters: 'T extends Object*');
+    isSubtype('T & int', 'FutureOr<num>', typeParameters: 'T extends Object');
+    isSubtype('T & int', 'FutureOr<num?>', typeParameters: 'T extends Object');
+    isSubtype('T & int', 'FutureOr<num>?', typeParameters: 'T extends Object');
+    isSubtype('T & int', 'FutureOr<num>', typeParameters: 'T extends Object?');
+    isSubtype('T & int', 'FutureOr<num?>', typeParameters: 'T extends Object?');
+    isSubtype('T & int', 'FutureOr<num>?', typeParameters: 'T extends Object?');
+    isObliviousSubtype('T & int?', 'FutureOr<num>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & int?', 'FutureOr<num?>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & int?', 'FutureOr<num>?',
+        typeParameters: 'T extends Object?');
+    isObliviousSubtype('T & S', 'FutureOr<Object>',
+        typeParameters: 'T extends Object?, S extends T');
+    isSubtype('T & S', 'FutureOr<Object?>',
+        typeParameters: 'T extends Object?, S extends T');
+    isSubtype('T & S', 'FutureOr<Object>?',
+        typeParameters: 'T extends Object?, S extends T');
+
+    isSubtype('T* & Future<num*>*', 'FutureOr<num*>*',
+        typeParameters: 'T extends Object*');
+    isSubtype('T* & Future<int*>*', 'FutureOr<num*>*',
+        typeParameters: 'T extends Object*');
+    isSubtype('T & Future<int>', 'FutureOr<num>',
+        typeParameters: 'T extends Object');
+    isSubtype('T & Future<int>', 'FutureOr<num?>',
+        typeParameters: 'T extends Object');
+    isSubtype('T & Future<int>', 'FutureOr<num>?',
+        typeParameters: 'T extends Object');
+    isSubtype('T & Future<int>', 'FutureOr<num>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & Future<int>', 'FutureOr<num?>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & Future<int>', 'FutureOr<num>?',
+        typeParameters: 'T extends Object?');
+    isObliviousSubtype('T & Future<int>?', 'FutureOr<num>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & Future<int>?', 'FutureOr<num?>',
+        typeParameters: 'T extends Object?');
+    isSubtype('T & Future<int>?', 'FutureOr<num>?',
+        typeParameters: 'T extends Object?');
+    isObliviousSubtype('T & Future<int?>', 'FutureOr<num>',
+        typeParameters: 'T extends Object');
+    isSubtype('T & Future<int?>', 'FutureOr<num?>',
+        typeParameters: 'T extends Object');
+    isObliviousSubtype('T & Future<int?>', 'FutureOr<num>?',
+        typeParameters: 'T extends Object');
+
     if (!skipFutureOrPromotion) {
       isSubtype('T & FutureOr<int*>*', 'FutureOr<num*>*', typeParameters: 'T');
       isSubtype('T & FutureOr<num*>*', 'FutureOr<num*>*', typeParameters: 'T');
@@ -252,6 +409,8 @@
           typeParameters: 'T extends FutureOr<int*>*');
       isSubtype('T* & FutureOr<String*>*', 'FutureOr<num*>*',
           typeParameters: 'T extends FutureOr<num*>*');
+      isNotSubtype('FutureOr<num>', 'T & FutureOr<num>',
+          typeParameters: 'T extends FutureOr<num>');
     }
     isNotSubtype('T & num*', 'FutureOr<int*>*', typeParameters: 'T');
     isNotSubtype('T & Future<num*>*', 'FutureOr<int*>*', typeParameters: 'T');
@@ -262,8 +421,17 @@
         typeParameters: 'T extends Future<num*>*');
     isNotSubtype('T* & FutureOr<String*>*', 'FutureOr<int*>*',
         typeParameters: 'T extends FutureOr<num*>*');
+
     isSubtype('Id<int*>*', 'FutureOr<num*>*');
+    isSubtype('Id<int>', 'FutureOr<num>');
+    isObliviousSubtype('Id<int?>', 'FutureOr<num>');
+    isSubtype('Id<int?>', 'FutureOr<num?>');
+    isSubtype('Id<int?>', 'FutureOr<num>?');
+    isObliviousSubtype('Id<int>?', 'FutureOr<num>');
+    isSubtype('Id<int>?', 'FutureOr<num?>');
+    isSubtype('Id<int>?', 'FutureOr<num>?');
     isNotSubtype('Id<num*>*', 'FutureOr<int*>*');
+
     isSubtype('FutureOr<Object*>*', 'FutureOr<FutureOr<Object*>*>*');
     isSubtype('FutureOr<num>*', 'Object');
     isSubtype('FutureOr<num>', 'Object');
@@ -287,6 +455,7 @@
     isNotSubtype('T* & num*', 'Never', typeParameters: 'T extends Object*');
     isSubtype('T', 'Never', typeParameters: 'T extends Never');
     isSubtype('T & Never', 'Never', typeParameters: 'T extends Object');
+    isSubtype('bottom', 'T & int', typeParameters: 'T extends Object');
 
     // Testing bottom types against type-parameter types.
     isSubtype('Null?', 'T?', typeParameters: 'T extends Object');
@@ -311,10 +480,16 @@
 
     // Trivial tests for type-parameter types and intersection types.
     // T & B <: T & A if B <: A
-    isSubtype('T & int*', 'T & int*', typeParameters: 'T');
-    isSubtype('T & int*', 'T & num*', typeParameters: 'T');
-    isSubtype('T & num*', 'T & num*', typeParameters: 'T');
-    isNotSubtype('T & num*', 'T & int*', typeParameters: 'T');
+    isSubtype('T* & int*', 'T* & int*', typeParameters: 'T extends Object*');
+    isSubtype('T* & int*', 'T* & num*', typeParameters: 'T extends Object*');
+    isSubtype('T* & num*', 'T* & num*', typeParameters: 'T extends Object*');
+    isNotSubtype('T* & num*', 'T* & int*', typeParameters: 'T extends Object*');
+
+    isSubtype('T & int', 'T & num', typeParameters: 'T extends Object');
+    isSubtype('T & int', 'T & num', typeParameters: 'T extends Object?');
+    isSubtype('T & int?', 'T & num?', typeParameters: 'T extends Object?');
+    isObliviousSubtype('T & int?', 'T & num',
+        typeParameters: 'T extends Object?');
 
     // T & B <: T extends A if B <: A
     // (Trivially satisfied since promoted bounds are always a isSubtype of the
@@ -325,12 +500,34 @@
 
     // T extends B <: T & A if B <: A
     isSubtype('T*', 'T* & int*', typeParameters: 'T extends int*');
+    isSubtype('T', 'T & int', typeParameters: 'T extends int');
+    isObliviousSubtype('T?', 'T & int', typeParameters: 'T extends int');
+    isObliviousSubtype('T', 'T & int', typeParameters: 'T extends int?');
+    isSubtype('T', 'T & int?', typeParameters: 'T extends int?');
+    isObliviousSubtype('T?', 'T & int?', typeParameters: 'T extends int?');
+
     isSubtype('T*', 'T* & num*', typeParameters: 'T extends int*');
+    isSubtype('T', 'T & num', typeParameters: 'T extends int');
+    isObliviousSubtype('T?', 'T & num', typeParameters: 'T extends int');
+    isObliviousSubtype('T', 'T & num', typeParameters: 'T extends int?');
+    isSubtype('T', 'T & num?', typeParameters: 'T extends int?');
+    isObliviousSubtype('T?', 'T & num?', typeParameters: 'T extends int?');
+
     isSubtype('T*', 'T* & num*', typeParameters: 'T extends num*');
+    isSubtype('T', 'T & num', typeParameters: 'T extends num');
+    isObliviousSubtype('T?', 'T & num', typeParameters: 'T extends num');
+    isObliviousSubtype('T', 'T & num', typeParameters: 'T extends num?');
+    isSubtype('T', 'T & num?', typeParameters: 'T extends num?');
+    isObliviousSubtype('T?', 'T & num?', typeParameters: 'T extends num?');
+
     isNotSubtype('T*', 'T* & int*', typeParameters: 'T extends num*');
 
     // T extends A <: T extends A
     isSubtype('T*', 'T*', typeParameters: 'T extends num*');
+    isSubtype('T', 'T', typeParameters: 'T extends num');
+    isSubtype('T', 'T', typeParameters: 'T extends num?');
+    isSubtype('T?', 'T?', typeParameters: 'T extends num');
+    isSubtype('T?', 'T?', typeParameters: 'T extends num?');
 
     isSubtype('T', 'T', typeParameters: 'T');
     isNotSubtype('S', 'T', typeParameters: 'S, T');
@@ -345,7 +542,46 @@
 
     // S <: T extends S
     isNotSubtype('S', 'T', typeParameters: 'S, T extends S');
-    isObliviousSubtype('T', 'S', typeParameters: 'S, T extends S');
+    isSubtype('T*', 'S*', typeParameters: 'S extends Object*, T extends S*');
+
+    isSubtype('T', 'S', typeParameters: 'S extends Object, T extends S');
+    isSubtype('T', 'S?', typeParameters: 'S extends Object, T extends S');
+    isObliviousSubtype('T?', 'S',
+        typeParameters: 'S extends Object, T extends S');
+    isSubtype('T?', 'S?', typeParameters: 'S extends Object, T extends S');
+
+    isSubtype('T', 'S', typeParameters: 'S extends Object?, T extends S');
+    isSubtype('T', 'S?', typeParameters: 'S extends Object?, T extends S');
+    isObliviousSubtype('T?', 'S',
+        typeParameters: 'S extends Object?, T extends S');
+    isSubtype('T?', 'S?', typeParameters: 'S extends Object?, T extends S');
+
+    isObliviousSubtype('T', 'S',
+        typeParameters: 'S extends Object?, T extends S?');
+    isSubtype('T', 'S?', typeParameters: 'S extends Object?, T extends S?');
+    isObliviousSubtype('T?', 'S',
+        typeParameters: 'S extends Object?, T extends S?');
+    isSubtype('T?', 'S?', typeParameters: 'S extends Object?, T extends S?');
+
+    isObliviousSubtype('T', 'S',
+        typeParameters: 'S extends Object, T extends S?');
+    isSubtype('T', 'S?', typeParameters: 'S extends Object, T extends S?');
+    isObliviousSubtype('T?', 'S',
+        typeParameters: 'S extends Object, T extends S?');
+    isSubtype('T?', 'S?', typeParameters: 'S extends Object, T extends S?');
+
+    isSubtype('T* & V*', 'S*',
+        typeParameters: 'S extends Object*, T extends S*, V extends S*');
+    isSubtype('T & V', 'S',
+        typeParameters: 'S extends Object, T extends S, V extends S');
+    isSubtype('T & V?', 'S?',
+        typeParameters: 'S extends Object, T extends S, V extends S');
+    isSubtype('T & V', 'S',
+        typeParameters: 'S extends Object?, T extends S, V extends S');
+    isSubtype('T & V', 'S',
+        typeParameters: 'S extends Object?, T extends S?, V extends S');
+    isObliviousSubtype('T & V', 'S',
+        typeParameters: 'S extends Object?, T extends S?, V extends S?');
 
     // Non-trivial tests for intersection types.
     // S & B <: A if B <: A, A is not S (or a promotion thereof)
@@ -564,6 +800,9 @@
     isNotSubtype('T & (void) ->* void', '(int*) ->* int*', typeParameters: 'T');
 
     isSubtype('T*', '() ->* void', typeParameters: 'T extends () ->* void');
+    isSubtype('T', '() -> void', typeParameters: 'T extends () -> void');
+    isObliviousSubtype('T?', '() -> void',
+        typeParameters: 'T extends () -> void');
     isNotSubtype('T', '() ->* void', typeParameters: 'T');
     isNotSubtype('Typedef<void>*', '() ->* void');
     isSubtype('VoidFunction*', '() ->* void');
@@ -586,7 +825,17 @@
     // Tests for checking typedef types against other kinds of types.
     isSubtype('dynamic', 'Id<dynamic>*');
     isNotSubtype('dynamic', 'Id<int*>*');
+
     isSubtype('() ->* void', 'Id<() ->* void>*');
+    isSubtype('() -> void', 'Id<() -> void>');
+    isSubtype('() -> void', 'Id<() ->? void>');
+    isSubtype('() ->? void', 'Id<() ->? void>');
+    isSubtype('() ->? void', 'Id<() -> void>?');
+    isSubtype('() ->? void', 'Id<() ->? void>?');
+    isSubtype('() -> void', 'VoidFunction');
+    isSubtype('() -> void', 'VoidFunction?');
+    isSubtype('() ->? void', 'VoidFunction?');
+
     isNotSubtype('() ->* void', 'Id<() ->* int>*');
     isNotSubtype('FutureOr<() ->* void>*', 'Id<() ->* void>*');
     isSubtype('FutureOr<() ->* void>*', 'Id<FutureOr<() ->* void>*>*');
@@ -639,17 +888,47 @@
     isNotSubtype('T & (void) ->* void', 'Id<(int*) ->* int*>*',
         typeParameters: 'T');
     isNotSubtype('dynamic', 'T & dynamic', typeParameters: 'T extends dynamic');
-    isNotSubtype('() ->* T', 'T & () ->* T', typeParameters: 'T');
+    isNotSubtype('() ->* T*', 'T* & () ->* T*',
+        typeParameters: 'T extends Object*');
 
     isNotSubtype('FutureOr<T & String*>*', 'T & String*', typeParameters: 'T');
 
-    isSubtype('Id<T & String*>*', 'T & String*', typeParameters: 'T');
-    isSubtype('Id<T & String*>*', 'T', typeParameters: 'T');
-    isSubtype('Id<T & String*>*', 'String*', typeParameters: 'T');
+    isSubtype('Id<T* & String*>*', 'T* & String*',
+        typeParameters: 'T extends Object*');
+    isSubtype('Id<T & String>', 'T & String',
+        typeParameters: 'T extends Object');
+    isSubtype('Id<T & String>', 'T & String',
+        typeParameters: 'T extends Object?');
+    isSubtype('Id<T & String?>', 'T & String?',
+        typeParameters: 'T extends Object?');
+    isSubtype('Id<T & String>', 'T & String?',
+        typeParameters: 'T extends Object?');
+    isObliviousSubtype('Id<T & String?>', 'T & String',
+        typeParameters: 'T extends Object?');
+    // TODO(dmitryas): Uncomment the following.
+    //isObliviousSubtype('Id<T & String>?', 'T & String', typeParameters: 'T extends Object');
+    //isObliviousSubtype('Id<T & String>?', 'T & String?', typeParameters: 'T extends Object');
+
+    isSubtype('Id<T* & String*>*', 'T*', typeParameters: 'T extends Object*');
+    isSubtype('Id<T & String>', 'T', typeParameters: 'T extends Object');
+    isSubtype('Id<T & String>', 'T?', typeParameters: 'T extends Object');
+    isSubtype('Id<T & String>', 'T', typeParameters: 'T extends Object?');
+    isSubtype('Id<T & String?>', 'T', typeParameters: 'T extends Object?');
+    // TODO(dmitryas): Uncomment the following.
+    //isSubtype('Id<T & String>?', 'T?', typeParameters: 'T extends Object?');
+
+    isSubtype('Id<T* & String*>*', 'String*',
+        typeParameters: 'T extends Object*');
     isNotSubtype('Id<T & String*>*', 'S & String*', typeParameters: 'T, S');
 
-    isNotSubtype('void', 'T & void', typeParameters: 'T');
+    isNotSubtype('void', 'T* & void', typeParameters: 'T extends Object*');
     isNotSubtype('void', 'T & void', typeParameters: 'T extends void');
+    isNotSubtype('Object', 'T & Object', typeParameters: 'T extends Object');
+    isNotSubtype('Object?', 'T & Object', typeParameters: 'T extends Object?');
+    isNotSubtype('Object?', 'T & Object?', typeParameters: 'T extends Object?');
+    isNotSubtype('Object*', 'T & Object*', typeParameters: 'T extends Object*');
+    isNotSubtype('num', 'T & num', typeParameters: 'T extends num');
+    isNotSubtype('FutureOr<num>', 'T & num', typeParameters: 'T extends num');
 
     isSubtype('T', 'Id<T>*', typeParameters: 'T');
     isSubtype('T', 'Id<Object*>*', typeParameters: 'T');
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
deleted file mode 100644
index c3df660..0000000
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler;
-
-import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
-
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
-    show Token, scanString;
-
-import 'package:expect/expect.dart' show Expect;
-
-import 'package:kernel/ast.dart' show Expression, ProcedureKind;
-
-import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
-
-import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/fasta/builder/procedure_builder.dart';
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
-
-import 'package:front_end/src/fasta/kernel/body_builder.dart' show BodyBuilder;
-
-import 'package:front_end/src/fasta/kernel/kernel_target.dart'
-    show KernelTarget;
-
-import 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
-    show UnlinkedScope;
-
-import 'package:front_end/src/fasta/scope.dart' show Scope;
-
-import 'package:front_end/src/fasta/source/source_library_builder.dart'
-    show SourceLibraryBuilder;
-
-DiagnosticMessageHandler handler;
-
-class MockLibraryBuilder extends SourceLibraryBuilder {
-  MockLibraryBuilder(Uri uri)
-      : super(
-            uri,
-            uri,
-            new KernelTarget(
-                    null,
-                    false,
-                    new DillTarget(
-                        null, null, new NoneTarget(new TargetFlags())),
-                    null)
-                .loader,
-            null);
-
-  ProcedureBuilder mockProcedure(String name) {
-    return new ProcedureBuilderImpl(null, 0, null, name, null, null,
-        ProcedureKind.Getter, this, -1, -1, -1, -1);
-  }
-}
-
-class MockBodyBuilder extends BodyBuilder {
-  MockBodyBuilder.internal(
-      MockLibraryBuilder libraryBuilder, String name, Scope scope)
-      : super(
-            libraryBuilder: libraryBuilder,
-            member: libraryBuilder.mockProcedure(name),
-            enclosingScope: scope,
-            formalParameterScope: scope,
-            isDeclarationInstanceMember: false,
-            uri: libraryBuilder.uri);
-
-  MockBodyBuilder(Uri uri, String name, Scope scope)
-      : this.internal(new MockLibraryBuilder(uri), name, scope);
-}
-
-Expression compileExpression(String source) {
-  BodyBuilder listener = new MockBodyBuilder(
-      Uri.parse("org-dartlang-test:my_library.dart"),
-      "<test>",
-      new UnlinkedScope());
-
-  handler = (DiagnosticMessage message) {
-    throw message.plainTextFormatted.join("\n");
-  };
-
-  Token token = scanString(source).tokens;
-  Parser parser = new Parser(listener);
-  parser.parseExpression(parser.syntheticPreviousToken(token));
-  Expression e = listener.popForValue();
-  listener.checkEmpty(-1);
-  return e;
-}
-
-void testExpression(String source, [String expected]) {
-  Expression e = compileExpression(source);
-  String actual =
-      "$e".replaceAll(new RegExp(r'invalid-expression "[^"]*"\.'), "");
-  Expect.stringEquals(expected ?? source, actual);
-  print(e);
-}
-
-main() {
-  CompilerContext context = new CompilerContext(new ProcessedOptions(
-      options: new CompilerOptions()
-        ..onDiagnostic = (DiagnosticMessage message) {
-          handler(message);
-        }));
-  context.runInContext((_) {
-    testExpression("unresolved");
-    testExpression("a + b", "a.+(b)");
-    testExpression("a = b");
-    return Future<void>.value();
-  });
-}
diff --git a/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart b/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
index 167365c..2bdb277 100644
--- a/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
+++ b/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
@@ -10,8 +10,6 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag;
 import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
 
@@ -28,10 +26,8 @@
       supportedMarkers: sharedMarkers,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const AssignedVariablesDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe with nnbd',
-            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
-      ]),
+      runTest: runTestFor(
+          const AssignedVariablesDataComputer(), [cfeNonNullableOnlyConfig]),
       skipList: [
         'for.dart',
         'for_element.dart',
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart b/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
index 939b23d..7fa9e26 100644
--- a/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
+++ b/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
@@ -7,9 +7,6 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag;
-
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/fasta/builder/member_builder.dart';
@@ -25,24 +22,14 @@
       supportedMarkers: sharedMarkers,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const DefiniteAssignmentDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe with nnbd',
-            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
-      ]),
+      runTest: runTestFor(
+          const DefiniteAssignmentDataComputer(), [cfeNonNullableOnlyConfig]),
       skipList: [
-        // TODO(dmitryas): Run all definite assignment tests.
-        'assert.dart',
-        'assignment.dart',
-        'binary_expression.dart',
-        'conditional_expression.dart',
+        // TODO(johnniwinther): Update break/continue handling to support these:
         'do.dart',
         'for.dart',
         'for_each.dart',
-        'function_expression.dart',
-        'if.dart',
-        'initialization.dart',
         'switch.dart',
-        'try.dart',
         'while.dart',
       ]);
 }
@@ -76,7 +63,7 @@
   @override
   String computeNodeValue(Id id, TreeNode node) {
     if (node is VariableGet) {
-      if (_flowResult.unassignedNodes.contains(node.variable)) {
+      if (_flowResult.unassignedNodes.contains(node)) {
         return 'unassigned';
       }
     }
diff --git a/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart b/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
index 2f9f044..c5473b0 100644
--- a/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
+++ b/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
@@ -7,9 +7,6 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag;
-
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:kernel/ast.dart' hide Variance;
 
@@ -21,19 +18,11 @@
       supportedMarkers: sharedMarkers,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const NullabilityDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe with nnbd',
-            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
-      ]),
+      runTest: runTestFor(
+          const NullabilityDataComputer(), [cfeNonNullableOnlyConfig]),
       skipList: [
-        // TODO(dmitryas): Run all nullability tests.
-        'assign.dart',
-        'if.dart',
-        'is.dart',
-        'logical.dart',
+        // TODO(johnniwinther): Run all nullability tests.
         'null_aware_access.dart',
-        'null_check.dart',
-        'potentially_mutated_in_closure.dart',
         'try_finally.dart',
         'while.dart',
       ]);
diff --git a/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart b/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
index 7397b38..634b4df 100644
--- a/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
+++ b/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
@@ -7,9 +7,6 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag;
-
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/fasta/builder/member_builder.dart';
@@ -24,10 +21,8 @@
       supportedMarkers: sharedMarkers,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const ReachabilityDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe with nnbd',
-            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
-      ]));
+      runTest: runTestFor(
+          const ReachabilityDataComputer(), [cfeNonNullableOnlyConfig]));
 }
 
 class ReachabilityDataComputer
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart b/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
index 68b4e14..cfaf1e5 100644
--- a/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
+++ b/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
-import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag;
-
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
@@ -23,34 +20,17 @@
       supportedMarkers: sharedMarkers,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const TypePromotionDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe with nnbd',
-            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
-      ]),
+      runTest: runTestFor(
+          const TypePromotionDataComputer(), [cfeNonNullableOnlyConfig]),
       skipList: [
-        // TODO(dmitryas): Run all type promotion tests.
-        'as.dart',
-        'assert.dart',
-        'assignment.dart',
+        // TODO(johnniwinther): Run all type promotion tests.
         'assignment_promoted.dart',
-        'assigned_anywhere.dart',
-        'binary.dart',
         'bug39178.dart',
-        'conditional.dart',
         'constructor_initializer.dart',
-        'do.dart',
         'for.dart',
-        'function_expression.dart',
-        'if.dart',
-        'initialization.dart',
-        'inside_closure.dart',
         'not_promoted.dart',
         'null_aware_assignment.dart',
-        'null_check.dart',
-        'potentially_mutated.dart',
         'switch.dart',
-        'try_catch.dart',
-        'try_catch_finally.dart',
         'try_finally.dart',
         'type_parameter.dart',
         'while.dart',
@@ -94,7 +74,7 @@
 
   @override
   String getText(DartType actualData) =>
-      typeToText(actualData, isNonNullableByDefault: true);
+      typeToText(actualData, TypeRepresentation.nonNullableByDefault);
 
   @override
   String isAsExpected(DartType actualData, String expectedData) {
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
new file mode 100644
index 0000000..4a703f2
--- /dev/null
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' show Directory, Platform;
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart';
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script
+      .resolve('../../../_fe_analyzer_shared/test/inheritance/data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkersWithNnbd,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(
+          const InheritanceDataComputer(), [cfeNonNullableOnlyConfig]));
+}
+
+class InheritanceDataComputer extends DataComputer<String> {
+  const InheritanceDataComputer();
+
+  /// Function that computes a data mapping for [library].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeLibraryData(InternalCompilerResult compilerResult,
+      Library library, Map<Id, ActualData<String>> actualMap,
+      {bool verbose}) {
+    new InheritanceDataExtractor(compilerResult, actualMap)
+        .computeForLibrary(library);
+  }
+
+  @override
+  void computeClassData(InternalCompilerResult compilerResult, Class cls,
+      Map<Id, ActualData<String>> actualMap,
+      {bool verbose}) {
+    new InheritanceDataExtractor(compilerResult, actualMap)
+        .computeForClass(cls);
+  }
+
+  @override
+  bool get supportsErrors => true;
+
+  @override
+  String computeErrorData(
+      InternalCompilerResult compiler, Id id, List<FormattedMessage> errors) {
+    return errorsToText(errors, useCodes: true);
+  }
+
+  @override
+  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+}
+
+class InheritanceDataExtractor extends CfeDataExtractor<String> {
+  final ClassHierarchy _hierarchy;
+
+  InheritanceDataExtractor(InternalCompilerResult compilerResult,
+      Map<Id, ActualData<String>> actualMap)
+      : _hierarchy = compilerResult.classHierarchy,
+        super(compilerResult, actualMap);
+
+  @override
+  String computeLibraryValue(Id id, Library node) {
+    return 'nnbd=${node.isNonNullableByDefault}';
+  }
+
+  @override
+  String computeClassValue(Id id, Class node) {
+    List<String> supertypes = <String>[];
+    for (Class superclass in computeAllSuperclasses(node)) {
+      supertypes.add(supertypeToText(
+          _hierarchy.getClassAsInstanceOf(node, superclass),
+          TypeRepresentation.implicitUndetermined));
+    }
+    supertypes.sort();
+    return supertypes.join(',');
+  }
+}
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 82ed6bd..48a4d48 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -14,7 +14,8 @@
 import 'package:expect/expect.dart' show Expect;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
+    show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
 
 import "package:front_end/src/api_prototype/memory_file_system.dart"
     show MemoryFileSystem;
@@ -76,7 +77,7 @@
 
 Future<Context> createContext(
     Chain suite, Map<String, String> environment) async {
-  return new Context();
+  return new Context(environment["updateExpectations"] == "true");
 }
 
 class Context extends ChainContext {
@@ -85,6 +86,9 @@
     const RunCompilations(),
   ];
 
+  final bool updateExpectations;
+  Context(this.updateExpectations);
+
   @override
   Future<void> cleanUp(TestDescription description, Result result) async {
     await cleanupHelper?.outDir?.delete(recursive: true);
@@ -96,6 +100,7 @@
 class TestData {
   YamlMap map;
   Directory outDir;
+  Uri loadedFrom;
 }
 
 class ReadTest extends Step<TestDescription, TestData, Context> {
@@ -108,6 +113,7 @@
     Uri uri = description.uri;
     String contents = await new File.fromUri(uri).readAsString();
     TestData data = new TestData();
+    data.loadedFrom = uri;
     data.map = loadYamlNode(contents, sourceUrl: uri);
     data.outDir =
         Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
@@ -144,6 +150,8 @@
           "incrementalSerialization"
         ]);
         await newWorldTest(
+          data,
+          context,
           map["worlds"],
           map["modules"],
           map["omitPlatform"],
@@ -286,8 +294,14 @@
   return moduleResult;
 }
 
-Future<Null> newWorldTest(List worlds, Map modules, bool omitPlatform,
-    String targetName, bool incrementalSerialization) async {
+Future<Null> newWorldTest(
+    TestData data,
+    Context context,
+    List worlds,
+    Map modules,
+    bool omitPlatform,
+    String targetName,
+    bool incrementalSerialization) async {
   final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
   final Uri base = Uri.parse("org-dartlang-test:///");
   final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
@@ -400,6 +414,12 @@
       options.sdkRoot = null;
       options.sdkSummary = sdkSummary;
       options.omitPlatform = omitPlatform != false;
+      if (world["experiments"] != null) {
+        Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
+            parseExperimentalArguments([world["experiments"]]),
+            onError: (e) => throw "Error on parsing experiments flags: $e");
+        options.experimentalFlags = experimentalFlags;
+      }
     }
     if (packagesUri != null) {
       options.packagesFileUri = packagesUri;
@@ -502,7 +522,8 @@
     performErrorAndWarningCheck(
         world, gotError, formattedErrors, gotWarning, formattedWarnings);
     util.throwOnEmptyMixinBodies(component);
-    util.throwOnInsufficientUriToSource(component);
+    await util.throwOnInsufficientUriToSource(component,
+        fileSystem: gotError ? null : fs);
     print("Compile took ${stopwatch.elapsedMilliseconds} ms");
 
     checkExpectedContent(world, component);
@@ -528,8 +549,9 @@
 
     newestWholeComponentData = util.postProcess(component);
     newestWholeComponent = component;
+    String actualSerialized = componentToStringSdkFiltered(component);
     print("*****\n\ncomponent:\n"
-        "${componentToStringSdkFiltered(component)}\n\n\n");
+        "${actualSerialized}\n\n\n");
 
     if (world["uriToSourcesDoesntInclude"] != null) {
       for (String filename in world["uriToSourcesDoesntInclude"]) {
@@ -557,6 +579,24 @@
       }
     }
 
+    Uri uri = data.loadedFrom
+        .resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect");
+    String expected;
+    File file = new File.fromUri(uri);
+    if (context.updateExpectations) {
+      file.writeAsStringSync(actualSerialized);
+    }
+    if (file.existsSync()) {
+      expected = file.readAsStringSync();
+    }
+    if (context.updateExpectations) {
+      file.writeAsStringSync(actualSerialized);
+    } else if (expected != actualSerialized) {
+      throw "Unexpected serialized representation. "
+          "Fix or update $uri to contain the below:\n\n"
+          "$actualSerialized";
+    }
+
     int nonSyntheticLibraries = countNonSyntheticLibraries(component);
     int nonSyntheticPlatformLibraries =
         countNonSyntheticPlatformLibraries(component);
@@ -588,6 +628,7 @@
             "libraries, got ${syntheticLibraries}";
       }
     }
+
     if (!noFullComponent) {
       List<Library> entryLib = component.libraries
           .where((Library lib) =>
@@ -708,7 +749,7 @@
       performErrorAndWarningCheck(
           world, gotError, formattedErrors, gotWarning, formattedWarnings);
       util.throwOnEmptyMixinBodies(component3);
-      util.throwOnInsufficientUriToSource(component3);
+      await util.throwOnInsufficientUriToSource(component3);
       print("Compile took ${stopwatch.elapsedMilliseconds} ms");
 
       util.postProcess(component3);
@@ -1108,7 +1149,7 @@
   Component component =
       await normalCompilePlain(input, options: options, compiler: compiler);
   util.throwOnEmptyMixinBodies(component);
-  util.throwOnInsufficientUriToSource(component);
+  await util.throwOnInsufficientUriToSource(component);
   return component;
 }
 
@@ -1130,7 +1171,7 @@
   }
   Component initializedComponent = await compiler.computeDelta();
   util.throwOnEmptyMixinBodies(initializedComponent);
-  util.throwOnInsufficientUriToSource(initializedComponent);
+  await util.throwOnInsufficientUriToSource(initializedComponent);
   bool result = compiler.initializedFromDill;
   new File.fromUri(output)
       .writeAsBytesSync(util.postProcess(initializedComponent));
@@ -1146,7 +1187,7 @@
   Component initializedFullComponent =
       await compiler.computeDelta(fullComponent: true);
   util.throwOnEmptyMixinBodies(initializedFullComponent);
-  util.throwOnInsufficientUriToSource(initializedFullComponent);
+  await util.throwOnInsufficientUriToSource(initializedFullComponent);
   Expect.equals(initializedComponent.libraries.length,
       initializedFullComponent.libraries.length);
   Expect.equals(initializedComponent.uriToSource.length,
@@ -1158,7 +1199,7 @@
 
   Component partialComponent = await compiler.computeDelta();
   util.throwOnEmptyMixinBodies(partialComponent);
-  util.throwOnInsufficientUriToSource(partialComponent);
+  await util.throwOnInsufficientUriToSource(partialComponent);
   actuallyInvalidatedCount = (compiler
           .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
           ?.length ??
@@ -1170,7 +1211,7 @@
 
   Component emptyComponent = await compiler.computeDelta();
   util.throwOnEmptyMixinBodies(emptyComponent);
-  util.throwOnInsufficientUriToSource(emptyComponent);
+  await util.throwOnInsufficientUriToSource(emptyComponent);
 
   List<Uri> fullLibUris =
       initializedComponent.libraries.map((lib) => lib.importUri).toList();
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index f5c07a6..7cc2842 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -2,6 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:convert' show utf8;
+
+import "package:front_end/src/api_prototype/file_system.dart" show FileSystem;
+
 import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
 
 import 'package:kernel/kernel.dart'
@@ -57,7 +61,8 @@
   return empty;
 }
 
-void throwOnInsufficientUriToSource(Component component) {
+Future<void> throwOnInsufficientUriToSource(Component component,
+    {FileSystem fileSystem}) async {
   UriFinder uriFinder = new UriFinder();
   component.accept(uriFinder);
   Set<Uri> uris = uriFinder.seenUris.toSet();
@@ -65,6 +70,39 @@
   if (uris.length != 0) {
     throw "Expected 0 uris with no source, but found ${uris.length} ($uris)";
   }
+
+  if (fileSystem != null) {
+    uris = uriFinder.seenUris.toSet();
+    for (Uri uri in uris) {
+      if (uri == null) continue;
+      if (uri.scheme != "org-dartlang-test") continue;
+      // The file system doesn't have the sources for any modules.
+      // For now assume that that is always what's going on.
+      if (!await fileSystem.entityForUri(uri).exists()) continue;
+      List<int> expected = await fileSystem.entityForUri(uri).readAsBytes();
+      List<int> actual = component.uriToSource[uri].source;
+      bool fail = false;
+      if (expected.length != actual.length) {
+        fail = true;
+      }
+      if (!fail) {
+        for (int i = 0; i < expected.length; i++) {
+          if (expected[i] != actual[i]) {
+            fail = true;
+            break;
+          }
+        }
+      }
+      if (fail) {
+        String expectedString = utf8.decode(expected);
+        String actualString = utf8.decode(actual);
+        throw "Not expected source for $uri:\n\n"
+            "$expectedString\n\n"
+            "vs\n\n"
+            "$actualString";
+      }
+    }
+  }
 }
 
 class UriFinder extends RecursiveVisitor {
diff --git a/pkg/front_end/test/kernel_generator_test.dart b/pkg/front_end/test/kernel_generator_test.dart
index 0c5a766..92c2b12 100644
--- a/pkg/front_end/test/kernel_generator_test.dart
+++ b/pkg/front_end/test/kernel_generator_test.dart
@@ -109,6 +109,7 @@
           ?.component;
       for (var lib in component.libraries) {
         if (lib.importUri.scheme == 'dart') {
+          // ignore: DEPRECATED_MEMBER_USE
           expect(lib.isExternal, isTrue);
         }
       }
@@ -126,6 +127,7 @@
 
       var aLib = component.libraries
           .firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart');
+      // ignore: DEPRECATED_MEMBER_USE
       expect(aLib.isExternal, isTrue);
     });
 
@@ -136,6 +138,7 @@
           ?.component;
       for (var lib in component.libraries) {
         if (lib.importUri.scheme == 'dart') {
+          // ignore: DEPRECATED_MEMBER_USE
           expect(lib.isExternal, isTrue);
         }
       }
@@ -152,6 +155,7 @@
 
       var aLib = component.libraries
           .firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart');
+      // ignore: DEPRECATED_MEMBER_USE
       expect(aLib.isExternal, isFalse);
     });
 
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
index 5eb2b73..4fec65a 100644
--- a/pkg/front_end/test/parser_suite.dart
+++ b/pkg/front_end/test/parser_suite.dart
@@ -26,7 +26,7 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
-import 'package:front_end/src/fasta/source/stack_listener.dart'
+import 'package:front_end/src/fasta/source/stack_listener_impl.dart'
     show offsetForToken;
 
 import 'package:kernel/ast.dart';
@@ -74,6 +74,11 @@
     enableExtensionMethods: true,
     enableNonNullable: true);
 
+ScannerConfiguration scannerConfigurationNonNNBD = new ScannerConfiguration(
+    enableTripleShift: true,
+    enableExtensionMethods: true,
+    enableNonNullable: false);
+
 class Context extends ChainContext with MatchContext {
   final bool updateExpectations;
   final bool addTrace;
@@ -100,7 +105,9 @@
   Future<Result<TestDescription>> run(
       TestDescription description, Context context) {
     List<int> lineStarts = new List<int>();
-    Token firstToken = scanUri(description.uri, lineStarts: lineStarts);
+
+    Token firstToken =
+        scanUri(description.uri, description.shortName, lineStarts: lineStarts);
 
     if (firstToken == null) {
       return Future.value(crash(description, StackTrace.current));
@@ -137,7 +144,7 @@
 
   Future<Result<TestDescription>> run(
       TestDescription description, Context context) {
-    Token firstToken = scanUri(description.uri);
+    Token firstToken = scanUri(description.uri, description.shortName);
 
     if (firstToken == null) {
       return Future.value(crash(description, StackTrace.current));
@@ -166,7 +173,8 @@
   Future<Result<TestDescription>> run(
       TestDescription description, Context context) {
     List<int> lineStarts = new List<int>();
-    Token firstToken = scanUri(description.uri, lineStarts: lineStarts);
+    Token firstToken =
+        scanUri(description.uri, description.shortName, lineStarts: lineStarts);
 
     if (firstToken == null) {
       return Future.value(crash(description, StackTrace.current));
@@ -261,15 +269,24 @@
   }
 }
 
-Token scanUri(Uri uri, {List<int> lineStarts}) {
+Token scanUri(Uri uri, String shortName, {List<int> lineStarts}) {
+  ScannerConfiguration config;
+
+  String firstDir = shortName.split("/")[0];
+  if (firstDir == "non-nnbd") {
+    config = scannerConfigurationNonNNBD;
+  } else {
+    config = scannerConfiguration;
+  }
+
   File f = new File.fromUri(uri);
   List<int> rawBytes = f.readAsBytesSync();
 
   Uint8List bytes = new Uint8List(rawBytes.length + 1);
   bytes.setRange(0, rawBytes.length, rawBytes);
 
-  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
-      includeComments: true, configuration: scannerConfiguration);
+  Utf8BytesScanner scanner =
+      new Utf8BytesScanner(bytes, includeComments: true, configuration: config);
   Token firstToken = scanner.tokenize();
   if (lineStarts != null) {
     lineStarts.addAll(scanner.lineStarts);
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index b7ea368..4e23241 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -28,7 +28,7 @@
       // Find first one that's not any of the blacklisted ones.
       String line = traceLines[i];
       if (line.contains("parser_test_listener.dart:") ||
-          line.contains("parser_test.dart:")) continue;
+          line.contains("parser_suite.dart:")) continue;
       return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
     }
     return "N/A";
diff --git a/pkg/front_end/test/parser_test_listener_creator.dart b/pkg/front_end/test/parser_test_listener_creator.dart
index 4042166..3607a44 100644
--- a/pkg/front_end/test/parser_test_listener_creator.dart
+++ b/pkg/front_end/test/parser_test_listener_creator.dart
@@ -63,7 +63,7 @@
       // Find first one that's not any of the blacklisted ones.
       String line = traceLines[i];
       if (line.contains("parser_test_listener.dart:") ||
-          line.contains("parser_test.dart:")) continue;
+          line.contains("parser_suite.dart:")) continue;
       return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
     }
     return "N/A";
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index 4615ee2..745be079 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.dart
@@ -32,7 +32,7 @@
       // Find first one that's not any of the blacklisted ones.
       String line = traceLines[i];
       if (line.contains("parser_test_listener.dart:") ||
-          line.contains("parser_test.dart:") ||
+          line.contains("parser_suite.dart:") ||
           line.contains("parser_test_parser.dart:") ||
           line == "<asynchronous suspension>") continue;
       return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
diff --git a/pkg/front_end/test/parser_test_parser_creator.dart b/pkg/front_end/test/parser_test_parser_creator.dart
index 8e9121c..002bf61 100644
--- a/pkg/front_end/test/parser_test_parser_creator.dart
+++ b/pkg/front_end/test/parser_test_parser_creator.dart
@@ -21,9 +21,8 @@
   } else {
     out = new StringBuffer();
   }
-
-  File f = new File.fromUri(
-      Platform.script.resolve("../lib/src/fasta/parser/parser.dart"));
+  File f = new File.fromUri(Platform.script
+      .resolve("../../_fe_analyzer_shared/lib/src/parser/parser_impl.dart"));
   List<int> rawBytes = f.readAsBytesSync();
 
   Uint8List bytes = new Uint8List(rawBytes.length + 1);
@@ -67,7 +66,7 @@
       // Find first one that's not any of the blacklisted ones.
       String line = traceLines[i];
       if (line.contains("parser_test_listener.dart:") ||
-          line.contains("parser_test.dart:") ||
+          line.contains("parser_suite.dart:") ||
           line.contains("parser_test_parser.dart:") ||
           line == "<asynchronous suspension>") continue;
       return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 56504e3..5f05c67 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -132,6 +132,12 @@
 clarification
 clashes
 class's
+class3a
+class3b
+class4a
+class4b
+class4c
+class4d
 clazz
 cls
 cn
@@ -448,7 +454,6 @@
 juxtaposition
 juxtapositions
 k
-k’s
 kallentu
 kernel's
 kernel2kernel
@@ -456,6 +461,7 @@
 kmillikin
 kustermann
 kv
+k’s
 l
 lacks
 lang
@@ -633,13 +639,14 @@
 quick
 quoted
 r
+r'$creation
 r'\f
 r'\r
 r'\s
 r'\t
 r'\u
 r'\v
-r'$creation
+ra
 radix
 raises
 ran
@@ -700,6 +707,7 @@
 resumed
 rewrites
 rewrote
+rf
 rhs
 ri
 rightmost
@@ -711,6 +719,7 @@
 roughly
 rounding
 rparen
+rs
 runnable
 s
 sb
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 82ad053..301934c 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -112,6 +112,7 @@
 amount
 ampersand
 an
+analog
 analogously
 analysis
 analyze
@@ -209,6 +210,7 @@
 attempting
 attempts
 attention
+attribute
 authors
 automatically
 available
@@ -377,12 +379,12 @@
 catches
 categories
 category
-caveats
 caught
 cause
 caused
 causes
 causing
+caveats
 certain
 chain
 chained
@@ -1216,8 +1218,8 @@
 go
 goes
 going
-good
 gone
+good
 got
 gotten
 governed
@@ -1551,6 +1553,7 @@
 labels
 lack
 lacking
+landed
 lands
 language
 large
@@ -2234,11 +2237,11 @@
 realigned
 realized
 really
-reassign
 reason
 reasonable
 reasoning
 reasons
+reassign
 receive
 receiver
 recent
@@ -2894,6 +2897,7 @@
 treatment
 treats
 tree
+tri
 trick
 tried
 tries
@@ -2962,6 +2966,8 @@
 unioned
 unique
 unit
+unite
+united
 units
 unix
 unknown
diff --git a/pkg/front_end/test/static_types/data/prefix_postfix.dart b/pkg/front_end/test/static_types/data/prefix_postfix.dart
index 398d9dc..71db218 100644
--- a/pkg/front_end/test/static_types/data/prefix_postfix.dart
+++ b/pkg/front_end/test/static_types/data/prefix_postfix.dart
@@ -95,13 +95,19 @@
     /*cfe:nnbd.update: num!*/
     /*cfe|dart2js.num*/
     /*cfe:nnbd.num!*/
-    numInstance /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
+    numInstance
+        /*cfe|dart2js.invoke: num*/
+        /*cfe:nnbd.invoke: num!*/
+        /*int*/ ++;
 
     /*cfe|dart2js.update: num*/
     /*cfe:nnbd.update: num!*/
     /*cfe|dart2js.num*/
     /*cfe:nnbd.num!*/
-    numInstance /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
+    numInstance
+        /*cfe|dart2js.invoke: num*/
+        /*cfe:nnbd.invoke: num!*/
+        /*int*/ --;
 
     /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
         /*cfe|dart2js.update: num*/
diff --git a/pkg/front_end/test/static_types/data/promoted_access.dart b/pkg/front_end/test/static_types/data/promoted_access.dart
index 9cc7227..a21bae7 100644
--- a/pkg/front_end/test/static_types/data/promoted_access.dart
+++ b/pkg/front_end/test/static_types/data/promoted_access.dart
@@ -8,8 +8,8 @@
 class Class<T> {
   method(T o) {
     if (/*cfe|dart2js.T*/ /*cfe:nnbd.T%*/ o is Class) {
-      /*cfe|dart2js.T extends Class<dynamic>*/
-      /*cfe:nnbd.T! extends Class<dynamic>!*/
+      /*cfe|dart2js.T & Class<dynamic>*/
+      /*cfe:nnbd.T! & Class<dynamic>!*/
       o. /*invoke: dynamic*/ method(/*Null*/ null);
     }
   }
@@ -17,8 +17,8 @@
 
 method<T>(T o) {
   if (/*cfe|dart2js.T*/ /*cfe:nnbd.T%*/ o is Class) {
-    /*cfe|dart2js.T extends Class<dynamic>*/
-    /*cfe:nnbd.T! extends Class<dynamic>!*/
+    /*cfe|dart2js.T & Class<dynamic>*/
+    /*cfe:nnbd.T! & Class<dynamic>!*/
     o. /*invoke: dynamic*/ method(/*Null*/ null);
   }
 }
diff --git a/pkg/front_end/test/summary_generator_test.dart b/pkg/front_end/test/summary_generator_test.dart
index 044f900..bd63826 100644
--- a/pkg/front_end/test/summary_generator_test.dart
+++ b/pkg/front_end/test/summary_generator_test.dart
@@ -39,6 +39,7 @@
     var component = loadComponentFromBytes(summary);
     var aLib = findLibrary(component, 'a.dart');
     expect(aLib.importUri.path, '/a/b/c/a.dart');
+    // ignore: DEPRECATED_MEMBER_USE
     expect(aLib.isExternal, isFalse);
   });
 
@@ -47,6 +48,7 @@
     var summary = await summarize(['a.dart'], allSources);
     var component = loadComponentFromBytes(summary);
     var coreLib = findLibrary(component, 'core');
+    // ignore: DEPRECATED_MEMBER_USE
     expect(coreLib.isExternal, isTrue);
   });
 
@@ -60,7 +62,9 @@
     var component = loadComponentFromBytes(summaryB);
     var aLib = findLibrary(component, 'a.dart');
     var bLib = findLibrary(component, 'b.dart');
+    // ignore: DEPRECATED_MEMBER_USE
     expect(aLib.isExternal, isTrue);
+    // ignore: DEPRECATED_MEMBER_USE
     expect(bLib.isExternal, isFalse);
   });
 
@@ -151,9 +155,13 @@
   var dLib = findLibrary(component, 'd.dart');
 
   // All libraries but `d.dart` are marked external.
+  // ignore: DEPRECATED_MEMBER_USE
   expect(aLib.isExternal, isTrue);
+  // ignore: DEPRECATED_MEMBER_USE
   expect(bLib.isExternal, isTrue);
+  // ignore: DEPRECATED_MEMBER_USE
   expect(cLib.isExternal, isTrue);
+  // ignore: DEPRECATED_MEMBER_USE
   expect(dLib.isExternal, isFalse);
 
   // The type-hierarchy for A, B, D is visible and correct
diff --git a/pkg/front_end/test/type_labeler_test.dart b/pkg/front_end/test/type_labeler_test.dart
index c904fbd..3adb0e8 100644
--- a/pkg/front_end/test/type_labeler_test.dart
+++ b/pkg/front_end/test/type_labeler_test.dart
@@ -64,102 +64,120 @@
   DartType dynamicType = const DynamicType();
   check({dynamicType: "dynamic"}, 0);
 
-  DartType boolType = new InterfaceType(boolClass);
+  DartType boolType = new InterfaceType(boolClass, Nullability.legacy);
   check({boolType: "bool"}, 0);
 
-  DartType numType = new InterfaceType(numClass);
+  DartType numType = new InterfaceType(numClass, Nullability.legacy);
   check({numType: "num"}, 0);
 
-  DartType intType = new InterfaceType(intClass);
+  DartType intType = new InterfaceType(intClass, Nullability.legacy);
   check({intType: "int"}, 0);
 
-  DartType object = new InterfaceType(objectClass);
+  DartType object = new InterfaceType(objectClass, Nullability.legacy);
   check({object: "Object"}, 1);
 
-  DartType foo = new InterfaceType(fooClass);
+  DartType foo = new InterfaceType(fooClass, Nullability.legacy);
   check({foo: "Foo"}, 1);
 
-  DartType foo2 = new InterfaceType(foo2Class);
+  DartType foo2 = new InterfaceType(foo2Class, Nullability.legacy);
   check({foo2: "Foo"}, 1);
   check({foo: "Foo/*1*/", foo2: "Foo/*2*/"}, 2);
 
-  DartType barVoid = new InterfaceType(barClass, [voidType]);
+  DartType barVoid =
+      new InterfaceType(barClass, Nullability.legacy, [voidType]);
   check({barVoid: "Bar<void>"}, 1);
 
-  DartType barObject = new InterfaceType(barClass, [object]);
+  DartType barObject =
+      new InterfaceType(barClass, Nullability.legacy, [object]);
   check({barObject: "Bar<Object>"}, 2);
 
-  DartType barBarDynamic = new InterfaceType(barClass, [
-    new InterfaceType(barClass, [dynamicType])
+  DartType barBarDynamic = new InterfaceType(barClass, Nullability.legacy, [
+    new InterfaceType(barClass, Nullability.legacy, [dynamicType])
   ]);
   check({barBarDynamic: "Bar<Bar<dynamic>>"}, 1);
 
-  DartType parameterY = new TypeParameterType(new TypeParameter("Y"));
-  DartType barY = new InterfaceType(barClass, [parameterY]);
+  DartType parameterY =
+      new TypeParameterType(new TypeParameter("Y"), Nullability.legacy);
+  DartType barY = new InterfaceType(barClass, Nullability.legacy, [parameterY]);
   check({parameterY: "Y", barY: "Bar<Y>"}, 1);
 
-  DartType bazFooBarBazDynamicVoid = new InterfaceType(bazClass, [
+  DartType bazFooBarBazDynamicVoid =
+      new InterfaceType(bazClass, Nullability.legacy, [
     foo,
-    new InterfaceType(barClass, [
-      new InterfaceType(bazClass, [dynamicType, voidType])
+    new InterfaceType(barClass, Nullability.legacy, [
+      new InterfaceType(bazClass, Nullability.legacy, [dynamicType, voidType])
     ])
   ]);
   check({bazFooBarBazDynamicVoid: "Baz<Foo, Bar<Baz<dynamic, void>>>"}, 3);
 
-  DartType bazFooFoo2 = new InterfaceType(bazClass, [foo, foo2]);
+  DartType bazFooFoo2 =
+      new InterfaceType(bazClass, Nullability.legacy, [foo, foo2]);
   check({bazFooFoo2: "Baz<Foo/*1*/, Foo/*2*/>"}, 3);
 
-  DartType funVoid = new FunctionType([], voidType);
+  DartType funVoid = new FunctionType([], voidType, Nullability.legacy);
   check({funVoid: "void Function()"}, 0);
 
-  DartType funFooBarVoid = new FunctionType([foo], barVoid);
+  DartType funFooBarVoid = new FunctionType([foo], barVoid, Nullability.legacy);
   check({funFooBarVoid: "Bar<void> Function(Foo)"}, 2);
 
-  DartType funFooFoo2 = new FunctionType([foo], foo2);
+  DartType funFooFoo2 = new FunctionType([foo], foo2, Nullability.legacy);
   check({funFooFoo2: "Foo/*1*/ Function(Foo/*2*/)"}, 2);
 
-  DartType funOptFooVoid =
-      new FunctionType([foo], voidType, requiredParameterCount: 0);
+  DartType funOptFooVoid = new FunctionType([foo], voidType, Nullability.legacy,
+      requiredParameterCount: 0);
   check({funOptFooVoid: "void Function([Foo])"}, 1);
 
-  DartType funFooOptIntVoid =
-      new FunctionType([foo, intType], voidType, requiredParameterCount: 1);
+  DartType funFooOptIntVoid = new FunctionType(
+      [foo, intType], voidType, Nullability.legacy,
+      requiredParameterCount: 1);
   check({funFooOptIntVoid: "void Function(Foo, [int])"}, 1);
 
-  DartType funOptFooOptIntVoid =
-      new FunctionType([foo, intType], voidType, requiredParameterCount: 0);
+  DartType funOptFooOptIntVoid = new FunctionType(
+      [foo, intType], voidType, Nullability.legacy,
+      requiredParameterCount: 0);
   check({funOptFooOptIntVoid: "void Function([Foo, int])"}, 1);
 
-  DartType funNamedObjectVoid = new FunctionType([], voidType,
+  DartType funNamedObjectVoid = new FunctionType(
+      [], voidType, Nullability.legacy,
       namedParameters: [new NamedType("obj", object)]);
   check({funNamedObjectVoid: "void Function({Object obj})"}, 1);
 
-  DartType funFooNamedObjectVoid = new FunctionType([foo], voidType,
+  DartType funFooNamedObjectVoid = new FunctionType(
+      [foo], voidType, Nullability.legacy,
       namedParameters: [new NamedType("obj", object)]);
   check({funFooNamedObjectVoid: "void Function(Foo, {Object obj})"}, 2);
 
   TypeParameter t = new TypeParameter("T", object, dynamicType);
   DartType funGeneric = new FunctionType(
-      [new TypeParameterType(t)], new TypeParameterType(t),
+      [new TypeParameterType(t, Nullability.legacy)],
+      new TypeParameterType(t, Nullability.legacy),
+      Nullability.legacy,
       typeParameters: [t]);
   check({funGeneric: "T Function<T>(T)"}, 0);
 
   TypeParameter tObject = new TypeParameter("T", object, object);
   DartType funGenericObject = new FunctionType(
-      [new TypeParameterType(tObject)], new TypeParameterType(tObject),
+      [new TypeParameterType(tObject, Nullability.legacy)],
+      new TypeParameterType(tObject, Nullability.legacy),
+      Nullability.legacy,
       typeParameters: [tObject]);
   check({funGenericObject: "T Function<T extends Object>(T)"}, 1);
 
   TypeParameter tFoo = new TypeParameter("T", foo, dynamicType);
   DartType funGenericFoo = new FunctionType(
-      [new TypeParameterType(tFoo)], new TypeParameterType(tFoo),
+      [new TypeParameterType(tFoo, Nullability.legacy)],
+      new TypeParameterType(tFoo, Nullability.legacy),
+      Nullability.legacy,
       typeParameters: [tFoo]);
   check({funGenericFoo: "T Function<T extends Foo>(T)"}, 1);
 
   TypeParameter tBar = new TypeParameter("T", dynamicType, dynamicType);
-  tBar.bound = new InterfaceType(barClass, [new TypeParameterType(tBar)]);
+  tBar.bound = new InterfaceType(barClass, Nullability.legacy,
+      [new TypeParameterType(tBar, Nullability.legacy)]);
   DartType funGenericBar = new FunctionType(
-      [new TypeParameterType(tBar)], new TypeParameterType(tBar),
+      [new TypeParameterType(tBar, Nullability.legacy)],
+      new TypeParameterType(tBar, Nullability.legacy),
+      Nullability.legacy,
       typeParameters: [tBar]);
   check({funGenericBar: "T Function<T extends Bar<T>>(T)"}, 1);
 
@@ -171,10 +189,12 @@
   Field nextField = new Field(new Name("next"), type: foo2);
   foo2Class.fields.add(nextField);
   Field xField = new Field(new Name("x"),
-      type: new TypeParameterType(bazClass.typeParameters[0]));
+      type: new TypeParameterType(
+          bazClass.typeParameters[0], Nullability.legacy));
   bazClass.fields.add(xField);
   Field yField = new Field(new Name("y"),
-      type: new TypeParameterType(bazClass.typeParameters[1]));
+      type: new TypeParameterType(
+          bazClass.typeParameters[1], Nullability.legacy));
   bazClass.fields.add(yField);
   FunctionNode gooFunction = new FunctionNode(new EmptyStatement(),
       typeParameters: [new TypeParameter("V")]);
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
index ebc86c0..a85b802 100644
--- a/pkg/front_end/test/unit_test_suites.dart
+++ b/pkg/front_end/test/unit_test_suites.dart
@@ -24,8 +24,6 @@
 import 'fasta/strong_tester.dart' as strong show createContext;
 import 'fasta/text_serialization_suite.dart' as text_serialization
     show createContext;
-import 'fasta/type_promotion_look_ahead_suite.dart' as type_promotion
-    show createContext;
 import 'incremental_bulk_compiler_smoke_suite.dart' as incremental_bulk_compiler
     show createContext;
 import 'incremental_load_from_dill_suite.dart' as incremental_load
@@ -40,9 +38,11 @@
 class Options {
   final String configurationName;
   final bool verbose;
+  final bool printFailureLog;
   final Uri outputDirectory;
 
-  Options(this.configurationName, this.verbose, this.outputDirectory);
+  Options(this.configurationName, this.verbose, this.printFailureLog,
+      this.outputDirectory);
 
   static Options parse(List<String> args) {
     var parser = new ArgParser()
@@ -52,12 +52,14 @@
       ..addOption("output-directory",
           help: "directory to which results.json and logs.json are written")
       ..addFlag("verbose",
-          abbr: "v", help: "print additional information", defaultsTo: false);
+          abbr: "v", help: "print additional information", defaultsTo: false)
+      ..addFlag("print",
+          abbr: "p", help: "print failure logs", defaultsTo: false);
     var parsedArguments = parser.parse(args);
     String outputPath = parsedArguments["output-directory"] ?? ".";
     Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
     return Options(parsedArguments["named-configuration"],
-        parsedArguments["verbose"], outputDirectory);
+        parsedArguments["verbose"], parsedArguments["print"], outputDirectory);
   }
 }
 
@@ -65,6 +67,7 @@
   final String suiteName;
   final String prefix;
   final bool verbose;
+  final bool printFailureLog;
   final SendPort resultsPort;
   final SendPort logsPort;
   final Map<String, Stopwatch> stopwatches = {};
@@ -72,7 +75,7 @@
   final Set<String> seenTests = {};
 
   ResultLogger(this.suiteName, this.prefix, this.resultsPort, this.logsPort,
-      this.verbose, this.configurationName);
+      this.verbose, this.printFailureLog, this.configurationName);
 
   String getTestName(TestDescription description) {
     return "$prefix/${description.shortName}";
@@ -131,6 +134,10 @@
         "result": outcome,
         "log": failureLog,
       }));
+      if (printFailureLog) {
+        print('FAILED: $testName: $outcome');
+        print(failureLog);
+      }
     }
     if (verbose) {
       String result = matchedExpectations ? "PASS" : "FAIL";
@@ -200,8 +207,6 @@
       path: "fasta/strong_tester.dart", shardCount: 4, shard: 2),
   const Suite("fasta/strong4", strong.createContext, "../../testing.json",
       path: "fasta/strong_tester.dart", shardCount: 4, shard: 3),
-  const Suite("fasta/type_promotion_look_ahead", type_promotion.createContext,
-      "../../testing.json"),
   const Suite("incremental_bulk_compiler_smoke",
       incremental_bulk_compiler.createContext, "../testing.json"),
   const Suite("incremental_load_from_dill", incremental_load.createContext,
@@ -222,9 +227,10 @@
   final SendPort resultsPort;
   final SendPort logsPort;
   final bool verbose;
+  final bool printFailureLog;
   final String configurationName;
   const SuiteConfiguration(this.name, this.resultsPort, this.logsPort,
-      this.verbose, this.configurationName);
+      this.verbose, this.printFailureLog, this.configurationName);
 }
 
 void runSuite(SuiteConfiguration configuration) {
@@ -238,6 +244,7 @@
       configuration.resultsPort,
       configuration.logsPort,
       configuration.verbose,
+      configuration.printFailureLog,
       configuration.configurationName);
   runMe(<String>[], suite.createContext,
       me: suiteUri,
@@ -270,6 +277,7 @@
         resultsPort.sendPort,
         logsPort.sendPort,
         options.verbose,
+        options.printFailureLog,
         options.configurationName);
     Future future = Future<bool>(() async {
       Stopwatch stopwatch = Stopwatch()..start();
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
deleted file mode 100644
index 9a61489..0000000
--- a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
+++ /dev/null
@@ -1,72 +0,0 @@
-pkg/front_end/testcases/extensions/compounds.dart:12:43: Context: Possible promotion of other@340
-  bool operator ==(Object other) => other is Number && value == other.value;
-                                          ^^
-pkg/front_end/testcases/extensions/compounds.dart:19:15: Context: Possible promotion of other@501
-    if (other is int) {
-              ^^
-pkg/front_end/testcases/extensions/compounds.dart:21:22: Context: Possible promotion of other@501
-    } else if (other is Number) {
-                     ^^
-pkg/front_end/testcases/extensions/compounds.dart:29:15: Context: Possible promotion of other@501
-    if (other is int) {
-              ^^
-pkg/front_end/testcases/extensions/compounds.dart:31:22: Context: Possible promotion of other@501
-    } else if (other is Number) {
-                     ^^
-pkg/front_end/testcases/extensions/compounds.dart:161:16: Context: Write to v@3587
-  expect(n1, v += n1);
-               ^^
-pkg/front_end/testcases/extensions/compounds.dart:162:16: Context: Write to v@3587
-  expect(n2, v += n1);
-               ^^
-pkg/front_end/testcases/extensions/compounds.dart:163:16: Context: Write to v@3587
-  expect(n0, v -= n2);
-               ^^
-pkg/front_end/testcases/extensions/compounds.dart:164:16: Context: Write to v@3587
-  expect(n1, v += n1);
-               ^^
-pkg/front_end/testcases/extensions/compounds.dart:165:16: Context: Write to v@3587
-  expect(n0, v -= n1);
-               ^^
-pkg/front_end/testcases/extensions/compounds.dart:166:14: Context: Write to v@3587
-  expect(n1, ++v);
-             ^^
-pkg/front_end/testcases/extensions/compounds.dart:167:14: Context: Write to v@3587
-  expect(n0, --v);
-             ^^
-pkg/front_end/testcases/extensions/compounds.dart:168:15: Context: Write to v@3587
-  expect(n0, v++);
-              ^^
-pkg/front_end/testcases/extensions/compounds.dart:169:15: Context: Write to v@3587
-  expect(n1, v--);
-              ^^
-pkg/front_end/testcases/extensions/compounds.dart:173:5: Context: Write to v@3587
-  v += n1;
-    ^^
-pkg/front_end/testcases/extensions/compounds.dart:175:5: Context: Write to v@3587
-  v += n1;
-    ^^
-pkg/front_end/testcases/extensions/compounds.dart:177:5: Context: Write to v@3587
-  v -= n2;
-    ^^
-pkg/front_end/testcases/extensions/compounds.dart:179:5: Context: Write to v@3587
-  v += n1;
-    ^^
-pkg/front_end/testcases/extensions/compounds.dart:181:5: Context: Write to v@3587
-  v -= n1;
-    ^^
-pkg/front_end/testcases/extensions/compounds.dart:183:3: Context: Write to v@3587
-  ++v;
-  ^^
-pkg/front_end/testcases/extensions/compounds.dart:185:3: Context: Write to v@3587
-  --v;
-  ^^
-pkg/front_end/testcases/extensions/compounds.dart:187:4: Context: Write to v@3587
-  v++;
-   ^^
-pkg/front_end/testcases/extensions/compounds.dart:189:4: Context: Write to v@3587
-  v--;
-   ^^
-pkg/front_end/testcases/extensions/compounds.dart:489:14: Context: Write to expected@13239
-    expected = null;
-             ^
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.type_promotion.expect
deleted file mode 100644
index 3748577..0000000
--- a/pkg/front_end/testcases/extensions/conflict_with_object.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/extensions/conflict_with_object.dart:16:9: Context: Write to value@422
-  value = Extension("").noSuchMethod;
-        ^
-pkg/front_end/testcases/extensions/conflict_with_object.dart:20:9: Context: Write to value@422
-  value = Extension("").runtimeType();
-        ^
-pkg/front_end/testcases/extensions/conflict_with_object.dart:27:9: Context: Write to value@762
-  value = "".noSuchMethod;
-        ^
-pkg/front_end/testcases/extensions/conflict_with_object.dart:29:9: Context: Write to value@762
-  value = "".runtimeType;
-        ^
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart
new file mode 100644
index 0000000..70ca3dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'deferred_explicit_access_lib.dart' deferred as prefix;
+
+main() async {
+  await prefix.loadLibrary();
+  expect(0, prefix.Extension.staticField);
+
+  expect(0, prefix.Extension(0).property);
+  expect(42, prefix.Extension(0).property = 42);
+  expect(84, prefix.Extension(42).property);
+  expect(85, prefix.Extension(43).method());
+
+  expect(42, prefix.Extension.staticProperty);
+  expect(87, prefix.Extension.staticProperty = 87);
+  expect(87, prefix.Extension.staticMethod());
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.outline.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.outline.expect
new file mode 100644
index 0000000..95c544f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.outline.expect
@@ -0,0 +1,54 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/deferred_explicit_access.dart:5:1: Error: Extension 'Extension' cannot be imported through a deferred import.
+// Try adding the `hide Extension` to the import.
+// import 'deferred_explicit_access_lib.dart' deferred as prefix;
+// ^
+//
+import self as self;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = self2::Extension|staticField;
+  static get staticProperty = get self2::Extension|staticProperty;
+  static method staticMethod = self2::Extension|staticMethod;
+  get property = self2::Extension|get#property;
+  method method = self2::Extension|method;
+  tearoff method = self2::Extension|get#method;
+  static set staticProperty = set self2::Extension|staticProperty;
+  set property = self2::Extension|set#property;
+}
+static field core::int* Extension|staticField;
+static field core::int* topLevelField;
+static get Extension|staticProperty() → core::int*
+  ;
+static set Extension|staticProperty(core::int* value) → void
+  ;
+static method Extension|staticMethod() → core::int*
+  ;
+static method Extension|get#property(final core::int* #this) → core::int*
+  ;
+static method Extension|set#property(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|method(final core::int* #this) → core::int*
+  ;
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => self2::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  ;
+static set topLevelProperty(core::int* value) → void
+  ;
+static method topLevelMethod() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.expect
new file mode 100644
index 0000000..e9e8aad
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.expect
@@ -0,0 +1,70 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/deferred_explicit_access.dart:5:1: Error: Extension 'Extension' cannot be imported through a deferred import.
+// Try adding the `hide Extension` to the import.
+// import 'deferred_explicit_access_lib.dart' deferred as prefix;
+// ^
+//
+import self as self;
+import "deferred_explicit_access_lib.dart" as def;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic async {
+  await LoadLibrary(prefix);
+  self::expect(0, let final dynamic #t1 = CheckLibraryIsLoaded(prefix) in def::Extension|staticField);
+  self::expect(0, let final dynamic #t2 = CheckLibraryIsLoaded(prefix) in def::Extension|get#property(0));
+  self::expect(42, let final dynamic #t3 = CheckLibraryIsLoaded(prefix) in let final core::int* #t4 = 0 in let final core::int* #t5 = 42 in let final void #t6 = def::Extension|set#property(#t4, #t5) in #t5);
+  self::expect(84, let final dynamic #t7 = CheckLibraryIsLoaded(prefix) in def::Extension|get#property(42));
+  self::expect(85, let final dynamic #t8 = CheckLibraryIsLoaded(prefix) in def::Extension|method(43));
+  self::expect(42, let final dynamic #t9 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty);
+  self::expect(87, let final dynamic #t10 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty = 87);
+  self::expect(87, let final dynamic #t11 = CheckLibraryIsLoaded(prefix) in def::Extension|staticMethod());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as def;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = def::Extension|staticField;
+  static get staticProperty = get def::Extension|staticProperty;
+  static method staticMethod = def::Extension|staticMethod;
+  get property = def::Extension|get#property;
+  method method = def::Extension|method;
+  tearoff method = def::Extension|get#method;
+  static set staticProperty = set def::Extension|staticProperty;
+  set property = def::Extension|set#property;
+}
+static field core::int* Extension|staticField = 0;
+static field core::int* topLevelField = def::Extension|staticField;
+static get Extension|staticProperty() → core::int*
+  return def::Extension|staticField;
+static set Extension|staticProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|staticMethod() → core::int*
+  return def::Extension|staticField;
+static method Extension|get#property(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|set#property(final core::int* #this, core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|method(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => def::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  return def::Extension|staticField;
+static set topLevelProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method topLevelMethod() → dynamic
+  return def::Extension|staticField;
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
new file mode 100644
index 0000000..ddb1b0a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
@@ -0,0 +1,96 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/deferred_explicit_access.dart:5:1: Error: Extension 'Extension' cannot be imported through a deferred import.
+// Try adding the `hide Extension` to the import.
+// import 'deferred_explicit_access_lib.dart' deferred as prefix;
+// ^
+//
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "deferred_explicit_access_lib.dart" as def;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(LoadLibrary(prefix), :async_op_then, :async_op_error, :async_op) in null;
+        :result;
+        self::expect(0, let final core::Object* #t2 = CheckLibraryIsLoaded(prefix) in def::Extension|staticField);
+        self::expect(0, let final core::Object* #t3 = CheckLibraryIsLoaded(prefix) in def::Extension|get#property(0));
+        self::expect(42, let final core::Object* #t4 = CheckLibraryIsLoaded(prefix) in let final core::int* #t5 = 0 in let final core::int* #t6 = 42 in let final void #t7 = def::Extension|set#property(#t5, #t6) in #t6);
+        self::expect(84, let final core::Object* #t8 = CheckLibraryIsLoaded(prefix) in def::Extension|get#property(42));
+        self::expect(85, let final core::Object* #t9 = CheckLibraryIsLoaded(prefix) in def::Extension|method(43));
+        self::expect(42, let final core::Object* #t10 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty);
+        self::expect(87, let final core::Object* #t11 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty = 87);
+        self::expect(87, let final core::Object* #t12 = CheckLibraryIsLoaded(prefix) in def::Extension|staticMethod());
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as def;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = def::Extension|staticField;
+  static get staticProperty = get def::Extension|staticProperty;
+  static method staticMethod = def::Extension|staticMethod;
+  get property = def::Extension|get#property;
+  method method = def::Extension|method;
+  tearoff method = def::Extension|get#method;
+  static set staticProperty = set def::Extension|staticProperty;
+  set property = def::Extension|set#property;
+}
+static field core::int* Extension|staticField = 0;
+static field core::int* topLevelField = def::Extension|staticField;
+static get Extension|staticProperty() → core::int*
+  return def::Extension|staticField;
+static set Extension|staticProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|staticMethod() → core::int*
+  return def::Extension|staticField;
+static method Extension|get#property(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|set#property(final core::int* #this, core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|method(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => def::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  return def::Extension|staticField;
+static set topLevelProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method topLevelMethod() → dynamic
+  return def::Extension|staticField;
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access_lib.dart b/pkg/front_end/testcases/extensions/deferred_explicit_access_lib.dart
new file mode 100644
index 0000000..a85bb28
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access_lib.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension Extension on int {
+  static int staticField = 0;
+
+  static int get staticProperty => staticField;
+
+  static void set staticProperty(int value) {
+    staticField = value;
+  }
+
+  static int staticMethod() => staticField;
+
+  int get property => this + staticField;
+
+  void set property(int value) {
+    staticField = value;
+  }
+
+  int method() => this + staticField;
+}
+
+int topLevelField = Extension.staticField;
+
+int get topLevelProperty => Extension.staticField;
+
+void set topLevelProperty(int value) {
+  Extension.staticField = value;
+}
+
+topLevelMethod() => Extension.staticField;
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart
new file mode 100644
index 0000000..c5d6507
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'deferred_explicit_access_lib.dart' deferred as prefix hide Extension;
+
+main() async {
+  await prefix.loadLibrary();
+  expect(0, prefix.topLevelField);
+  expect(42, prefix.topLevelField = 42);
+  expect(42, prefix.topLevelField);
+
+  expect(0, prefix.topLevelProperty);
+  expect(87, prefix.topLevelProperty = 87);
+  expect(87, prefix.topLevelProperty);
+  expect(87, prefix.topLevelMethod());
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.outline.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.outline.expect
new file mode 100644
index 0000000..d102c56
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.outline.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = self2::Extension|staticField;
+  static get staticProperty = get self2::Extension|staticProperty;
+  static method staticMethod = self2::Extension|staticMethod;
+  get property = self2::Extension|get#property;
+  method method = self2::Extension|method;
+  tearoff method = self2::Extension|get#method;
+  static set staticProperty = set self2::Extension|staticProperty;
+  set property = self2::Extension|set#property;
+}
+static field core::int* Extension|staticField;
+static field core::int* topLevelField;
+static get Extension|staticProperty() → core::int*
+  ;
+static set Extension|staticProperty(core::int* value) → void
+  ;
+static method Extension|staticMethod() → core::int*
+  ;
+static method Extension|get#property(final core::int* #this) → core::int*
+  ;
+static method Extension|set#property(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|method(final core::int* #this) → core::int*
+  ;
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => self2::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  ;
+static set topLevelProperty(core::int* value) → void
+  ;
+static method topLevelMethod() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect
new file mode 100644
index 0000000..1341a83
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect
@@ -0,0 +1,60 @@
+library;
+import self as self;
+import "deferred_explicit_access_lib.dart" as def;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic async {
+  await LoadLibrary(prefix);
+  self::expect(0, let final dynamic #t1 = CheckLibraryIsLoaded(prefix) in def::topLevelField);
+  self::expect(42, let final dynamic #t2 = CheckLibraryIsLoaded(prefix) in def::topLevelField = 42);
+  self::expect(42, let final dynamic #t3 = CheckLibraryIsLoaded(prefix) in def::topLevelField);
+  self::expect(0, let final dynamic #t4 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
+  self::expect(87, let final dynamic #t5 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty = 87);
+  self::expect(87, let final dynamic #t6 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
+  self::expect(87, let final dynamic #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{dart.core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as def;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = def::Extension|staticField;
+  static get staticProperty = get def::Extension|staticProperty;
+  static method staticMethod = def::Extension|staticMethod;
+  get property = def::Extension|get#property;
+  method method = def::Extension|method;
+  tearoff method = def::Extension|get#method;
+  static set staticProperty = set def::Extension|staticProperty;
+  set property = def::Extension|set#property;
+}
+static field core::int* Extension|staticField = 0;
+static field core::int* topLevelField = def::Extension|staticField;
+static get Extension|staticProperty() → core::int*
+  return def::Extension|staticField;
+static set Extension|staticProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|staticMethod() → core::int*
+  return def::Extension|staticField;
+static method Extension|get#property(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|set#property(final core::int* #this, core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|method(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => def::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  return def::Extension|staticField;
+static set topLevelProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method topLevelMethod() → dynamic
+  return def::Extension|staticField;
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
new file mode 100644
index 0000000..0508e3e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
@@ -0,0 +1,87 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "deferred_explicit_access_lib.dart" as def;
+
+import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
+
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(LoadLibrary(prefix), :async_op_then, :async_op_error, :async_op) in null;
+        :result;
+        self::expect(0, let final core::Object* #t2 = CheckLibraryIsLoaded(prefix) in def::topLevelField);
+        self::expect(42, let final core::Object* #t3 = CheckLibraryIsLoaded(prefix) in def::topLevelField = 42);
+        self::expect(42, let final core::Object* #t4 = CheckLibraryIsLoaded(prefix) in def::topLevelField);
+        self::expect(0, let final core::Object* #t5 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
+        self::expect(87, let final core::Object* #t6 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty = 87);
+        self::expect(87, let final core::Object* #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
+        self::expect(87, let final core::Object* #t8 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as def;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  static field staticField = def::Extension|staticField;
+  static get staticProperty = get def::Extension|staticProperty;
+  static method staticMethod = def::Extension|staticMethod;
+  get property = def::Extension|get#property;
+  method method = def::Extension|method;
+  tearoff method = def::Extension|get#method;
+  static set staticProperty = set def::Extension|staticProperty;
+  set property = def::Extension|set#property;
+}
+static field core::int* Extension|staticField = 0;
+static field core::int* topLevelField = def::Extension|staticField;
+static get Extension|staticProperty() → core::int*
+  return def::Extension|staticField;
+static set Extension|staticProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|staticMethod() → core::int*
+  return def::Extension|staticField;
+static method Extension|get#property(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|set#property(final core::int* #this, core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method Extension|method(final core::int* #this) → core::int*
+  return #this.{core::num::+}(def::Extension|staticField);
+static method Extension|get#method(final core::int* #this) → () →* core::int*
+  return () → core::int* => def::Extension|method(#this);
+static get topLevelProperty() → core::int*
+  return def::Extension|staticField;
+static set topLevelProperty(core::int* value) → void {
+  def::Extension|staticField = value;
+}
+static method topLevelMethod() → dynamic
+  return def::Extension|staticField;
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.type_promotion.expect
deleted file mode 100644
index 5d34b36..0000000
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/extensions/direct_static_access.dart:101:11: Context: Write to field@408
-    field = property;
-          ^
-pkg/front_end/testcases/extensions/direct_static_access.dart:170:11: Context: Write to field@408
-    field = property;
-          ^
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.type_promotion.expect
deleted file mode 100644
index 48040a1..0000000
--- a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.type_promotion.expect
+++ /dev/null
@@ -1,216 +0,0 @@
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:27:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:28:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:29:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:30:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:32:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:33:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:34:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:35:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:37:13: Context: Write to aVariable@453
-  aVariable = GenericExtension(cClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:38:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<A>(cClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:39:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<B>(cClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:40:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<C>(cClass).property;
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:42:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:43:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:44:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:45:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:47:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:48:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:49:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:50:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:52:13: Context: Write to aVariable@453
-  aVariable = GenericExtension(cClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:53:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<A>(cClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:54:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<B>(cClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:55:13: Context: Write to aVariable@453
-  aVariable = GenericExtension<C>(cClass).method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:57:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:58:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:59:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:60:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(aClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:61:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:62:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:63:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:64:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(aClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:65:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:66:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:67:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:68:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(aClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:69:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:70:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:71:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:72:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(aClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:74:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:75:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:76:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:77:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(bClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:78:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:79:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:80:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:81:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(bClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:82:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:83:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:84:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:85:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(bClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:86:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:87:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:88:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:89:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(bClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:91:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(cClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:92:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(cClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:93:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(cClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:94:13: Context: Write to cVariable@468
-  cVariable = GenericExtension(cClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:95:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(cClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:96:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(cClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:97:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(cClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:98:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<A>(cClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:99:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(cClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:100:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(cClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:101:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(cClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:102:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<B>(cClass).genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:103:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(cClass).genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:104:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(cClass).genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:105:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(cClass).genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/explicit_extension_inference.dart:106:13: Context: Write to cVariable@468
-  cVariable = GenericExtension<C>(cClass).genericMethod1<C>(aVariable);
-            ^
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.type_promotion.expect
deleted file mode 100644
index b4cc663..0000000
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart:15:16: Context: Write to latestType@375
-    latestType = '$T';
-               ^
-pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart:19:16: Context: Write to latestType@375
-    latestType = '$T';
-               ^
-pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart:23:16: Context: Write to latestType@375
-    latestType = '$T';
-               ^
-pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart:27:16: Context: Write to latestType@375
-    latestType = '$T:$S';
-               ^
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.type_promotion.expect
deleted file mode 100644
index 759a79d..0000000
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/extensions/extension_setter.dart:19:11: Context: Write to value@335
-    value = value + 1;
-          ^
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect
deleted file mode 100644
index 8431aad..0000000
--- a/pkg/front_end/testcases/extensions/if_null.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/extensions/if_null.dart:27:5: Context: Write to c@408
-  c = new Class();
-    ^
diff --git a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.type_promotion.expect
deleted file mode 100644
index c086585..0000000
--- a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.type_promotion.expect
+++ /dev/null
@@ -1,54 +0,0 @@
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:27:13: Context: Write to cVariable@468
-  cVariable = aClass.property;
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:28:13: Context: Write to cVariable@468
-  cVariable = bClass.property;
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:29:13: Context: Write to aVariable@453
-  aVariable = cClass.property;
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:31:13: Context: Write to cVariable@468
-  cVariable = aClass.method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:32:13: Context: Write to cVariable@468
-  cVariable = bClass.method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:33:13: Context: Write to aVariable@453
-  aVariable = cClass.method(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:35:13: Context: Write to cVariable@468
-  cVariable = aClass.genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:36:13: Context: Write to cVariable@468
-  cVariable = aClass.genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:37:13: Context: Write to cVariable@468
-  cVariable = aClass.genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:38:13: Context: Write to cVariable@468
-  cVariable = aClass.genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:40:13: Context: Write to cVariable@468
-  cVariable = bClass.genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:41:13: Context: Write to cVariable@468
-  cVariable = bClass.genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:42:13: Context: Write to cVariable@468
-  cVariable = bClass.genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:43:13: Context: Write to cVariable@468
-  cVariable = bClass.genericMethod1<C>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:45:13: Context: Write to cVariable@468
-  cVariable = cClass.genericMethod1(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:46:13: Context: Write to cVariable@468
-  cVariable = cClass.genericMethod1<A>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:47:13: Context: Write to cVariable@468
-  cVariable = cClass.genericMethod1<B>(aVariable);
-            ^
-pkg/front_end/testcases/extensions/implicit_extension_inference.dart:48:13: Context: Write to cVariable@468
-  cVariable = cClass.genericMethod1<C>(aVariable);
-            ^
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart b/pkg/front_end/testcases/extensions/import_via_prefix.dart
new file mode 100644
index 0000000..a266734
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'import_via_prefix_lib.dart' as prefix;
+
+main() {
+  expect(3, "foo".method());
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw "Expected $expected, actual $actual";
+}
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart.outline.expect b/pkg/front_end/testcases/extensions/import_via_prefix.dart.outline.expect
new file mode 100644
index 0000000..4b7b4b9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///import_via_prefix_lib.dart" as prefix;
+
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+extension Extension on core::String* {
+  method method = self2::Extension|method;
+  tearoff method = self2::Extension|get#method;
+}
+static method Extension|method(final core::String* #this) → core::int*
+  ;
+static method Extension|get#method(final core::String* #this) → () →* core::int*
+  return () → core::int* => self2::Extension|method(#this);
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect
new file mode 100644
index 0000000..255aa8c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "import_via_prefix_lib.dart" as imp;
+
+import "org-dartlang-testcase:///import_via_prefix_lib.dart" as prefix;
+
+static method main() → dynamic {
+  self::expect(3, imp::Extension|method("foo"));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{dart.core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as imp;
+import "dart:core" as core;
+
+extension Extension on core::String* {
+  method method = imp::Extension|method;
+  tearoff method = imp::Extension|get#method;
+}
+static method Extension|method(final core::String* #this) → core::int*
+  return #this.{core::String::length};
+static method Extension|get#method(final core::String* #this) → () →* core::int*
+  return () → core::int* => imp::Extension|method(#this);
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect
new file mode 100644
index 0000000..255aa8c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "import_via_prefix_lib.dart" as imp;
+
+import "org-dartlang-testcase:///import_via_prefix_lib.dart" as prefix;
+
+static method main() → dynamic {
+  self::expect(3, imp::Extension|method("foo"));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{dart.core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as imp;
+import "dart:core" as core;
+
+extension Extension on core::String* {
+  method method = imp::Extension|method;
+  tearoff method = imp::Extension|get#method;
+}
+static method Extension|method(final core::String* #this) → core::int*
+  return #this.{core::String::length};
+static method Extension|get#method(final core::String* #this) → () →* core::int*
+  return () → core::int* => imp::Extension|method(#this);
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix_lib.dart b/pkg/front_end/testcases/extensions/import_via_prefix_lib.dart
new file mode 100644
index 0000000..a2f111a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/import_via_prefix_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension Extension on String {
+  int method() => length;
+}
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/instance_access.dart.type_promotion.expect
deleted file mode 100644
index 052b274..0000000
--- a/pkg/front_end/testcases/extensions/instance_access.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/extensions/instance_access.dart:37:10: Context: Write to value@755
-    value++;
-         ^^
-pkg/front_end/testcases/extensions/instance_access.dart:57:10: Context: Write to value@1217
-    value++;
-         ^^
diff --git a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.type_promotion.expect
deleted file mode 100644
index 2967660..0000000
--- a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/extensions/instance_access_of_static.dart:18:10: Context: Write to value@447
-    value++;
-         ^^
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.type_promotion.expect
deleted file mode 100644
index 675c36c..0000000
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/extensions/instance_tearoff.dart:54:6: Context: Write to c0@978
-  c0 = new Class1(-4);
-     ^
-pkg/front_end/testcases/extensions/instance_tearoff.dart:58:6: Context: Write to c1@1007
-  c1 = new Class1(-7);
-     ^
-pkg/front_end/testcases/extensions/instance_tearoff.dart:73:6: Context: Write to c0@1494
-  c0 = new Class2(-4);
-     ^
-pkg/front_end/testcases/extensions/instance_tearoff.dart:77:6: Context: Write to c1@1523
-  c1 = new Class2(-7);
-     ^
diff --git a/pkg/front_end/testcases/extensions/issue38745.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/issue38745.dart.type_promotion.expect
deleted file mode 100644
index 02c6ac8..0000000
--- a/pkg/front_end/testcases/extensions/issue38745.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/extensions/issue38745.dart:21:11: Context: Write to field@266
-    field = 23;
-          ^
-pkg/front_end/testcases/extensions/issue38745.dart:23:14: Context: Write to property@286
-    property = 23;
-             ^
-pkg/front_end/testcases/extensions/issue38745.dart:25:15: Context: Write to property2@349
-    property2 = 23;
-              ^
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
deleted file mode 100644
index 5534d1b..0000000
--- a/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/extensions/null_aware.dart:31:5: Context: Write to c@530
-  c = new Class();
-    ^
diff --git a/pkg/front_end/testcases/extensions/operators.dart b/pkg/front_end/testcases/extensions/operators.dart
index 6927bfe..17d5e27 100644
--- a/pkg/front_end/testcases/extensions/operators.dart
+++ b/pkg/front_end/testcases/extensions/operators.dart
@@ -121,6 +121,11 @@
   expect(c0, -c0);
 }
 
+void errors(Complex c) {
+  Operators(c) == c;
+  Operators(c) != c;
+}
+
 expect(expected, actual) {
   if (expected != actual) {
     throw 'Mismatch: expected=$expected, actual=$actual';
diff --git a/pkg/front_end/testcases/extensions/operators.dart.outline.expect b/pkg/front_end/testcases/extensions/operators.dart.outline.expect
index c38c397..ca95978 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.outline.expect
@@ -38,5 +38,7 @@
   ;
 static method explicit() → dynamic
   ;
+static method errors(self::Complex* c) → void
+  ;
 static method expect(dynamic expected, dynamic actual) → dynamic
   ;
diff --git a/pkg/front_end/testcases/extensions/operators.dart.strong.expect b/pkg/front_end/testcases/extensions/operators.dart.strong.expect
index 3453a24..4a46ae4 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.strong.expect
@@ -1,4 +1,15 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/operators.dart:125:3: Error: Explicit extension application cannot be used as an expression.
+//   Operators(c) == c;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/operators.dart:126:3: Error: Explicit extension application cannot be used as an expression.
+//   Operators(c) != c;
+//   ^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -114,6 +125,14 @@
   self::expect(c0, self::Operators|-(c_m2, c_m2));
   self::expect(c0, self::Operators|unary-(c0));
 }
+static method errors(self::Complex* c) → void {
+  invalid-expression "pkg/front_end/testcases/extensions/operators.dart:125:3: Error: Explicit extension application cannot be used as an expression.
+  Operators(c) == c;
+  ^^^^^^^^^".{core::Object::==}(c);
+  !invalid-expression "pkg/front_end/testcases/extensions/operators.dart:126:3: Error: Explicit extension application cannot be used as an expression.
+  Operators(c) != c;
+  ^^^^^^^^^".{core::Object::==}(c);
+}
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
     throw "Mismatch: expected=${expected}, actual=${actual}";
diff --git a/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
index 3453a24..4a46ae4 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
@@ -1,4 +1,15 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/operators.dart:125:3: Error: Explicit extension application cannot be used as an expression.
+//   Operators(c) == c;
+//   ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/operators.dart:126:3: Error: Explicit extension application cannot be used as an expression.
+//   Operators(c) != c;
+//   ^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -114,6 +125,14 @@
   self::expect(c0, self::Operators|-(c_m2, c_m2));
   self::expect(c0, self::Operators|unary-(c0));
 }
+static method errors(self::Complex* c) → void {
+  invalid-expression "pkg/front_end/testcases/extensions/operators.dart:125:3: Error: Explicit extension application cannot be used as an expression.
+  Operators(c) == c;
+  ^^^^^^^^^".{core::Object::==}(c);
+  !invalid-expression "pkg/front_end/testcases/extensions/operators.dart:126:3: Error: Explicit extension application cannot be used as an expression.
+  Operators(c) != c;
+  ^^^^^^^^^".{core::Object::==}(c);
+}
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
     throw "Mismatch: expected=${expected}, actual=${actual}";
diff --git a/pkg/front_end/testcases/extensions/operators.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/operators.dart.type_promotion.expect
deleted file mode 100644
index 0cf24a9..0000000
--- a/pkg/front_end/testcases/extensions/operators.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/extensions/operators.dart:27:18: Context: Possible promotion of other@348
-    return other is Complex &&
-                 ^^
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect
deleted file mode 100644
index a2934e5..0000000
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/extensions/unnamed_extensions.dart:37:10: Context: Write to value@744
-    value++;
-         ^^
-pkg/front_end/testcases/extensions/unnamed_extensions.dart:57:10: Context: Write to value@1195
-    value++;
-         ^^
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.type_promotion.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.type_promotion.expect
deleted file mode 100644
index 1a6ab73..0000000
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.type_promotion.expect
+++ /dev/null
@@ -1,57 +0,0 @@
-pkg/front_end/testcases/general/DeltaBlue.dart:458:20: Context: Write to overridden@13140
-        overridden = overridden.satisfy(mark));
-                   ^
-pkg/front_end/testcases/general/DeltaBlue.dart:479:48: Context: Write to i@14066
-      for (int i = 0; i < unsatisfied.length; i++) {
-                                               ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:483:16: Context: Write to strength@14021
-      strength = strength.nextWeaker();
-               ^
-pkg/front_end/testcases/general/DeltaBlue.dart:530:46: Context: Write to i@16109
-    for (int i = 0; i < constraints.length; i++) {
-                                             ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:578:50: Context: Write to i@17909
-      for (int i = 0; i < v.constraints.length; i++) {
-                                                 ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:583:50: Context: Write to i@17909
-      for (int i = 0; i < v.constraints.length; i++) {
-                                                 ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:596:48: Context: Write to i@18497
-    for (int i = 0; i < v.constraints.length; i++) {
-                                               ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:618:39: Context: Write to i@19006
-    for (int i = 0; i < list.length; i++) {
-                                      ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:641:28: Context: Write to i@19940
-  for (int i = 0; i <= n; i++) {
-                           ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:644:23: Context: Write to first@19858
-    if (i == 0) first = v;
-                      ^
-pkg/front_end/testcases/general/DeltaBlue.dart:645:22: Context: Write to last@19872
-    if (i == n) last = v;
-                     ^
-pkg/front_end/testcases/general/DeltaBlue.dart:646:10: Context: Write to prev@19845
-    prev = v;
-         ^
-pkg/front_end/testcases/general/DeltaBlue.dart:651:29: Context: Write to i@19940
-  for (int i = 0; i < 100; i++) {
-                            ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:674:27: Context: Write to i@21031
-  for (int i = 0; i < n; i++) {
-                          ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:675:9: Context: Write to src@20956
-    src = new Variable("src", i);
-        ^
-pkg/front_end/testcases/general/DeltaBlue.dart:676:9: Context: Write to dst@20968
-    dst = new Variable("dst", i);
-        ^
-pkg/front_end/testcases/general/DeltaBlue.dart:686:31: Context: Write to i@21031
-  for (int i = 0; i < n - 1; i++) {
-                              ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:690:31: Context: Write to i@21031
-  for (int i = 0; i < n - 1; i++) {
-                              ^^
-pkg/front_end/testcases/general/DeltaBlue.dart:698:28: Context: Write to i@21838
-  for (int i = 0; i < 10; i++) {
-                           ^^
diff --git a/pkg/front_end/testcases/all_variances.dart b/pkg/front_end/testcases/general/all_variances.dart
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart
rename to pkg/front_end/testcases/general/all_variances.dart
diff --git a/pkg/front_end/testcases/all_variances.dart.legacy.expect b/pkg/front_end/testcases/general/all_variances.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart.legacy.expect
rename to pkg/front_end/testcases/general/all_variances.dart.legacy.expect
diff --git a/pkg/front_end/testcases/all_variances.dart.legacy.transformed.expect b/pkg/front_end/testcases/general/all_variances.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart.legacy.transformed.expect
rename to pkg/front_end/testcases/general/all_variances.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/all_variances.dart.outline.expect b/pkg/front_end/testcases/general/all_variances.dart.outline.expect
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart.outline.expect
rename to pkg/front_end/testcases/general/all_variances.dart.outline.expect
diff --git a/pkg/front_end/testcases/all_variances.dart.strong.expect b/pkg/front_end/testcases/general/all_variances.dart.strong.expect
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart.strong.expect
rename to pkg/front_end/testcases/general/all_variances.dart.strong.expect
diff --git a/pkg/front_end/testcases/all_variances.dart.strong.transformed.expect b/pkg/front_end/testcases/general/all_variances.dart.strong.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/all_variances.dart.strong.transformed.expect
rename to pkg/front_end/testcases/general/all_variances.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/general/arithmetic.dart.type_promotion.expect b/pkg/front_end/testcases/general/arithmetic.dart.type_promotion.expect
deleted file mode 100644
index ec473b6..0000000
--- a/pkg/front_end/testcases/general/arithmetic.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/arithmetic.dart:11:35: Context: Write to i@330
-  for (int i = 0; i < xs.length; i++) {}
-                                  ^^
diff --git a/pkg/front_end/testcases/general/bad_setter_abstract.dart.type_promotion.expect b/pkg/front_end/testcases/general/bad_setter_abstract.dart.type_promotion.expect
deleted file mode 100644
index 4ea66ae..0000000
--- a/pkg/front_end/testcases/general/bad_setter_abstract.dart.type_promotion.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-pkg/front_end/testcases/general/bad_setter_abstract.dart:22:11: Context: Write to threw@344
-    threw = true;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:24:11: Context: Write to threw@344
-    threw = false;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:32:11: Context: Write to threw@344
-    threw = true;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:34:11: Context: Write to threw@344
-    threw = false;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:42:11: Context: Write to threw@344
-    threw = true;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:44:11: Context: Write to threw@344
-    threw = false;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:55:11: Context: Write to threw@344
-    threw = true;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:57:11: Context: Write to threw@344
-    threw = false;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:65:11: Context: Write to threw@344
-    threw = true;
-          ^
-pkg/front_end/testcases/general/bad_setter_abstract.dart:67:11: Context: Write to threw@344
-    threw = false;
-          ^
diff --git a/pkg/front_end/testcases/general/bug32414a.dart.type_promotion.expect b/pkg/front_end/testcases/general/bug32414a.dart.type_promotion.expect
deleted file mode 100644
index 398e367..0000000
--- a/pkg/front_end/testcases/general/bug32414a.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/bug32414a.dart:10:5: Context: Write to b@305
-  b = 42;
-    ^
diff --git a/pkg/front_end/testcases/general/cascade.dart.type_promotion.expect b/pkg/front_end/testcases/general/cascade.dart.type_promotion.expect
deleted file mode 100644
index 27988f8..0000000
--- a/pkg/front_end/testcases/general/cascade.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/cascade.dart:25:8: Context: Write to list@232
-  list = [
-       ^
diff --git a/pkg/front_end/testcases/general/check_deferred_is_check.dart.type_promotion.expect b/pkg/front_end/testcases/general/check_deferred_is_check.dart.type_promotion.expect
deleted file mode 100644
index 0223359..0000000
--- a/pkg/front_end/testcases/general/check_deferred_is_check.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/check_deferred_is_check.dart:9:11: Context: Possible promotion of x@279
-  print(x is lib.C);
-          ^^
diff --git a/pkg/front_end/testcases/general/closure.dart.type_promotion.expect b/pkg/front_end/testcases/general/closure.dart.type_promotion.expect
deleted file mode 100644
index 82f0475..0000000
--- a/pkg/front_end/testcases/general/closure.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/closure.dart:18:7: Context: Write to x@336
-    x = new Foo();
-      ^
diff --git a/pkg/front_end/testcases/general/control_flow_collection.dart.type_promotion.expect b/pkg/front_end/testcases/general/control_flow_collection.dart.type_promotion.expect
deleted file mode 100644
index c79cbe1..0000000
--- a/pkg/front_end/testcases/general/control_flow_collection.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/general/control_flow_collection.dart:13:31: Context: Write to i@354
-    for (int i = 11; i <= 14; ++i) i,
-                              ^^
-pkg/front_end/testcases/general/control_flow_collection.dart:22:31: Context: Write to i@354
-    for (int i = 11; i <= 14; ++i) i,
-                              ^^
-pkg/front_end/testcases/general/control_flow_collection.dart:31:31: Context: Write to i@354
-    for (int i = 11; i <= 14; ++i) i: i,
-                              ^^
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.type_promotion.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.type_promotion.expect
deleted file mode 100644
index 4fe87a7..0000000
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.type_promotion.expect
+++ /dev/null
@@ -1,306 +0,0 @@
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:123:49: Context: Write to i@7018
-  var list10 = [for (int i = 0; oracle("foo"); i++) 42];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:124:48: Context: Write to i@7018
-  var set10 = {for (int i = 0; oracle("foo"); i++) 42, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:125:48: Context: Write to i@7018
-  var map10 = {for (int i = 0; oracle("foo"); i++) "bar": 42, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:126:49: Context: Write to i@7018
-  var list11 = [for (int i = 0; oracle("foo"); i++) dynVar];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:127:48: Context: Write to i@7018
-  var set11 = {for (int i = 0; oracle("foo"); i++) dynVar, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:128:48: Context: Write to i@7018
-  var map11 = {for (int i = 0; oracle("foo"); i++) "bar": dynVar, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:129:49: Context: Write to i@7018
-  var list12 = [for (int i = 0; oracle("foo"); i++) [42]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:130:48: Context: Write to i@7018
-  var set12 = {for (int i = 0; oracle("foo"); i++) [42], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:131:48: Context: Write to i@7018
-  var map12 = {for (int i = 0; oracle("foo"); i++) "bar": [42], "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:132:49: Context: Write to i@7018
-  var list20 = [for (int i = 0; oracle("foo"); i++) ...[42]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:133:48: Context: Write to i@7018
-  var set20 = {for (int i = 0; oracle("foo"); i++) ...[42], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:134:48: Context: Write to i@7018
-  var map20 = {for (int i = 0; oracle("foo"); i++) ...{"bar": 42}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:135:49: Context: Write to i@7018
-  var list21 = [for (int i = 0; oracle("foo"); i++) ...[dynVar]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:136:48: Context: Write to i@7018
-  var set21 = {for (int i = 0; oracle("foo"); i++) ...[dynVar], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:137:48: Context: Write to i@7018
-  var map21 = {for (int i = 0; oracle("foo"); i++) ...{"bar": dynVar}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:138:49: Context: Write to i@7018
-  var list22 = [for (int i = 0; oracle("foo"); i++) ...[[42]]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:139:48: Context: Write to i@7018
-  var set22 = {for (int i = 0; oracle("foo"); i++) ...[[42]], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:140:48: Context: Write to i@7018
-  var map22 = {for (int i = 0; oracle("foo"); i++) ...{"bar": [42]}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:141:49: Context: Write to i@7018
-  var list30 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[42]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:142:48: Context: Write to i@7018
-  var set30 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[42], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:143:48: Context: Write to i@7018
-  var map30 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...{"bar": 42}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:144:49: Context: Write to i@7018
-  var list31 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[dynVar]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:145:48: Context: Write to i@7018
-  var set31 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[dynVar], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:146:48: Context: Write to i@7018
-  var map31 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...{"bar": dynVar}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:147:49: Context: Write to i@7018
-  var list33 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[42]]];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:148:48: Context: Write to i@7018
-  var set33 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[42]], null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:149:48: Context: Write to i@7018
-  var map33 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...{"bar": [42]}, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:150:61: Context: Write to i@7018
-  List<List<int>> list40 = [for (int i = 0; oracle("foo"); i++) ...[[]]];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:151:59: Context: Write to i@7018
-  Set<List<int>> set40 = {for (int i = 0; oracle("foo"); i++) ...[[]], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:152:67: Context: Write to i@7018
-  Map<String, List<int>> map40 = {for (int i = 0; oracle("foo"); i++) ...{"bar": []}, "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:153:61: Context: Write to i@7018
-  List<List<int>> list41 = [for (int i = 0; oracle("foo"); i++) ...{[]}];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:154:59: Context: Write to i@7018
-  Set<List<int>> set41 = {for (int i = 0; oracle("foo"); i++) ...{[]}, null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:155:61: Context: Write to i@7018
-  List<List<int>> list42 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[]]];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:156:59: Context: Write to i@7018
-  Set<List<int>> set42 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[]], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:157:67: Context: Write to i@7018
-  Map<String, List<int>> map42 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...{"bar": []}, "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:158:55: Context: Write to i@7018
-  List<int> list50 = [for (int i = 0; oracle("foo"); i++) ...[]];
-                                                      ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:159:53: Context: Write to i@7018
-  Set<int> set50 = {for (int i = 0; oracle("foo"); i++) ...[], null};
-                                                    ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:160:61: Context: Write to i@7018
-  Map<String, int> map50 = {for (int i = 0; oracle("foo"); i++) ...{}, "baz": null};
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:161:55: Context: Write to i@7018
-  List<int> list51 = [for (int i = 0; oracle("foo"); i++) ...{}];
-                                                      ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:162:53: Context: Write to i@7018
-  Set<int> set51 = {for (int i = 0; oracle("foo"); i++) ...{}, null};
-                                                    ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:163:55: Context: Write to i@7018
-  List<int> list52 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[]];
-                                                      ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:164:53: Context: Write to i@7018
-  Set<int> set52 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[], null};
-                                                    ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:165:61: Context: Write to i@7018
-  List<List<int>> list60 = [for (int i = 0; oracle("foo"); i++) ...[[]]];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:166:59: Context: Write to i@7018
-  Set<List<int>> set60 = {for (int i = 0; oracle("foo"); i++) ...[[]], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:167:67: Context: Write to i@7018
-  Map<String, List<int>> map60 = {for (int i = 0; oracle("foo"); i++) ...{"bar": []}, "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:168:61: Context: Write to i@7018
-  List<List<int>> list61 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[]]];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:169:59: Context: Write to i@7018
-  Set<List<int>> set61 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...[[]], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:170:67: Context: Write to i@7018
-  Map<String, List<int>> map61 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...{"bar": []}, "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:171:61: Context: Write to i@7018
-  List<List<int>> list70 = [for (int i = 0; oracle("foo"); i++) []];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:172:59: Context: Write to i@7018
-  Set<List<int>> set70 = {for (int i = 0; oracle("foo"); i++) [], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:173:67: Context: Write to i@7018
-  Map<String, List<int>> map70 = {for (int i = 0; oracle("foo"); i++) "bar": [], "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:174:61: Context: Write to i@7018
-  List<List<int>> list71 = [for (int i = 0; oracle("foo"); i++) if (oracle()) []];
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:175:59: Context: Write to i@7018
-  Set<List<int>> set71 = {for (int i = 0; oracle("foo"); i++) if (oracle()) [], null};
-                                                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:176:67: Context: Write to i@7018
-  Map<String, List<int>> map71 = {for (int i = 0; oracle("foo"); i++) if (oracle()) "bar": [], "baz": null};
-                                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:177:49: Context: Write to i@7018
-  var list80 = [for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else 3.14];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:178:48: Context: Write to i@7018
-  var set80 = {for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else 3.14, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:179:48: Context: Write to i@7018
-  var map80 = {for (int i = 0; oracle("foo"); i++) if (oracle()) "bar": 42 else "bar": 3.14, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:180:49: Context: Write to i@7018
-  var list81 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...listInt else ...listDouble];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:181:48: Context: Write to i@7018
-  var set81 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...listInt else ...listDouble, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:182:48: Context: Write to i@7018
-  var map81 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...mapStringInt else ...mapStringDouble, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:183:49: Context: Write to i@7018
-  var list82 = [for (int i = 0; oracle("foo"); i++) if (oracle()) ...listInt else ...dynVar];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:184:48: Context: Write to i@7018
-  var set82 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...listInt else ...dynVar, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:185:48: Context: Write to i@7018
-  var map82 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...mapStringInt else ...dynVar, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:186:49: Context: Write to i@7018
-  var list83 = [for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else ...listDouble];
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:187:48: Context: Write to i@7018
-  var set83 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...listInt else 3.14, null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:188:48: Context: Write to i@7018
-  var map83 = {for (int i = 0; oracle("foo"); i++) if (oracle()) ...mapStringInt else "bar": 3.14, "baz": null};
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:189:55: Context: Write to i@7018
-  List<int> list90 = [for (int i = 0; oracle("foo"); i++) dynVar];
-                                                      ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:190:53: Context: Write to i@7018
-  Set<int> set90 = {for (int i = 0; oracle("foo"); i++) dynVar, null};
-                                                    ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:191:61: Context: Write to i@7018
-  Map<String, int> map90 = {for (int i = 0; oracle("foo"); i++) "bar": dynVar, "baz": null};
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:192:55: Context: Write to i@7018
-  List<int> list91 = [for (int i = 0; oracle("foo"); i++) ...dynVar];
-                                                      ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:193:53: Context: Write to i@7018
-  Set<int> set91 = {for (int i = 0; oracle("foo"); i++) ...dynVar, null};
-                                                    ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:194:61: Context: Write to i@7018
-  Map<String, int> map91 = {for (int i = 0; oracle("foo"); i++) ...dynVar, "baz": null};
-                                                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:195:40: Context: Write to index@6916
-  List<int> list100 = <int>[for (index = 0; oracle("foo"); index++) 42];
-                                       ^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:195:65: Context: Write to index@6916
-  List<int> list100 = <int>[for (index = 0; oracle("foo"); index++) 42];
-                                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:196:38: Context: Write to index@6916
-  Set<int> set100 = <int>{for (index = 0; oracle("foo"); index++) 42};
-                                     ^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:196:63: Context: Write to index@6916
-  Set<int> set100 = <int>{for (index = 0; oracle("foo"); index++) 42};
-                                                              ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:197:54: Context: Write to index@6916
-  Map<String, int> map100 = <String, int>{for (index = 0; oracle("foo"); index++) "bar": 42};
-                                                     ^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:197:79: Context: Write to index@6916
-  Map<String, int> map100 = <String, int>{for (index = 0; oracle("foo"); index++) "bar": 42};
-                                                                              ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:204:48: Context: Write to i@7018
-  List<int> list130 = [for (var i = 1; i < 2; i++) i];
-                                               ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:205:46: Context: Write to i@7018
-  Set<int> set130 = {for (var i = 1; i < 2; i++) i};
-                                             ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:206:51: Context: Write to i@7018
-  Map<int, int> map130 = {for (var i = 1; i < 2; i++) i: i};
-                                                  ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:210:41: Context: Write to i@13789
-  <int>[for (int i = 0; oracle("foo"); i++) "bar"];
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:211:41: Context: Write to i@13789
-  <int>{for (int i = 0; oracle("foo"); i++) "bar", null};
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:212:46: Context: Write to i@13789
-  <int, int>{for (int i = 0; oracle("foo"); i++) "bar": "bar", "baz": null};
-                                             ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:213:41: Context: Write to i@13789
-  <int>[for (int i = 0; oracle("foo"); i++) ...["bar"]];
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:214:41: Context: Write to i@13789
-  <int>{for (int i = 0; oracle("foo"); i++) ...["bar"], null};
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:215:46: Context: Write to i@13789
-  <int, int>{for (int i = 0; oracle("foo"); i++) ...{"bar": "bar"}, "baz": null};
-                                             ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:216:41: Context: Write to i@13789
-  <int>[for (int i = 0; oracle("foo"); i++) ...map];
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:217:41: Context: Write to i@13789
-  <int>{for (int i = 0; oracle("foo"); i++) ...map, null};
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:218:46: Context: Write to i@13789
-  <int, int>{for (int i = 0; oracle("foo"); i++) ...list, 42: null};
-                                             ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:219:44: Context: Write to i@13789
-  <String>[for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else 3.14];
-                                           ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:220:44: Context: Write to i@13789
-  <String>{for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else 3.14, null};
-                                           ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:221:52: Context: Write to i@13789
-  <String, String>{for (int i = 0; oracle("foo"); i++) if (oracle()) "bar": 42 else "bar": 3.14, "baz": null};
-                                                   ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:222:41: Context: Write to i@13789
-  <int>[for (int i = 0; oracle("foo"); i++) if (oracle()) ...map else 42];
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:223:41: Context: Write to i@13789
-  <int>{for (int i = 0; oracle("foo"); i++) if (oracle()) ...map else 42, null};
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:224:49: Context: Write to i@13789
-  <String, int>{for (int i = 0; oracle("foo"); i++) if (oracle()) ...list else "bar": 42, "baz": null};
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:225:41: Context: Write to i@13789
-  <int>[for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else ...map];
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:226:41: Context: Write to i@13789
-  <int>{for (int i = 0; oracle("foo"); i++) if (oracle()) 42 else ...map, null};
-                                        ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:227:49: Context: Write to i@13789
-  <String, int>{for (int i = 0; oracle("foo"); i++) if (oracle()) "bar": 42 else ...list, "baz": null};
-                                                ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:267:29: Context: Possible promotion of a@16609
-  List<int> list10 = [if (a is B) a.foo];
-                            ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:268:27: Context: Possible promotion of a@16609
-  Set<int> set10 = {if (a is B) a.foo};
-                          ^^
-pkg/front_end/testcases/general/control_flow_collection_inference.dart:269:32: Context: Possible promotion of a@16609
-  Map<int, int> map10 = {if (a is B) a.foo: a.foo};
-                               ^^
diff --git a/pkg/front_end/testcases/general/escape.dart.type_promotion.expect b/pkg/front_end/testcases/general/escape.dart.type_promotion.expect
deleted file mode 100644
index 4360f9c..0000000
--- a/pkg/front_end/testcases/general/escape.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/general/escape.dart:31:5: Context: Write to x@483
-  x ??= "";
-    ^^^
-pkg/front_end/testcases/general/escape.dart:32:5: Context: Write to x@483
-  x ??= 45;
-    ^^^
diff --git a/pkg/front_end/testcases/general/expressions.dart.type_promotion.expect b/pkg/front_end/testcases/general/expressions.dart.type_promotion.expect
deleted file mode 100644
index 765bde0..0000000
--- a/pkg/front_end/testcases/general/expressions.dart.type_promotion.expect
+++ /dev/null
@@ -1,15 +0,0 @@
-pkg/front_end/testcases/general/expressions.dart:34:5: Context: Write to i@286
-  i = 87;
-    ^
-pkg/front_end/testcases/general/expressions.dart:38:9: Context: Write to i@286
-  print(--i);
-        ^^
-pkg/front_end/testcases/general/expressions.dart:39:9: Context: Write to i@286
-  print(++i);
-        ^^
-pkg/front_end/testcases/general/expressions.dart:40:10: Context: Write to i@286
-  print(i--);
-         ^^
-pkg/front_end/testcases/general/expressions.dart:41:10: Context: Write to i@286
-  print(i++);
-         ^^
diff --git a/pkg/front_end/testcases/general/fallthrough.dart.type_promotion.expect b/pkg/front_end/testcases/general/fallthrough.dart.type_promotion.expect
deleted file mode 100644
index 3758346..0000000
--- a/pkg/front_end/testcases/general/fallthrough.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/fallthrough.dart:9:9: Context: Write to x@254
-      x = 4;
-        ^
diff --git a/pkg/front_end/testcases/general/fibonacci.dart.type_promotion.expect b/pkg/front_end/testcases/general/fibonacci.dart.type_promotion.expect
deleted file mode 100644
index 76596ca..0000000
--- a/pkg/front_end/testcases/general/fibonacci.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/fibonacci.dart:11:28: Context: Write to i@332
-  for (int i = 0; i < 20; i++) {
-                           ^^
diff --git a/pkg/front_end/testcases/general/function_type_is_check.dart.type_promotion.expect b/pkg/front_end/testcases/general/function_type_is_check.dart.type_promotion.expect
deleted file mode 100644
index 30852a8..0000000
--- a/pkg/front_end/testcases/general/function_type_is_check.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/general/function_type_is_check.dart:8:9: Context: Possible promotion of f@272
-  if (f is void Function(Object, StackTrace)) return 1;
-        ^^
-pkg/front_end/testcases/general/function_type_is_check.dart:9:9: Context: Possible promotion of f@272
-  if (f is void Function(Object)) return 10;
-        ^^
-pkg/front_end/testcases/general/function_type_is_check.dart:10:9: Context: Possible promotion of f@272
-  if (f is void Function()) return 100;
-        ^^
diff --git a/pkg/front_end/testcases/general/implicit_new.dart.type_promotion.expect b/pkg/front_end/testcases/general/implicit_new.dart.type_promotion.expect
deleted file mode 100644
index f455e75..0000000
--- a/pkg/front_end/testcases/general/implicit_new.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/general/implicit_new.dart:31:5: Context: Write to x@522
-  x = prefix.Foo();
-    ^
-pkg/front_end/testcases/general/implicit_new.dart:33:5: Context: Write to z@559
-  z = prefix.Bar.named();
-    ^
-pkg/front_end/testcases/general/implicit_new.dart:39:5: Context: Write to l@682
-  l = [prefix.Foo(), prefix.Bar.named()];
-    ^
-pkg/front_end/testcases/general/implicit_new.dart:41:5: Context: Write to m@756
-  m = {"foo": prefix.Foo(), "bar": prefix.Bar.named()};
-    ^
diff --git a/pkg/front_end/testcases/general/implicit_scope_test.dart.type_promotion.expect b/pkg/front_end/testcases/general/implicit_scope_test.dart.type_promotion.expect
deleted file mode 100644
index ab4afb9..0000000
--- a/pkg/front_end/testcases/general/implicit_scope_test.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/general/implicit_scope_test.dart:28:30: Context: Write to i@736
-    for (int i = 0; i < 10; i++) var a = "bar", b = "baz";
-                             ^^
diff --git a/pkg/front_end/testcases/general/invalid_assignment.dart.type_promotion.expect b/pkg/front_end/testcases/general/invalid_assignment.dart.type_promotion.expect
deleted file mode 100644
index 9d791cd..0000000
--- a/pkg/front_end/testcases/general/invalid_assignment.dart.type_promotion.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-pkg/front_end/testcases/general/invalid_assignment.dart:10:5: Context: Write to i@273
-  i = 1;
-    ^
-pkg/front_end/testcases/general/invalid_assignment.dart:11:5: Context: Write to i@273
-  i = s;
-    ^
-pkg/front_end/testcases/general/invalid_assignment.dart:12:5: Context: Write to i@273
-  i ??= 1;
-    ^^^
-pkg/front_end/testcases/general/invalid_assignment.dart:13:5: Context: Write to i@273
-  i ??= s;
-    ^^^
-pkg/front_end/testcases/general/invalid_assignment.dart:14:5: Context: Write to a@288
-  a = new A();
-    ^
-pkg/front_end/testcases/general/invalid_assignment.dart:15:5: Context: Write to a@288
-  a += 1;
-    ^^
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect b/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect
deleted file mode 100644
index 6aa997e..0000000
--- a/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect
+++ /dev/null
@@ -1,21 +0,0 @@
-pkg/front_end/testcases/general/nested_variable_set.dart:11:25: Context: Write to intLocal2@249
-  intLocal1 = intLocal2 = numLocal;
-                        ^
-pkg/front_end/testcases/general/nested_variable_set.dart:11:13: Context: Write to intLocal1@232
-  intLocal1 = intLocal2 = numLocal;
-            ^
-pkg/front_end/testcases/general/nested_variable_set.dart:12:24: Context: Write to numLocal@266
-  intLocal1 = numLocal = intLocal2;
-                       ^
-pkg/front_end/testcases/general/nested_variable_set.dart:12:13: Context: Write to intLocal1@232
-  intLocal1 = numLocal = intLocal2;
-            ^
-pkg/front_end/testcases/general/nested_variable_set.dart:13:12: Context: Write to numLocal@266
-  numLocal = 0.5;
-           ^
-pkg/front_end/testcases/general/nested_variable_set.dart:15:29: Context: Write to doubleLocal@285
-    intLocal1 = doubleLocal = numLocal;
-                            ^
-pkg/front_end/testcases/general/nested_variable_set.dart:15:15: Context: Write to intLocal1@232
-    intLocal1 = doubleLocal = numLocal;
-              ^
diff --git a/pkg/front_end/testcases/nested_variance_test.dart b/pkg/front_end/testcases/general/nested_variance.dart
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart
rename to pkg/front_end/testcases/general/nested_variance.dart
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.hierarchy.expect b/pkg/front_end/testcases/general/nested_variance.dart.hierarchy.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.hierarchy.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.hierarchy.expect
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.legacy.expect b/pkg/front_end/testcases/general/nested_variance.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.legacy.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.legacy.expect
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.legacy.transformed.expect b/pkg/front_end/testcases/general/nested_variance.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.legacy.transformed.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.outline.expect b/pkg/front_end/testcases/general/nested_variance.dart.outline.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.outline.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.outline.expect
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.strong.expect b/pkg/front_end/testcases/general/nested_variance.dart.strong.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.strong.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.strong.expect
diff --git a/pkg/front_end/testcases/nested_variance_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/nested_variance.dart.strong.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_variance_test.dart.strong.transformed.expect
rename to pkg/front_end/testcases/general/nested_variance.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/general/promoted_access.dart.type_promotion.expect b/pkg/front_end/testcases/general/promoted_access.dart.type_promotion.expect
deleted file mode 100644
index 4f2344b..0000000
--- a/pkg/front_end/testcases/general/promoted_access.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/general/promoted_access.dart:3:11: Context: Possible promotion of o@28
-    if (o is Class) {
-          ^^
-pkg/front_end/testcases/general/promoted_access.dart:10:9: Context: Possible promotion of o@28
-  if (o is Class) {
-        ^^
diff --git a/pkg/front_end/testcases/general/statements.dart.type_promotion.expect b/pkg/front_end/testcases/general/statements.dart.type_promotion.expect
deleted file mode 100644
index 5384f47..0000000
--- a/pkg/front_end/testcases/general/statements.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/general/statements.dart:51:10: Context: Write to done@988
-    done = true;
-         ^
-pkg/front_end/testcases/general/statements.dart:101:9: Context: Write to i@1834
-    if (++i < 3) continue;
-        ^^
-pkg/front_end/testcases/general/statements.dart:104:5: Context: Write to i@1834
-  i = 0;
-    ^
-pkg/front_end/testcases/general/statements.dart:108:9: Context: Write to i@1834
-    if (++i < 3) continue OUTER;
-        ^^
diff --git a/pkg/front_end/testcases/general/unsound_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/general/unsound_promotion.dart.type_promotion.expect
deleted file mode 100644
index b7149e2b..0000000
--- a/pkg/front_end/testcases/general/unsound_promotion.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/general/unsound_promotion.dart:20:9: Context: Possible promotion of s@397
-  if (s is A) {
-        ^^
-pkg/front_end/testcases/general/unsound_promotion.dart:31:9: Context: Write to aList@541
-  aList = list;
-        ^
-pkg/front_end/testcases/general/unsound_promotion.dart:33:9: Context: Write to aList@541
-  aList = o;
-        ^
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect
new file mode 100644
index 0000000..c58b401
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    main::foo();
+  }
+  static method foo() → dynamic {}
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect
new file mode 100644
index 0000000..ea10dfd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:2:3: Error: 'await' can only be used in 'async' or 'async*' methods.
+//   await foo();
+//   ^^^^^
+//
+
+  static method main() → dynamic {
+    invalid-expression "org-dartlang-test:///main.dart:2:3: Error: 'await' can only be used in 'async' or 'async*' methods.\n  await foo();\n  ^^^^^";
+  }
+  static method foo() → dynamic {}
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.1.expect
new file mode 100644
index 0000000..f620098
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.1.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("Hello from v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.2.expect
new file mode 100644
index 0000000..fd564fa
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.2.expect
@@ -0,0 +1,37 @@
+main = <No Member>;
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("Hello from v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
+library from "package:foo/foo.dart" as foo {
+
+  import "package:example/b.dart";
+
+  static field dart.core::bool* foo1 = true;
+  static method foo() → dynamic {
+    dart.core::print("Hello from foo");
+    b::b();
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    foo::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.3.expect
new file mode 100644
index 0000000..36a808a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules.yaml.world.3.expect
@@ -0,0 +1,43 @@
+main = <No Member>;
+library from "package:example/b.dart" as b {
+
+  static field dart.core::bool* example011 = true;
+  static method b() → dynamic {
+    dart.core::print("Hello from v0.1.1");
+  }
+}
+library from "package:foo/bar.dart" as bar {
+
+  static method bar() → dynamic {
+    dart.core::print("hello from bar");
+  }
+}
+library from "package:foo/baz.dart" as baz {
+
+  static method baz() → dynamic {
+    dart.core::print("hello from baz");
+  }
+}
+library from "package:foo/foo.dart" as foo {
+
+  import "package:example/b.dart";
+  import "package:foo/bar.dart";
+  import "package:foo/baz.dart";
+
+  static field dart.core::bool* foo2 = true;
+  static method foo() → dynamic {
+    dart.core::print("Hello from foo 2");
+    bar::bar();
+    baz::baz();
+    b::b();
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    foo::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.1.expect
new file mode 100644
index 0000000..d0e1860
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.1.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:module/a.dart";
+
+  class Foo extends a::A {
+    synthetic constructor •() → main::Foo*
+      : super a::A::•()
+      ;
+  }
+}
+library from "package:module/a.dart" as a {
+
+  import "package:module/b.dart";
+
+  class A extends a::A2<b::B*> {
+    synthetic constructor •() → a::A*
+      : super a::A2::•()
+      ;
+  }
+  class A2<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::A2<a::A2::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:module/b.dart" as b {
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.2.expect
new file mode 100644
index 0000000..d0e1860
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml.world.2.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:module/a.dart";
+
+  class Foo extends a::A {
+    synthetic constructor •() → main::Foo*
+      : super a::A::•()
+      ;
+  }
+}
+library from "package:module/a.dart" as a {
+
+  import "package:module/b.dart";
+
+  class A extends a::A2<b::B*> {
+    synthetic constructor •() → a::A*
+      : super a::A2::•()
+      ;
+  }
+  class A2<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::A2<a::A2::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:module/b.dart" as b {
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.1.expect
new file mode 100644
index 0000000..946f8db
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.1.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:module/a.dart";
+
+  class Foo extends a::A {
+    synthetic constructor •() → main::Foo*
+      : super a::A::•()
+      ;
+  }
+}
+library from "package:module/a.dart" as a {
+
+  import "package:module/b.dart";
+
+  class A extends dart.core::Object implements a::A2<b::B*> {
+    synthetic constructor •() → a::A*
+      : super dart.core::Object::•()
+      ;
+  }
+  class A2<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::A2<a::A2::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:module/b.dart" as b {
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.2.expect
new file mode 100644
index 0000000..946f8db
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml.world.2.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:module/a.dart";
+
+  class Foo extends a::A {
+    synthetic constructor •() → main::Foo*
+      : super a::A::•()
+      ;
+  }
+}
+library from "package:module/a.dart" as a {
+
+  import "package:module/b.dart";
+
+  class A extends dart.core::Object implements a::A2<b::B*> {
+    synthetic constructor •() → a::A*
+      : super dart.core::Object::•()
+      ;
+  }
+  class A2<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::A2<a::A2::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:module/b.dart" as b {
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml.world.1.expect
new file mode 100644
index 0000000..c1f1b5c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml.world.1.expect
@@ -0,0 +1,9 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect
new file mode 100644
index 0000000..f66a0d5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:module/a.dart";
+
+  class ABC = a::AB with a::C {
+    synthetic constructor •() → main::ABC*
+      : super a::AB::•()
+      ;
+  }
+}
+library from "package:module/a.dart" as a {
+
+  class A extends dart.core::Object {
+    synthetic constructor •() → a::A*
+      : super dart.core::Object::•()
+      ;
+  }
+  class B extends dart.core::Object {
+    synthetic constructor •() → a::B*
+      : super dart.core::Object::•()
+      ;
+  }
+  class C extends dart.core::Object {
+    synthetic constructor •() → a::C*
+      : super dart.core::Object::•()
+      ;
+  }
+  class AB = a::A with a::B {
+    synthetic constructor •() → a::AB*
+      : super a::A::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.1.expect
new file mode 100644
index 0000000..df74ba9c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.1.expect
@@ -0,0 +1,23 @@
+main = <No Member>;
+library from "package:example/a.dart" as a {
+
+  static field dart.core::bool* example = true;
+  static method a() → dynamic {}
+}
+library from "package:foo/foo.dart" as foo {
+additionalExports = (a::example,
+  a::a)
+
+  export "package:example/a.dart";
+
+  static field dart.core::bool* foo = true;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.2.expect
new file mode 100644
index 0000000..df74ba9c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml.world.2.expect
@@ -0,0 +1,23 @@
+main = <No Member>;
+library from "package:example/a.dart" as a {
+
+  static field dart.core::bool* example = true;
+  static method a() → dynamic {}
+}
+library from "package:foo/foo.dart" as foo {
+additionalExports = (a::example,
+  a::a)
+
+  export "package:example/a.dart";
+
+  static field dart.core::bool* foo = true;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect
new file mode 100644
index 0000000..71e4ef1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "package:foo/foo.dart" as foo {
+
+  static field dart.core::bool* foo = true;
+  final field dynamic lalala_SimulateTransformer /* from null */;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  final field dynamic lalala_SimulateTransformer /* from null */;
+  static method main() → dynamic {
+    dart.core::print(foo::foo);
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect
new file mode 100644
index 0000000..e13a156
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "package:foo/foo.dart" as foo {
+
+  static field dart.core::bool* foo2 = true;
+  final field dynamic lalala_SimulateTransformer /* from null */;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/foo.dart";
+
+  final field dynamic lalala_SimulateTransformer /* from null */;
+  static method main() → dynamic {
+    dart.core::print(foo::foo2);
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml.world.1.expect
new file mode 100644
index 0000000..864ab07
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_4.yaml.world.1.expect
@@ -0,0 +1,39 @@
+main = <No Member>;
+library from "org-dartlang-test:///a.dart" as a {
+
+  import "package:moduleB/b.dart";
+
+  static field dart.core::String* foo = c::baz;
+  static field dart.core::int* x = b::mya2.{b::A2::bar};
+}
+library from "package:moduleB/b.dart" as b {
+additionalExports = (c::baz)
+
+  import "package:moduleC/c.dart";
+  export "package:moduleC/c.dart";
+
+  class A2 extends c::A3 {
+    field dart.core::int* bar = 42;
+    synthetic constructor •() → b::A2*
+      : super c::A3::•()
+      ;
+  }
+  static field b::A2* mya2 = new b::A2::•();
+}
+library from "package:moduleC/c.dart" as c {
+
+  import "package:moduleD/d.dart";
+
+  class A3 extends dart.core::Object {
+    field dart.core::int* foo = 42;
+    synthetic constructor •() → c::A3*
+      : super dart.core::Object::•()
+      ;
+  }
+  static field dart.core::String* baz = "42";
+  static field dart.core::String* baz2 = d::baz3;
+}
+library from "package:moduleD/d.dart" as d {
+
+  static field dart.core::String* baz3 = "baz3";
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml.world.1.expect
new file mode 100644
index 0000000..f3a7ae9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_5.yaml.world.1.expect
@@ -0,0 +1,39 @@
+main = <No Member>;
+library from "org-dartlang-test:///a.dart" as a {
+
+  import "package:moduleB/b.dart";
+
+  static field dart.core::int* foo = b::bVar;
+  static field dart.core::String* foo2 = b::bVarFromC;
+}
+library from "package:moduleB/b.dart" as b {
+
+  import "package:moduleC/c.dart";
+
+  class A2 extends c::A3 {
+    field dart.core::int* bar = 42;
+    synthetic constructor •() → b::A2*
+      : super c::A3::•()
+      ;
+  }
+  static field dart.core::int* bVar = 42;
+  static field dart.core::String* bVarFromC = c::baz2;
+  static field b::A2* mya2 = new b::A2::•();
+}
+library from "package:moduleC/c.dart" as c {
+
+  import "package:moduleD/d.dart";
+
+  class A3 extends dart.core::Object {
+    field dart.core::int* foo = 42;
+    synthetic constructor •() → c::A3*
+      : super dart.core::Object::•()
+      ;
+  }
+  static field dart.core::String* baz = "42";
+  static field dart.core::String* baz2 = d::baz3;
+}
+library from "package:moduleD/d.dart" as d {
+
+  static field dart.core::String* baz3 = "baz3";
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml.world.1.expect
new file mode 100644
index 0000000..64c3715
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_6.yaml.world.1.expect
@@ -0,0 +1,46 @@
+main = <No Member>;
+library from "org-dartlang-test:///a.dart" as a {
+
+  import "package:moduleB/b.dart";
+
+  class A1 extends b::A2 {
+    synthetic constructor •() → a::A1*
+      : super b::A2::•()
+      ;
+    method fooMethod() → dart.core::String*
+      return "42!";
+  }
+  static field dart.core::int* foo = b::bVar;
+  static field dart.core::String* foo2 = b::bVarFromC;
+}
+library from "package:moduleB/b.dart" as b {
+
+  import "package:moduleC/c.dart";
+
+  class A2 extends c::A3 {
+    field dart.core::int* bar = 42;
+    synthetic constructor •() → b::A2*
+      : super c::A3::•()
+      ;
+  }
+  static field dart.core::int* bVar = 42;
+  static field dart.core::String* bVarFromC = c::baz2;
+  static field b::A2* mya2 = new b::A2::•();
+}
+library from "package:moduleC/c.dart" as c {
+
+  import "package:moduleD/d.dart";
+
+  class A3 extends dart.core::Object {
+    field dart.core::int* foo = 42;
+    synthetic constructor •() → c::A3*
+      : super dart.core::Object::•()
+      ;
+  }
+  static field dart.core::String* baz = "42";
+  static field dart.core::String* baz2 = d::baz3;
+}
+library from "package:moduleD/d.dart" as d {
+
+  static field dart.core::String* baz3 = "baz3";
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.1.expect
new file mode 100644
index 0000000..d997be9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.1.expect
@@ -0,0 +1,69 @@
+main = <No Member>;
+library from "org-dartlang-test:///compileme.dart" as com {
+
+  import "package:module/lib1.dart";
+  import "package:module/lib2.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → com::Foo*
+      : super dart.core::Object::•()
+      ;
+    method class1() → lib1::Class1* {
+      lib1::Class1* class1 = new lib1::Class1::•();
+      class1.{lib1::Class1::c3a}.{lib3::Class3a::c3b}.{lib3::Class3b::str}();
+      return class1;
+    }
+  }
+  static method main() → dynamic {
+    lib2::Class2* class2 = new lib2::Class2::•();
+    dart.core::print(class2);
+  }
+}
+library from "package:module/lib1.dart" as lib1 {
+
+  import "package:module/lib3.dart";
+
+  class Class1 extends dart.core::Object {
+    synthetic constructor •() → lib1::Class1*
+      : super dart.core::Object::•()
+      ;
+    get c3a() → lib3::Class3a* {}
+  }
+}
+library from "package:module/lib2.dart" as lib2 {
+
+  import "package:module/lib4.dart";
+
+  class Class2 extends dart.core::Object {
+    synthetic constructor •() → lib2::Class2*
+      : super dart.core::Object::•()
+      ;
+    method cl4() → void {
+      lib4::Class4* class4 = new lib4::Class4::•();
+      dart.core::print(class4);
+    }
+  }
+}
+library from "package:module/lib3.dart" as lib3 {
+
+  class Class3a extends dart.core::Object {
+    synthetic constructor •() → lib3::Class3a*
+      : super dart.core::Object::•()
+      ;
+    get c3b() → lib3::Class3b* {}
+  }
+  class Class3b extends dart.core::Object {
+    synthetic constructor •() → lib3::Class3b*
+      : super dart.core::Object::•()
+      ;
+    method str() → dart.core::String* {}
+  }
+}
+library from "package:module/lib4.dart" as lib4 {
+
+  class Class4 extends dart.core::Object {
+    synthetic constructor •() → lib4::Class4*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.2.expect
new file mode 100644
index 0000000..1ac4a6f
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_7.yaml.world.2.expect
@@ -0,0 +1,63 @@
+main = <No Member>;
+library from "org-dartlang-test:///compileme.dart" as com {
+
+  import "package:module/lib1.dart";
+  import "package:module/lib2.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → com::Foo*
+      ;
+    method class1() → lib1::Class1*
+      ;
+  }
+  static method main() → dynamic
+    ;
+}
+library from "package:module/lib1.dart" as lib1 {
+
+  import "package:module/lib3.dart";
+
+  class Class1 extends dart.core::Object {
+    synthetic constructor •() → lib1::Class1*
+      : super dart.core::Object::•()
+      ;
+    get c3a() → lib3::Class3a* {}
+  }
+}
+library from "package:module/lib2.dart" as lib2 {
+
+  import "package:module/lib4.dart";
+
+  class Class2 extends dart.core::Object {
+    synthetic constructor •() → lib2::Class2*
+      : super dart.core::Object::•()
+      ;
+    method cl4() → void {
+      lib4::Class4* class4 = new lib4::Class4::•();
+      dart.core::print(class4);
+    }
+  }
+}
+library from "package:module/lib3.dart" as lib3 {
+
+  class Class3a extends dart.core::Object {
+    synthetic constructor •() → lib3::Class3a*
+      : super dart.core::Object::•()
+      ;
+    get c3b() → lib3::Class3b* {}
+  }
+  class Class3b extends dart.core::Object {
+    synthetic constructor •() → lib3::Class3b*
+      : super dart.core::Object::•()
+      ;
+    method str() → dart.core::String* {}
+  }
+}
+library from "package:module/lib4.dart" as lib4 {
+
+  class Class4 extends dart.core::Object {
+    synthetic constructor •() → lib4::Class4*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect
new file mode 100644
index 0000000..5680e46
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect
@@ -0,0 +1,40 @@
+main = <No Member>;
+library from "org-dartlang-test:///compileme.dart" as com {
+
+  import "package:module/lib1.dart";
+
+  static method main() → dynamic {
+    lib1::XSet* history = new lib3::XIdentityHashSet::•();
+  }
+}
+library from "package:module/lib1.dart" as lib1 {
+
+  import "package:module/lib2.dart";
+
+  abstract class XSet extends dart.core::Object {
+    static field dynamic _redirecting# = <dynamic>[lib1::XSet::identity];
+    static factory identity() → lib1::XSet*
+      let dynamic #redirecting_factory = lib2::XLinkedHashSet::identity in invalid-expression;
+  }
+}
+library from "package:module/lib2.dart" as lib2 {
+
+  import "package:module/lib1.dart";
+  import "package:module/lib3.dart";
+
+  class XLinkedHashSet extends dart.core::Object implements lib1::XSet {
+    static field dynamic _redirecting# = <dynamic>[lib2::XLinkedHashSet::identity];
+    static factory identity() → lib2::XLinkedHashSet*
+      let dynamic #redirecting_factory = lib3::XIdentityHashSet::• in invalid-expression;
+  }
+}
+library from "package:module/lib3.dart" as lib3 {
+
+  import "package:module/lib2.dart";
+
+  class XIdentityHashSet extends dart.core::Object implements lib2::XLinkedHashSet {
+    constructor •() → lib3::XIdentityHashSet*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.1.expect
new file mode 100644
index 0000000..e8e1f54
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.1.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:moduleA/a.dart";
+
+  static method main() → dynamic {
+    a::A* a = new a::A::•();
+  }
+}
+library from "package:moduleA/a.dart" as a {
+additionalExports = (b::B)
+
+  export "package:moduleB/b.dart";
+
+  class A extends dart.core::Object {
+    synthetic constructor •() → a::A*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:moduleB/b.dart" as b {
+
+  class B extends dart.core::Object {
+    field dart.core::int* foo = 42;
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.2.expect
new file mode 100644
index 0000000..e8e1f54
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml.world.2.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:moduleA/a.dart";
+
+  static method main() → dynamic {
+    a::A* a = new a::A::•();
+  }
+}
+library from "package:moduleA/a.dart" as a {
+additionalExports = (b::B)
+
+  export "package:moduleB/b.dart";
+
+  class A extends dart.core::Object {
+    synthetic constructor •() → a::A*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "package:moduleB/b.dart" as b {
+
+  class B extends dart.core::Object {
+    field dart.core::int* foo = 42;
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.1.expect
new file mode 100644
index 0000000..bb6b7ad
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  part c.dart;
+  static method b() → dynamic {
+    b::c();
+  }
+  static method /* from org-dartlang-test:///c.dart */ c() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.2.expect
new file mode 100644
index 0000000..27d1567
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part.yaml.world.2.expect
@@ -0,0 +1,13 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.1.expect
new file mode 100644
index 0000000..4ed9953
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.1.expect
@@ -0,0 +1,23 @@
+main = <No Member>;
+library libFoo from "org-dartlang-test:///b.dart" as lib {
+
+  part e.dart;
+  part c.dart;
+  part d.dart;
+  static method b() → dynamic {
+    lib::c();
+    lib::d();
+    lib::e();
+  }
+  static method /* from org-dartlang-test:///c.dart */ c() → dynamic {}
+  static method /* from org-dartlang-test:///d.dart */ d() → dynamic {}
+  static method /* from org-dartlang-test:///e.dart */ e() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    lib::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.2.expect
new file mode 100644
index 0000000..a9622d3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_part_if_unused.yaml.world.2.expect
@@ -0,0 +1,9 @@
+main = <No Member>;
+library libFoo from "org-dartlang-test:///main.dart" as lib {
+
+  part c.dart;
+  static method /* from org-dartlang-test:///c.dart */ c() → dynamic {}
+  static method main() → dynamic {
+    lib::c();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.1.expect
new file mode 100644
index 0000000..bb6b7ad
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  part c.dart;
+  static method b() → dynamic {
+    b::c();
+  }
+  static method /* from org-dartlang-test:///c.dart */ c() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.2.expect
new file mode 100644
index 0000000..1a14625
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.2.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.3.expect
new file mode 100644
index 0000000..1a14625
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_non_package_unreferenced_libraries.yaml.world.3.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.1.expect
new file mode 100644
index 0000000..7d83543
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.1.expect
@@ -0,0 +1,13 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.2.expect
new file mode 100644
index 0000000..1a14625
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/cleans_up_uritosource_unreferenced_package_library.yaml.world.2.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.1.expect
new file mode 100644
index 0000000..b2256ee
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.1.expect
@@ -0,0 +1,26 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static const field dart.core::Set<dart.core::String*>* bar = #C6;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field dart.core::Set<dart.core::String*>* foo = #C9;
+  static method main() → dynamic {
+    dart.core::print(#C9);
+    dart.core::print(#C6);
+  }
+}
+constants  {
+  #C1 = "hello"
+  #C2 = null
+  #C3 = "world"
+  #C4 = <dynamic>[#C1, #C2, #C3, #C2]
+  #C5 = dart.core::_ImmutableMap<dart.core::String*, dart.core::Null?> {_kvPairs:#C4}
+  #C6 = dart.collection::_UnmodifiableSet<dart.core::String*> {_map:#C5}
+  #C7 = <dynamic>[]
+  #C8 = dart.core::_ImmutableMap<dart.core::String*, dart.core::Null?> {_kvPairs:#C7}
+  #C9 = dart.collection::_UnmodifiableSet<dart.core::String*> {_map:#C8}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.2.expect
new file mode 100644
index 0000000..264f105
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/constant_set_literal.yaml.world.2.expect
@@ -0,0 +1,25 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static const field dart.core::Set<dart.core::int*>* bar = #C5;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field dart.core::Set<dart.core::String*>* foo = #C8;
+  static method main() → dynamic {
+    dart.core::print(#C8);
+    dart.core::print(#C5);
+  }
+}
+constants  {
+  #C1 = 42
+  #C2 = null
+  #C3 = <dynamic>[#C1, #C2]
+  #C4 = dart.core::_ImmutableMap<dart.core::int*, dart.core::Null?> {_kvPairs:#C3}
+  #C5 = dart.collection::_UnmodifiableSet<dart.core::int*> {_map:#C4}
+  #C6 = <dynamic>[]
+  #C7 = dart.core::_ImmutableMap<dart.core::String*, dart.core::Null?> {_kvPairs:#C6}
+  #C8 = dart.collection::_UnmodifiableSet<dart.core::String*> {_map:#C7}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
new file mode 100644
index 0000000..69ca563
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
@@ -0,0 +1,63 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:3:11: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+//   factory C.e4() async = C;
+//           ^^
+//
+// org-dartlang-test:///main.dart:3:18: Error: Factory bodies can't use 'async', 'async*', or 'sync*'.
+//   factory C.e4() async = C;
+//                  ^^^^^
+//
+// org-dartlang-test:///main.dart:3:24: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   factory C.e4() async = C;
+//                        ^
+//
+// org-dartlang-test:///main.dart:3:26: Error: A value of type 'Type' can't be assigned to a variable of type 'FutureOr<C>'.
+//  - 'Type' is from 'dart:core'.
+//  - 'FutureOr' is from 'dart:async'.
+//  - 'C' is from 'org-dartlang-test:///main.dart'.
+//   factory C.e4() async = C;
+//                          ^
+//
+
+  class C extends dart.core::Object {
+    static field dynamic _redirecting# = <dynamic>[main::C::e4];
+    constructor •() → main::C*
+      : super dart.core::Object::•()
+      ;
+    static factory e4() → main::C* /* originally async */ {
+      final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+      dart.async::FutureOr<dynamic>* :return_value;
+      dynamic :async_stack_trace;
+      dynamic :async_op_then;
+      dynamic :async_op_error;
+      dynamic :await_jump_var = 0;
+      dynamic :await_ctx_var;
+      function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+        try {
+          #L1:
+          {
+            :return_value = let final<BottomType> #t1 = invalid-expression "org-dartlang-test:///main.dart:3:26: Error: A value of type 'Type' can't be assigned to a variable of type 'FutureOr<C>'.\n - 'Type' is from 'dart:core'.\n - 'FutureOr' is from 'dart:async'.\n - 'C' is from 'org-dartlang-test:///main.dart'.\n  factory C.e4() async = C;\n                         ^" in main::C* as{TypeError} dart.async::FutureOr<main::C*>*;
+            break #L1;
+          }
+          dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+          return;
+        }
+        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+          :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+        }
+      :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+      :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+      :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+      :async_completer.start(:async_op);
+      return :async_completer.{dart.async::Completer::future};
+    }
+  }
+  static method main() → void {
+    main::C* c = main::C::e4();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.1.expect
new file mode 100644
index 0000000..7e2a45a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("b");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("Hello no. 0");
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.2.expect
new file mode 100644
index 0000000..77f97dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.2.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:8: Error: Error when reading 'org-dartlang-test:///b.dart': File org-dartlang-test:///b.dart does not exist.
+// import "b.dart";
+//        ^
+//
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.
+//   b();
+//   ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("Hello no. 0");
+    invalid-expression "org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.\n  b();\n  ^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.3.expect
new file mode 100644
index 0000000..78ff159
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.3.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:8: Error: Error when reading 'org-dartlang-test:///b.dart': File org-dartlang-test:///b.dart does not exist.
+// import "b.dart";
+//        ^
+//
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.
+//   b();
+//   ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("Hello no. 1");
+    invalid-expression "org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.\n  b();\n  ^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.4.expect
new file mode 100644
index 0000000..78ff159
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deleting_file.yaml.world.4.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:8: Error: Error when reading 'org-dartlang-test:///b.dart': File org-dartlang-test:///b.dart does not exist.
+// import "b.dart";
+//        ^
+//
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.
+//   b();
+//   ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("Hello no. 1");
+    invalid-expression "org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.\n  b();\n  ^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.1.expect
new file mode 100644
index 0000000..510b8a9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library bLibrary from "org-dartlang-test:///b.dart" as bLi {
+
+  static method foo() → dynamic {
+    dart.core::print("hello from b.dart foo!");
+  }
+}
+library mainLibrary from "org-dartlang-test:///main.dart" as mai {
+
+  import "org-dartlang-test:///b.dart" as b;
+
+  static method main() → dynamic {
+    bLi::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.2.expect
new file mode 100644
index 0000000..cae5df6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library bLibrary from "org-dartlang-test:///b.dart" as bLi {
+
+  static method main() → dynamic {
+    dart.core::print("hello from b!");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.1.expect
new file mode 100644
index 0000000..a6e8b36
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("b");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.2.expect
new file mode 100644
index 0000000..118bd73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml.world.1.expect
new file mode 100644
index 0000000..4c3e6ae
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml.world.1.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "package:untitled/main.dart" as main {
+
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml.world.1.expect
new file mode 100644
index 0000000..b188792
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml.world.1.expect
@@ -0,0 +1,14 @@
+main = <No Member>;
+library from "package:untitled/main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:2:3: Error: Getter not found: 'asdf'.
+//   asdf;
+//   ^^^^
+//
+
+  static method main() → dynamic {
+    invalid-expression "org-dartlang-test:///main.dart:2:3: Error: Getter not found: 'asdf'.\n  asdf;\n  ^^^^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml.world.1.expect
new file mode 100644
index 0000000..b1df83d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml.world.1.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "package:untitled/main.dart" as main {
+
+  static method notMain() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
new file mode 100644
index 0000000..9af8d7f
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
@@ -0,0 +1,21 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application with an experiment enabled (actually, two experiments
+# in this case).
+
+type: newworld
+worlds:
+  - entry: main.dart
+    experiments: triple-shift,non-nullable
+    sources:
+      main.dart: |
+        main() {
+          dynamic x;
+          print(x >>> 2);
+          Class? c = new Class();
+          print(c!);
+        }
+        class Class {}
+    expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml.world.1.expect
new file mode 100644
index 0000000..ce0d68a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Class extends dart.core::Object {
+    synthetic constructor •() → main::Class*
+      : super dart.core::Object::•()
+      ;
+  }
+  static method main() → dynamic {
+    dynamic x;
+    dart.core::print(x.>>>(2));
+    main::Class? c = new main::Class::•();
+    dart.core::print(c!);
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expect
new file mode 100644
index 0000000..118bd73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.2.expect
new file mode 100644
index 0000000..118bd73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect
new file mode 100644
index 0000000..5dfc563
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect
@@ -0,0 +1,64 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class FooEntry extends dart.core::Object {
+    synthetic constructor •() → lib::FooEntry*
+      : super dart.core::Object::•()
+      ;
+  }
+  class BarEntry extends lib::FooEntry {
+    synthetic constructor •() → lib::BarEntry*
+      : super lib::FooEntry::•()
+      ;
+  }
+  abstract class FooTarget extends dart.core::Object {
+    synthetic constructor •() → lib::FooTarget*
+      : super dart.core::Object::•()
+      ;
+    abstract method hello(lib::FooEntry* entry) → void;
+  }
+  abstract class Baz extends dart.core::Object implements lib::FooTarget {
+    synthetic constructor •() → lib::Baz*
+      : super dart.core::Object::•()
+      ;
+    method hello(covariant lib::FooEntry* entry) → void {}
+  }
+  abstract class MyMixin extends lib::Baz {
+  }
+  abstract class Qux extends lib::Baz {
+    synthetic constructor •() → lib::Qux*
+      : super lib::Baz::•()
+      ;
+    method hello(covariant lib::BarEntry* entry) → void {}
+  }
+  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin {
+    synthetic constructor •() → lib::_Quux&Qux&MyMixin*
+      : super lib::Qux::•()
+      ;
+    abstract forwarding-stub method hello(covariant lib::FooEntry* entry) → void;
+  }
+  class Quux extends lib::_Quux&Qux&MyMixin {
+    synthetic constructor •() → lib::Quux*
+      : super lib::_Quux&Qux&MyMixin::•()
+      ;
+    abstract forwarding-stub method hello(covariant lib::FooEntry* entry) → void;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Test extends main::Test2 {
+    synthetic constructor •() → main::Test*
+      : super main::Test2::•()
+      ;
+    method world() → lib::Quux*
+      return null;
+  }
+  abstract class Test2 extends dart.core::Object {
+    synthetic constructor •() → main::Test2*
+      : super dart.core::Object::•()
+      ;
+    abstract method world() → lib::Baz*;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect
new file mode 100644
index 0000000..f0b2d5e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect
@@ -0,0 +1,67 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class FooEntry extends dart.core::Object {
+    synthetic constructor •() → lib::FooEntry*
+      : super dart.core::Object::•()
+      ;
+  }
+  class BarEntry extends lib::FooEntry {
+    synthetic constructor •() → lib::BarEntry*
+      : super lib::FooEntry::•()
+      ;
+  }
+  abstract class FooTarget extends dart.core::Object {
+    synthetic constructor •() → lib::FooTarget*
+      : super dart.core::Object::•()
+      ;
+    abstract method hello(lib::FooEntry* entry) → void;
+  }
+  abstract class Baz extends dart.core::Object implements lib::FooTarget {
+    synthetic constructor •() → lib::Baz*
+      : super dart.core::Object::•()
+      ;
+    method hello(covariant lib::FooEntry* entry) → void {}
+  }
+  abstract class MyMixin extends lib::Baz {
+  }
+  abstract class Qux extends lib::Baz {
+    synthetic constructor •() → lib::Qux*
+      : super lib::Baz::•()
+      ;
+    method hello(covariant lib::BarEntry* entry) → void {}
+  }
+  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin {
+    synthetic constructor •() → lib::_Quux&Qux&MyMixin*
+      : super lib::Qux::•()
+      ;
+    abstract forwarding-stub method hello(covariant lib::FooEntry* entry) → void;
+  }
+  class Quux extends lib::_Quux&Qux&MyMixin {
+    synthetic constructor •() → lib::Quux*
+      : super lib::_Quux&Qux&MyMixin::•()
+      ;
+    abstract forwarding-stub method hello(covariant lib::FooEntry* entry) → void;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Test extends main::Test2 {
+    synthetic constructor •() → main::Test*
+      : super main::Test2::•()
+      ;
+    method world() → lib::Quux*
+      return null;
+  }
+  abstract class Test2 extends dart.core::Object {
+    synthetic constructor •() → main::Test2*
+      : super dart.core::Object::•()
+      ;
+    abstract method world() → lib::Baz*;
+  }
+  static method main() → dynamic {
+    dart.core::print(new main::Test::•());
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.1.expect
new file mode 100644
index 0000000..6ef7b8a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.1.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:core";
+  import "package:package2/lib2.dart";
+  import "package:package2/lib3.dart";
+
+  static method main() → dynamic {
+    lib2::lib2();
+    lib3::lib3();
+  }
+}
+library from "package:package1/lib1.dart" as lib1 {
+
+  static method lib1() → dynamic {
+    return 42;
+  }
+}
+library from "package:package2/lib2.dart" as lib2 {
+
+  static method lib2() → dynamic {
+    return 42;
+  }
+}
+library from "package:package2/lib3.dart" as lib3 {
+
+  import "package:package1/lib1.dart";
+
+  static method lib3() → dynamic {
+    return lib1::lib1();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.2.expect
new file mode 100644
index 0000000..20882e7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.2.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:package1/lib1.dart";
+
+  static method main() → dynamic {
+    lib1::lib1();
+  }
+}
+library from "package:package1/lib1.dart" as lib1 {
+
+  static method lib1() → dynamic {
+    return 42;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.3.expect
new file mode 100644
index 0000000..5087f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.3.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:package2/lib2.dart";
+
+  static method main() → dynamic {
+    lib2::lib2();
+  }
+}
+library from "package:package2/lib2.dart" as lib2 {
+
+  static method lib2() → dynamic {
+    return 42;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.4.expect
new file mode 100644
index 0000000..5087f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_1.yaml.world.4.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:package2/lib2.dart";
+
+  static method main() → dynamic {
+    lib2::lib2();
+  }
+}
+library from "package:package2/lib2.dart" as lib2 {
+
+  static method lib2() → dynamic {
+    return 42;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.1.expect
new file mode 100644
index 0000000..91a004a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.1.expect
@@ -0,0 +1,33 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:package1/lib1.dart";
+  import "package:package1/lib2.dart";
+  import "package:package1/lib3.dart";
+
+  static method main() → dynamic {
+    lib1::lib1();
+    lib2::lib2();
+    lib3::lib3();
+  }
+}
+library from "package:package1/lib1.dart" as lib1 {
+
+  static method lib1() → dynamic {
+    return 42;
+  }
+}
+library from "package:package1/lib2.dart" as lib2 {
+
+  static method lib2() → dynamic {
+    return 42;
+  }
+}
+library from "package:package1/lib3.dart" as lib3 {
+
+  import "package:package1/lib1.dart";
+
+  static method lib3() → dynamic {
+    return lib1::lib1();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.2.expect
new file mode 100644
index 0000000..4a62ec6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_2.yaml.world.2.expect
@@ -0,0 +1,24 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:package1/lib1.dart";
+  import "package:package1/lib2.dart";
+  import "package:package1/lib3.dart";
+
+  static method main() → dynamic {
+    #lib1::lib1();
+    #lib2::lib2();
+    lib3::lib3();
+  }
+}
+library from "package:package1/lib3.dart" as lib3 {
+
+  import "package:package1/lib1.dart";
+
+  static method lib3() → dynamic {
+    return lib3::lib3_1();
+  }
+  static method lib3_1() → dynamic {
+    return #lib1::lib1();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.1.expect
new file mode 100644
index 0000000..91c88a8
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.1.expect
@@ -0,0 +1,48 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:core";
+  import "package:package1/lib1_a.dart";
+
+  static method main() → dynamic {
+    lib::lib1();
+  }
+}
+library from "package:package1/lib1_a.dart" as lib2 {
+additionalExports = (lib::la,
+  lib::lib1)
+
+  import "package:package3/lib3.dart" as lib3;
+  export "package:package1/lib1_b.dart";
+
+  static method lib1a() → dynamic {
+    lib3::lib3();
+  }
+}
+library from "package:package1/lib1_b.dart" as lib {
+
+  import "package:package2/lib2.dart" as lib2;
+
+  static method lib1() → dynamic {
+    return lib::la(null);
+  }
+  static method la(lib22::Foo* f) → dynamic {
+    return 42;
+  }
+}
+library from "package:package2/lib2.dart" as lib22 {
+
+  class Foo extends dart.core::Object {
+    static field dart.core::int* y = 42;
+    synthetic constructor •() → lib22::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+  static field dart.core::int* f = 42;
+}
+library from "package:package3/lib3.dart" as lib3 {
+
+  static method lib3() → dynamic {
+    dart.core::print("lib3");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.2.expect
new file mode 100644
index 0000000..91c88a8
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/incremental_serialization_3.yaml.world.2.expect
@@ -0,0 +1,48 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:core";
+  import "package:package1/lib1_a.dart";
+
+  static method main() → dynamic {
+    lib::lib1();
+  }
+}
+library from "package:package1/lib1_a.dart" as lib2 {
+additionalExports = (lib::la,
+  lib::lib1)
+
+  import "package:package3/lib3.dart" as lib3;
+  export "package:package1/lib1_b.dart";
+
+  static method lib1a() → dynamic {
+    lib3::lib3();
+  }
+}
+library from "package:package1/lib1_b.dart" as lib {
+
+  import "package:package2/lib2.dart" as lib2;
+
+  static method lib1() → dynamic {
+    return lib::la(null);
+  }
+  static method la(lib22::Foo* f) → dynamic {
+    return 42;
+  }
+}
+library from "package:package2/lib2.dart" as lib22 {
+
+  class Foo extends dart.core::Object {
+    static field dart.core::int* y = 42;
+    synthetic constructor •() → lib22::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+  static field dart.core::int* f = 42;
+}
+library from "package:package3/lib3.dart" as lib3 {
+
+  static method lib3() → dynamic {
+    dart.core::print("lib3");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.1.expect
new file mode 100644
index 0000000..9d2d146
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.1.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///foo.dart" as foo {
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → foo::Foo*
+      : super dart.core::Object::•()
+      ;
+    method foo() → dynamic {
+      dart.core::print("Foo!");
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///foo.dart";
+
+  static method main() → dynamic {
+    foo::Foo* foo = new foo::Foo::•();
+    foo.{foo::Foo::foo}();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.2.expect
new file mode 100644
index 0000000..e1510d4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello from main");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.3.expect
new file mode 100644
index 0000000..9d2d146
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_file_then_use_type.yaml.world.3.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///foo.dart" as foo {
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → foo::Foo*
+      : super dart.core::Object::•()
+      ;
+    method foo() → dynamic {
+      dart.core::print("Foo!");
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///foo.dart";
+
+  static method main() → dynamic {
+    foo::Foo* foo = new foo::Foo::•();
+    foo.{foo::Foo::foo}();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.1.expect
new file mode 100644
index 0000000..19ebb12
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.1.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/foo.dart";
+
+  static method main() → dynamic {
+    foo::Foo* foo = new foo::Foo::•();
+    foo.{foo::Foo::foo}();
+  }
+}
+library from "package:mypackage/foo.dart" as foo {
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → foo::Foo*
+      : super dart.core::Object::•()
+      ;
+    method foo() → dynamic {
+      dart.core::print("Foo!");
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.2.expect
new file mode 100644
index 0000000..e1510d4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello from main");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.3.expect
new file mode 100644
index 0000000..19ebb12
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/initialize_with_unused_package_then_use_type.yaml.world.3.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/foo.dart";
+
+  static method main() → dynamic {
+    foo::Foo* foo = new foo::Foo::•();
+    foo.{foo::Foo::foo}();
+  }
+}
+library from "package:mypackage/foo.dart" as foo {
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → foo::Foo*
+      : super dart.core::Object::•()
+      ;
+    method foo() → dynamic {
+      dart.core::print("Foo!");
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect
new file mode 100644
index 0000000..38a3f82
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-malformed-uri:?+package%3Afoo%2Fbar.dart" as ?+p {
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:2:7: Error: Couldn't parse URI ' package:foo/bar.dart':
+//   Scheme not starting with alphabetic character.
+// part ' package:foo/bar.dart';
+//       ^
+//
+
+  part  package:foo/bar.dart;
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.2.expect
new file mode 100644
index 0000000..1a14625
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.2.expect
@@ -0,0 +1,5 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.1.expect
new file mode 100644
index 0000000..63174bf
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.1.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b1");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.2.expect
new file mode 100644
index 0000000..5ddb0bf
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.2.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b2");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.3.expect
new file mode 100644
index 0000000..231c540
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml.world.3.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b3");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml
new file mode 100644
index 0000000..47a379d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml
@@ -0,0 +1,53 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Test that invalidating a part of a package works.
+
+type: newworld
+worlds:
+  - entry: "package:example/main.dart"
+    sources:
+      pkg/example/main.dart: |
+        part "b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      pkg/example/b.dart: |
+        part of "main.dart";
+        b() {
+          print("b1");
+        }
+      .packages: example:pkg/example
+    expectedLibraryCount: 1
+  - entry: "package:example/main.dart"
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - pkg/example/b.dart
+    expectedInvalidatedUri:
+      - "package:example/b.dart"
+    sources:
+      pkg/example/b.dart: |
+        part of "main.dart";
+        b() {
+          print("b2");
+        }
+      .packages: example:pkg/example
+    expectedLibraryCount: 1
+  - entry: "package:example/main.dart"
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - "package:example/b.dart"
+    expectedInvalidatedUri:
+      - "package:example/b.dart"
+    sources:
+      pkg/example/b.dart: |
+        part of "main.dart";
+        b() {
+          print("b3");
+        }
+      .packages: example:pkg/example
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.1.expect
new file mode 100644
index 0000000..63174bf
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.1.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b1");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.2.expect
new file mode 100644
index 0000000..5ddb0bf
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.2.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b2");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.3.expect
new file mode 100644
index 0000000..231c540
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_2.yaml.world.3.expect
@@ -0,0 +1,12 @@
+main = <No Member>;
+library from "package:example/main.dart" as main {
+
+  part b.dart;
+  static method /* from org-dartlang-test:///pkg/example/b.dart */ b() → dynamic {
+    dart.core::print("b3");
+  }
+  static method main() → dynamic {
+    dart.core::print("hello");
+    main::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.1.expect
new file mode 100644
index 0000000..5d55e04
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from b");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.2.expect
new file mode 100644
index 0000000..d52d5b0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.2.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "org-dartlang-test:///c.dart";
+
+  static method b() → dynamic {
+    dart.core::print("hello from b");
+    c::c();
+  }
+}
+library from "org-dartlang-test:///c.dart" as c {
+
+  static method c() → dynamic {
+    dart.core::print("hello from c");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+  import "org-dartlang-test:///nonexisting.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:2:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.3.expect
new file mode 100644
index 0000000..7002b6b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidation_across_compile_time_error.yaml.world.3.expect
@@ -0,0 +1,25 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "org-dartlang-test:///c.dart";
+
+  static method b() → dynamic {
+    dart.core::print("hello from b");
+    c::c();
+  }
+}
+library from "org-dartlang-test:///c.dart" as c {
+
+  static method c() → dynamic {
+    dart.core::print("hello from c");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect
new file mode 100644
index 0000000..4e19cd5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "dart:core";
+
+  static method useString(dart.core::String* s) → void {
+    dart.core::print("Hello from useString: ${s}");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    b::useString("hello");
+  }
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect
new file mode 100644
index 0000000..4e19cd5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "dart:core";
+
+  static method useString(dart.core::String* s) → void {
+    dart.core::print("Hello from useString: ${s}");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    b::useString("hello");
+  }
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect
new file mode 100644
index 0000000..b2daf41
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:3:7: Error: 'Object' doesn't implement 'A<dynamic>' so it can't be used with 'M<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'org-dartlang-test:///main.dart'.
+//  - 'M' is from 'org-dartlang-test:///main.dart'.
+// class C extends Object with M {}
+//       ^
+//
+// org-dartlang-test:///main.dart:3:7: Error: Type parameters could not be inferred for the mixin 'M' because 'Object' does not implement the mixin's supertype constraint 'A<T>'.
+//  - 'A' is from 'org-dartlang-test:///main.dart'.
+// class C extends Object with M {}
+//       ^
+//
+
+  abstract class A<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → main::A<main::A::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  abstract class M<T extends dart.core::Object* = dynamic> extends main::A<main::M::T*> {
+  }
+  abstract class _C&Object&M extends dart.core::Object implements main::M<dynamic> {
+    const synthetic constructor •() → main::_C&Object&M*
+      : super dart.core::Object::•()
+      ;
+  }
+  class C extends main::_C&Object&M {
+    synthetic constructor •() → main::C*
+      : super main::_C&Object&M::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/multiple_entriepoints.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/multiple_entriepoints.yaml.world.1.expect
new file mode 100644
index 0000000..46423d5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/multiple_entriepoints.yaml.world.1.expect
@@ -0,0 +1,13 @@
+main = <No Member>;
+library from "org-dartlang-test:///a.dart" as a {
+
+  static method a() → dynamic {
+    dart.core::print("hello a");
+  }
+}
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello b");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml
new file mode 100644
index 0000000..d3fe395
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml
@@ -0,0 +1,53 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application, change a file, but don't change the outline.
+
+type: newworld
+worlds:
+  - entry: actualMain.dart
+    sources:
+      actualMain.dart: |
+        import 'main.dart' as m;
+        main() {
+          m.main();
+        }
+      main.dart: |
+        import 'libA.dart';
+
+        main() {
+          whatever();
+        }
+        mainHello() {}
+      libA.dart: |
+        import 'main.dart';
+        import 'libB.dart';
+        class Foo {}
+        whatever() {
+          Bar bar = new Bar(new Foo());
+          mainHello();
+        }
+      libB.dart: |
+        import 'libA.dart';
+        class Bar {
+          Foo foo;
+          Bar(this.foo);
+        }
+    expectedLibraryCount: 4
+  - entry: actualMain.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        main() {
+          whatever();
+          mainHello();
+        }
+        mainHello() {}
+    expectedLibraryCount: 4
+    expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.1.expect
new file mode 100644
index 0000000..9a15e2a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.1.expect
@@ -0,0 +1,44 @@
+main = <No Member>;
+library from "org-dartlang-test:///actualMain.dart" as act {
+
+  import "org-dartlang-test:///main.dart" as m;
+
+  static method main() → dynamic {
+    main::main();
+  }
+}
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+  import "org-dartlang-test:///libB.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → libA::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+  static method whatever() → dynamic {
+    libB::Bar* bar = new libB::Bar::•(new libA::Foo::•());
+    main::mainHello();
+  }
+}
+library from "org-dartlang-test:///libB.dart" as libB {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Bar extends dart.core::Object {
+    field libA::Foo* foo;
+    constructor •(libA::Foo* foo) → libB::Bar*
+      : libB::Bar::foo = foo, super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  static method main() → dynamic {
+    libA::whatever();
+  }
+  static method mainHello() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.2.expect
new file mode 100644
index 0000000..dbacc07
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml.world.2.expect
@@ -0,0 +1,45 @@
+main = <No Member>;
+library from "org-dartlang-test:///actualMain.dart" as act {
+
+  import "org-dartlang-test:///main.dart" as m;
+
+  static method main() → dynamic {
+    main::main();
+  }
+}
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+  import "org-dartlang-test:///libB.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → libA::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+  static method whatever() → dynamic {
+    libB::Bar* bar = new libB::Bar::•(new libA::Foo::•());
+    main::mainHello();
+  }
+}
+library from "org-dartlang-test:///libB.dart" as libB {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Bar extends dart.core::Object {
+    field libA::Foo* foo;
+    constructor •(libA::Foo* foo) → libB::Bar*
+      : libB::Bar::foo = foo, super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  static method main() → dynamic {
+    libA::whatever();
+    main::mainHello();
+  }
+  static method mainHello() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml
new file mode 100644
index 0000000..e9a82b1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml
@@ -0,0 +1,60 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application, change a file, but don't change the outline.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          final message;
+          Foo(this.message);
+          @override
+          toString() { return '$message'; }
+        }
+
+        main() {
+          Foo foo = new Foo("hello");
+          whatever(foo);
+          CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+          print(compilationStrategy);
+        }
+
+        enum CompilationStrategy { direct, toKernel, toData, fromData }
+      libA.dart: |
+        import 'main.dart';
+        whatever(Foo foo) {
+          print(foo);
+        }
+    expectedLibraryCount: 2
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          final message;
+          Foo(this.message);
+          @override
+          toString() { return '$message!'; }
+        }
+
+        main() {
+          Foo foo = new Foo("hello");
+          whatever(foo);
+          CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+          print(compilationStrategy);
+        }
+
+        enum CompilationStrategy { direct, toKernel, toData, fromData }
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
new file mode 100644
index 0000000..761708e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
@@ -0,0 +1,60 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+
+  static method whatever(main::Foo* foo) → dynamic {
+    dart.core::print(foo);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    final field dynamic message;
+    constructor •(dynamic message) → main::Foo*
+      : main::Foo::message = message, super dart.core::Object::•()
+      ;
+    @#C1
+    method toString() → dart.core::String* {
+      return "${this.{main::Foo::message}}";
+    }
+  }
+  class CompilationStrategy extends dart.core::Object {
+    final field dart.core::int* index;
+    final field dart.core::String* _name;
+    static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
+    static const field main::CompilationStrategy* direct = #C4;
+    static const field main::CompilationStrategy* toKernel = #C7;
+    static const field main::CompilationStrategy* toData = #C10;
+    static const field main::CompilationStrategy* fromData = #C13;
+    const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+      : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+      ;
+    method toString() → dart.core::String*
+      return this.{=main::CompilationStrategy::_name};
+  }
+  static method main() → dynamic {
+    main::Foo* foo = new main::Foo::•("hello");
+    libA::whatever(foo);
+    main::CompilationStrategy* compilationStrategy = #C4;
+    dart.core::print(compilationStrategy);
+  }
+}
+constants  {
+  #C1 = dart.core::_Override {}
+  #C2 = 0
+  #C3 = "CompilationStrategy.direct"
+  #C4 = main::CompilationStrategy {index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "CompilationStrategy.toKernel"
+  #C7 = main::CompilationStrategy {index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "CompilationStrategy.toData"
+  #C10 = main::CompilationStrategy {index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "CompilationStrategy.fromData"
+  #C13 = main::CompilationStrategy {index:#C11, _name:#C12}
+  #C14 = <main::CompilationStrategy*>[#C4, #C7, #C10, #C13]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
new file mode 100644
index 0000000..7d8e26b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
@@ -0,0 +1,60 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+
+  static method whatever(main::Foo* foo) → dynamic {
+    dart.core::print(foo);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    final field dynamic message;
+    constructor •(dynamic message) → main::Foo*
+      : main::Foo::message = message, super dart.core::Object::•()
+      ;
+    @#C1
+    method toString() → dart.core::String* {
+      return "${this.{main::Foo::message}}!";
+    }
+  }
+  class CompilationStrategy extends dart.core::Object {
+    final field dart.core::int* index;
+    final field dart.core::String* _name;
+    static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
+    static const field main::CompilationStrategy* direct = #C4;
+    static const field main::CompilationStrategy* toKernel = #C7;
+    static const field main::CompilationStrategy* toData = #C10;
+    static const field main::CompilationStrategy* fromData = #C13;
+    const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+      : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+      ;
+    method toString() → dart.core::String*
+      return this.{=main::CompilationStrategy::_name};
+  }
+  static method main() → dynamic {
+    main::Foo* foo = new main::Foo::•("hello");
+    libA::whatever(foo);
+    main::CompilationStrategy* compilationStrategy = #C4;
+    dart.core::print(compilationStrategy);
+  }
+}
+constants  {
+  #C1 = dart.core::_Override {}
+  #C2 = 0
+  #C3 = "CompilationStrategy.direct"
+  #C4 = main::CompilationStrategy {index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "CompilationStrategy.toKernel"
+  #C7 = main::CompilationStrategy {index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "CompilationStrategy.toData"
+  #C10 = main::CompilationStrategy {index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "CompilationStrategy.fromData"
+  #C13 = main::CompilationStrategy {index:#C11, _name:#C12}
+  #C14 = <main::CompilationStrategy*>[#C4, #C7, #C10, #C13]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml
new file mode 100644
index 0000000..4ba8586
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml
@@ -0,0 +1,51 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application, change a file, but don't change the outline.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          const Foo();
+          @override
+          toString() => 'Foo!';
+        }
+
+        main() async {
+          await whatever();
+          print(const Foo());
+        }
+      libA.dart: |
+        whatever() async {
+          await null;
+          return "hello";
+        }
+    expectedLibraryCount: 2
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          const Foo();
+          @override
+          toString() => 'Foo!';
+        }
+
+        main() async {
+          await whatever();
+          print(const Foo());
+          print("Done");
+        }
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
new file mode 100644
index 0000000..7a4295d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
@@ -0,0 +1,80 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  static method whatever() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    dart.async::FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L1:
+        {
+          [yield] let dynamic #t1 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = "hello";
+          break #L1;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.start(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    const constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    @#C1
+    method toString() → dart.core::String*
+      return "Foo!";
+  }
+  static method main() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    dart.async::FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L2:
+        {
+          [yield] let dynamic #t2 = dart.async::_awaitHelper(libA::whatever(), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          dart.core::print(#C2);
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.start(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+constants  {
+  #C1 = dart.core::_Override {}
+  #C2 = main::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
new file mode 100644
index 0000000..42e02f0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
@@ -0,0 +1,81 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  static method whatever() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    dart.async::FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L1:
+        {
+          [yield] let dynamic #t1 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = "hello";
+          break #L1;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.start(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    const constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    @#C1
+    method toString() → dart.core::String*
+      return "Foo!";
+  }
+  static method main() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    dart.async::FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L2:
+        {
+          [yield] let dynamic #t2 = dart.async::_awaitHelper(libA::whatever(), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          dart.core::print(#C2);
+          dart.core::print("Done");
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.start(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+constants  {
+  #C1 = dart.core::_Override {}
+  #C2 = main::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml
new file mode 100644
index 0000000..554f242
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml
@@ -0,0 +1,44 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application, change a file, but don't change the outline.
+# Use it as a mixin, though, so we cannot neccesarily rebuild the bodies only.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          method() {
+            print("A");
+          }
+        }
+      libA.dart: |
+        import 'main.dart';
+
+        class Bar extends Object with Foo {
+          method2() {
+            method();
+          }
+        }
+    expectedLibraryCount: 2
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import 'libA.dart';
+
+        class Foo {
+          method() {
+            print("B");
+          }
+        }
+    expectedLibraryCount: 2
+    # expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
new file mode 100644
index 0000000..a2166d9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
@@ -0,0 +1,35 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo {
+    const synthetic constructor •() → libA::_Bar&Object&Foo*
+      : super dart.core::Object::•()
+      ;
+    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
+      dart.core::print("A");
+    }
+  }
+  class Bar extends libA::_Bar&Object&Foo {
+    synthetic constructor •() → libA::Bar*
+      : super libA::_Bar&Object&Foo::•()
+      ;
+    method method2() → dynamic {
+      this.{main::Foo::method}();
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    method method() → dynamic {
+      dart.core::print("A");
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
new file mode 100644
index 0000000..6ec9787
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
@@ -0,0 +1,35 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+  import "org-dartlang-test:///main.dart";
+
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo {
+    const synthetic constructor •() → libA::_Bar&Object&Foo*
+      : super dart.core::Object::•()
+      ;
+    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
+      dart.core::print("B");
+    }
+  }
+  class Bar extends libA::_Bar&Object&Foo {
+    synthetic constructor •() → libA::Bar*
+      : super libA::_Bar&Object&Foo::•()
+      ;
+    method method2() → dynamic {
+      this.{main::Foo::method}();
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///libA.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    method method() → dynamic {
+      dart.core::print("B");
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.1.expect
new file mode 100644
index 0000000..7efd651
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.1.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("Hello world");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.2.expect
new file mode 100644
index 0000000..ff56e2e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("Hello world!");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.1.expect
new file mode 100644
index 0000000..7efd651
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.1.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("Hello world");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.2.expect
new file mode 100644
index 0000000..ff56e2e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("Hello world!");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect
new file mode 100644
index 0000000..62daba9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect
@@ -0,0 +1,28 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("Hello world");
+  }
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.2.expect
new file mode 100644
index 0000000..98d8a29
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.2.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method lib() → dynamic {
+    return "hello";
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    dart.core::print(lib::lib());
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.3.expect
new file mode 100644
index 0000000..ad8c78c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.3.expect
@@ -0,0 +1,9 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    dart.core::print(#lib1::lib().+("!"));
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect
new file mode 100644
index 0000000..6a5ad02
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method lib() → dynamic {
+    return "hello";
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    dart.core::print(lib::lib());
+  }
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect
new file mode 100644
index 0000000..d78d309
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method lib() → dynamic {
+    return "hello";
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    dart.core::print(lib::lib().+("!!"));
+  }
+}
+
+And 19 platform libraries:
+ - dart:vmservice_io
+ - dart:_http
+ - dart:_builtin
+ - dart:async
+ - dart:cli
+ - dart:collection
+ - dart:convert
+ - dart:core
+ - dart:developer
+ - dart:ffi
+ - dart:nativewrappers
+ - dart:_internal
+ - dart:io
+ - dart:isolate
+ - dart:math
+ - dart:mirrors
+ - dart:typed_data
+ - dart:_vmservice
+ - dart:wasm
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only.yaml.world.1.expect
new file mode 100644
index 0000000..112da80
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only.yaml.world.1.expect
@@ -0,0 +1,6 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic
+    ;
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only_2.yaml.world.1.expect
new file mode 100644
index 0000000..2858e1c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/outline_only_2.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  abstract class Foo extends dart.core::Object {
+    synthetic constructor •() → main::Foo*
+      ;
+    abstract get foo() → dart.core::int*;
+  }
+  class Bar extends dart.core::Object implements main::Foo {
+    static field dart.core::int* _foo;
+    final field dart.core::int* foo;
+    synthetic constructor •() → main::Bar*
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.1.expect
new file mode 100644
index 0000000..7b14759
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.1.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b({dart.core::int* named = #C1}) → dynamic {
+    dart.core::print("b");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:3:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   b(42);
+//    ^
+// org-dartlang-test:///b.dart:1:1: Context: Found this candidate, but the arguments don't match.
+// b({int named}) {
+// ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    invalid-expression "org-dartlang-test:///main.dart:3:4: Error: Too many positional arguments: 0 allowed, but 1 found.\nTry removing the extra positional arguments.\n  b(42);\n   ^";
+  }
+}
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.2.expect
new file mode 100644
index 0000000..c214ed4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml.world.2.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b({dart.core::int* named = #C1}) → dynamic {
+    dart.core::print("b");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:3:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   b(42);
+//    ^
+// org-dartlang-test:///b.dart:5:1: Context: Found this candidate, but the arguments don't match.
+// b({int named}) {
+// ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    invalid-expression "org-dartlang-test:///main.dart:3:4: Error: Too many positional arguments: 0 allowed, but 1 found.\nTry removing the extra positional arguments.\n  b(42);\n   ^";
+  }
+}
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.1.expect
new file mode 100644
index 0000000..0c74f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.1.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:1: Error: Expected ';' after this.
+// asdf
+// ^^^^
+//
+// org-dartlang-test:///b.dart:1:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// asdf
+// ^^^^
+//
+
+  static field dynamic asdf;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.2.expect
new file mode 100644
index 0000000..0c74f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.2.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:1: Error: Expected ';' after this.
+// asdf
+// ^^^^
+//
+// org-dartlang-test:///b.dart:1:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// asdf
+// ^^^^
+//
+
+  static field dynamic asdf;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.3.expect
new file mode 100644
index 0000000..0c74f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.3.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:1: Error: Expected ';' after this.
+// asdf
+// ^^^^
+//
+// org-dartlang-test:///b.dart:1:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// asdf
+// ^^^^
+//
+
+  static field dynamic asdf;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.4.expect
new file mode 100644
index 0000000..0c74f50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.4.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:1: Error: Expected ';' after this.
+// asdf
+// ^^^^
+//
+// org-dartlang-test:///b.dart:1:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// asdf
+// ^^^^
+//
+
+  static field dynamic asdf;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.5.expect
new file mode 100644
index 0000000..a44b5dc
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.5.expect
@@ -0,0 +1,18 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// asdf;
+// ^^^^
+//
+
+  static field dynamic asdf;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.6.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.6.expect
new file mode 100644
index 0000000..adb8a44
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml.world.6.expect
@@ -0,0 +1,10 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method asdf() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect
new file mode 100644
index 0000000..e14d840
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
new file mode 100644
index 0000000..775fa51
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
@@ -0,0 +1,35 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField2 = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(invalid-expression "This assertion failed.");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
new file mode 100644
index 0000000..2a323b6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = #C1;
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField2 = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(invalid-expression "This assertion failed.");
+  }
+}
+constants  {
+  #C1 = lib::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
new file mode 100644
index 0000000..5da4981
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(#C1);
+  }
+}
+constants  {
+  #C1 = lib::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect
new file mode 100644
index 0000000..79519c1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = #C1;
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(#C1);
+  }
+}
+constants  {
+  #C1 = lib::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect
new file mode 100644
index 0000000..e14d840
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
new file mode 100644
index 0000000..ced3bbf
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
@@ -0,0 +1,34 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Bar extends dart.core::Object {
+    final field lib::Foo* x;
+    const constructor •() → lib2::Bar*
+      : lib2::Bar::x = invalid-expression "This assertion failed.", super dart.core::Object::•()
+      ;
+  }
+  static method bar() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib2::bar();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect
new file mode 100644
index 0000000..b212595
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect
@@ -0,0 +1,37 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Bar extends dart.core::Object {
+    final field lib::Foo* x;
+    const constructor •() → lib2::Bar*
+      : lib2::Bar::x = #C1, super dart.core::Object::•()
+      ;
+  }
+  static method bar() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib2::bar();
+  }
+}
+constants  {
+  #C1 = lib::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.1.expect
new file mode 100644
index 0000000..62af8dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.1.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:3:17: Error: Type 'A' not found.
+// class B extends A {}
+//                 ^
+//
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends b::B {
+    synthetic constructor •() → main::A*
+      : super b::B::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.2.expect
new file mode 100644
index 0000000..62af8dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.2.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:3:17: Error: Type 'A' not found.
+// class B extends A {}
+//                 ^
+//
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends b::B {
+    synthetic constructor •() → main::A*
+      : super b::B::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.3.expect
new file mode 100644
index 0000000..62af8dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.3.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:3:17: Error: Type 'A' not found.
+// class B extends A {}
+//                 ^
+//
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends b::B {
+    synthetic constructor •() → main::A*
+      : super b::B::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.4.expect
new file mode 100644
index 0000000..62af8dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.4.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:3:17: Error: Type 'A' not found.
+// class B extends A {}
+//                 ^
+//
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends b::B {
+    synthetic constructor •() → main::A*
+      : super b::B::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.5.expect
new file mode 100644
index 0000000..a8630dc
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.5.expect
@@ -0,0 +1,35 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:3:7: Error: 'B' is a supertype of itself.
+// class B extends A {}
+//       ^
+//
+
+  import "org-dartlang-test:///main.dart";
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:3:7: Error: 'A' is a supertype of itself.
+// class A extends B {}
+//       ^
+//
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends dart.core::Object {
+    synthetic constructor •() → main::A*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.6.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.6.expect
new file mode 100644
index 0000000..3ae163a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml.world.6.expect
@@ -0,0 +1,19 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  class B extends dart.core::Object {
+    synthetic constructor •() → b::B*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  class A extends b::B {
+    synthetic constructor •() → main::A*
+      : super b::B::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.1.expect
new file mode 100644
index 0000000..560b3dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.1.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> {
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.2.expect
new file mode 100644
index 0000000..560b3dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.2.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> {
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.3.expect
new file mode 100644
index 0000000..560b3dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.3.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> {
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.4.expect
new file mode 100644
index 0000000..560b3dd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.4.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> {
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.5.expect
new file mode 100644
index 0000000..bfe5392
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml.world.5.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  class Baz extends a::Bar<dart.core::int*> {
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.1.expect
new file mode 100644
index 0000000..999851d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.1.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  part package:mypackage/c.dart;
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> { // from org-dartlang-test:///mypackage/c.dart
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.2.expect
new file mode 100644
index 0000000..999851d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.2.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  part package:mypackage/c.dart;
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> { // from org-dartlang-test:///mypackage/c.dart
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.3.expect
new file mode 100644
index 0000000..999851d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.3.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  part package:mypackage/c.dart;
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> { // from org-dartlang-test:///mypackage/c.dart
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.4.expect
new file mode 100644
index 0000000..999851d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.4.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  part package:mypackage/c.dart;
+  class Baz extends a::Bar<dart.core::int*> implements a::Foo<dart.core::String*> { // from org-dartlang-test:///mypackage/c.dart
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.5.expect
new file mode 100644
index 0000000..d34698f
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml.world.5.expect
@@ -0,0 +1,32 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart";
+
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  class Foo<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → a::Foo<a::Foo::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class Bar<T extends dart.core::Object* = dynamic> extends a::Foo<a::Bar::T*> {
+    synthetic constructor •() → a::Bar<a::Bar::T*>*
+      : super a::Foo::•()
+      ;
+  }
+}
+library from "package:mypackage/b.dart" as b {
+
+  import "package:mypackage/a.dart";
+
+  part package:mypackage/c.dart;
+  class Baz extends a::Bar<dart.core::int*> { // from org-dartlang-test:///mypackage/c.dart
+    synthetic constructor •() → b::Baz*
+      : super a::Bar::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.1.expect
new file mode 100644
index 0000000..336b536
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.1.expect
@@ -0,0 +1,30 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart" as a;
+
+  static method main() → dynamic {
+    a::main();
+  }
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  static method main() → dynamic {
+    b::foo();
+  }
+}
+library from "package:mypackage/b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.
+//   bar();
+//   ^^^
+//
+
+  static method foo() → dynamic {
+    invalid-expression "org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.\n  bar();\n  ^^^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.2.expect
new file mode 100644
index 0000000..336b536
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.2.expect
@@ -0,0 +1,30 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart" as a;
+
+  static method main() → dynamic {
+    a::main();
+  }
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  static method main() → dynamic {
+    b::foo();
+  }
+}
+library from "package:mypackage/b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.
+//   bar();
+//   ^^^
+//
+
+  static method foo() → dynamic {
+    invalid-expression "org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.\n  bar();\n  ^^^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.3.expect
new file mode 100644
index 0000000..11d08c5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.3.expect
@@ -0,0 +1,31 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart" as a;
+
+  static method main() → dynamic {
+    a::main();
+  }
+}
+library from "package:mypackage/a.dart" as a {
+
+  import "package:mypackage/b.dart";
+
+  static method main() → dynamic {
+    b::foo();
+    b::foo();
+  }
+}
+library from "package:mypackage/b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.
+//   bar();
+//   ^^^
+//
+
+  static method foo() → dynamic {
+    invalid-expression "org-dartlang-test:///mypackage/b.dart:2:3: Error: Method not found: 'bar'.\n  bar();\n  ^^^";
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.4.expect
new file mode 100644
index 0000000..0165c50
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml.world.4.expect
@@ -0,0 +1,17 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:mypackage/a.dart" as a;
+
+  static method main() → dynamic {
+    a::main();
+  }
+}
+library from "package:mypackage/a.dart" as a {
+
+  static method main() → dynamic {
+    a::foo();
+    a::foo();
+  }
+  static method foo() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.1.expect
new file mode 100644
index 0000000..287e451
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.1.expect
@@ -0,0 +1,30 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:21: Error: Expected 0 type arguments.
+// class Bar<X extends Foo<Null>> {}
+//                     ^
+//
+// org-dartlang-test:///lib.dart:3:21: Error: Type 'Foo' not found.
+// class Bar<X extends Foo<Null>> {}
+//                     ^^^
+//
+
+  class Bar<X extends invalid-type = invalid-type> extends dart.core::Object {
+    synthetic constructor •() → lib::Bar<lib::Bar::X*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Foo<X extends lib::Bar<invalid-type>* = lib::Bar<invalid-type>*> extends dart.core::Object {
+    synthetic constructor •() → main::Foo<main::Foo::X*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.2.expect
new file mode 100644
index 0000000..4c8930d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.2.expect
@@ -0,0 +1,30 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:21: Error: Expected 0 type arguments.
+// class Bar<X extends Foo<Null>> {}
+//                     ^
+//
+// org-dartlang-test:///lib.dart:3:21: Error: Type 'Foo' not found.
+// class Bar<X extends Foo<Null>> {}
+//                     ^^^
+//
+
+  class Bar<X extends invalid-type = invalid-type> extends dart.core::Object {
+    synthetic constructor •() → lib::Bar<lib::Bar::X*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Foo extends dart.core::Object {
+    synthetic constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.3.expect
new file mode 100644
index 0000000..f05ee7f
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_6.yaml.world.3.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "org-dartlang-test:///main.dart";
+
+  class Bar<X extends main::Foo<dart.core::Null?>* = main::Foo<dart.core::Null?>*> extends dart.core::Object {
+    synthetic constructor •() → lib::Bar<lib::Bar::X*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class Foo<X extends lib::Bar<main::Foo<dart.core::Null?>*>* = lib::Bar<main::Foo<dart.core::Null?>*>*> extends dart.core::Object {
+    synthetic constructor •() → main::Foo<main::Foo::X*>*
+      : super dart.core::Object::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.1.expect
new file mode 100644
index 0000000..add2ad8
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.1.expect
@@ -0,0 +1,25 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  static method foo() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import 'nonexisting.dart';
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.2.expect
new file mode 100644
index 0000000..901f5bc
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.2.expect
@@ -0,0 +1,26 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  static method foo() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib::foo();
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import 'nonexisting.dart';
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.3.expect
new file mode 100644
index 0000000..f9c00f1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.3.expect
@@ -0,0 +1,33 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  static method foo() → dynamic {}
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  static method bar() → dynamic {
+    dart.core::print("hello");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib2::bar();
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import 'nonexisting.dart';
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.4.expect
new file mode 100644
index 0000000..a737d73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.4.expect
@@ -0,0 +1,33 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+  static method foo() → dynamic {}
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  static method bar() → dynamic {
+    dart.core::print("hello2");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib2::bar();
+  }
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import 'nonexisting.dart';
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.5.expect
new file mode 100644
index 0000000..9a5acc1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_7.yaml.world.5.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method foo() → dynamic {}
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  static method bar() → dynamic {
+    dart.core::print("hello2");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    lib2::bar();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect
new file mode 100644
index 0000000..e14d840
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
new file mode 100644
index 0000000..fd1eaf9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
@@ -0,0 +1,29 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method bar() → dynamic {
+    invalid-expression "This assertion failed.";
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect
new file mode 100644
index 0000000..e14d840
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect
new file mode 100644
index 0000000..e14d840
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
new file mode 100644
index 0000000..b96fc85
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
@@ -0,0 +1,35 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib2.dart";
+
+  static const field lib::Foo* fooField2 = invalid-expression "This assertion failed.";
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(invalid-expression "This assertion failed.");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect
new file mode 100644
index 0000000..06f21af
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect
@@ -0,0 +1,38 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  class Foo extends dart.core::Object {
+    const constructor •(dart.core::int* i) → lib::Foo*
+      : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
+      ;
+  }
+  static method foo() → dynamic {
+    new lib::Foo::•(0);
+  }
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static const field lib::Foo* fooField = #C1;
+}
+library from "org-dartlang-test:///lib3.dart" as lib3 {
+
+  import "org-dartlang-test:///lib2.dart";
+
+  static const field lib::Foo* fooField2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+  import "org-dartlang-test:///lib2.dart";
+  import "org-dartlang-test:///lib3.dart";
+
+  static method main() → dynamic {
+    lib::foo();
+    dart.core::print(#C1);
+  }
+}
+constants  {
+  #C1 = lib::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.1.expect
new file mode 100644
index 0000000..7d86835
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.1.expect
@@ -0,0 +1,36 @@
+main = <No Member>;
+library bLibrary from "org-dartlang-test:///b.dart" as bLi {
+
+  class I<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+    synthetic constructor •() → bLi::I<bLi::I::T*>*
+      : super dart.core::Object::•()
+      ;
+  }
+  class A extends dart.core::Object implements bLi::I<dart.core::int*> {
+    synthetic constructor •() → bLi::A*
+      : super dart.core::Object::•()
+      ;
+  }
+  class B extends dart.core::Object implements bLi::I<dart.core::String*> {
+    synthetic constructor •() → bLi::B*
+      : super dart.core::Object::•()
+      ;
+  }
+  class C extends bLi::A implements bLi::B {
+    synthetic constructor •() → bLi::C*
+      : super bLi::A::•()
+      ;
+  }
+  static method foo() → dynamic {
+    dart.core::print("hello from b.dart foo!");
+    dart.core::print(new bLi::C::•());
+  }
+}
+library mainLibrary from "org-dartlang-test:///main.dart" as mai {
+
+  import "org-dartlang-test:///b.dart" as b;
+
+  static method main() → dynamic {
+    bLi::foo();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.2.expect
new file mode 100644
index 0000000..468dd2a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library mainLibrary from "org-dartlang-test:///main.dart" as mai {
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.1.expect
new file mode 100644
index 0000000..a5961e3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("b");
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.2.expect
new file mode 100644
index 0000000..118bd73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.1.expect
new file mode 100644
index 0000000..5f4155b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.1.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.2.expect
new file mode 100644
index 0000000..1ac0905
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_1.yaml.world.2.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from v0.1.1");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.1.expect
new file mode 100644
index 0000000..5f4155b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.1.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.2.expect
new file mode 100644
index 0000000..1ac0905
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml.world.2.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from v0.1.1");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.1.expect
new file mode 100644
index 0000000..5f4155b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.1.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.2.expect
new file mode 100644
index 0000000..1ac0905
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml.world.2.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from v0.1.1");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.1.expect
new file mode 100644
index 0000000..79c4fd3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from package");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.2.expect
new file mode 100644
index 0000000..9ca4da6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_4.yaml.world.2.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.
+//   b();
+//   ^
+//
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    invalid-expression "org-dartlang-test:///main.dart:4:3: Error: Method not found: 'b'.\n  b();\n  ^";
+  }
+}
+library from "package:example/b.dart" as b {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:8: Error: Not found: 'package:example/b.dart'
+// import "package:example/b.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.1.expect
new file mode 100644
index 0000000..5f4155b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.1.expect
@@ -0,0 +1,27 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/a.dart" as a {
+
+  static method a() → dynamic {
+    a::la1();
+  }
+  static method la1() → dynamic {
+    dart.core::print("v0.1.0");
+  }
+}
+library from "package:example/b.dart" as b {
+
+  import "package:example/a.dart";
+
+  static method b() → dynamic {
+    a::a();
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.2.expect
new file mode 100644
index 0000000..1ac0905
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_uri.yaml.world.2.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:example/b.dart";
+
+  static method main() → dynamic {
+    dart.core::print("hello");
+    b::b();
+  }
+}
+library from "package:example/b.dart" as b {
+
+  static method b() → dynamic {
+    dart.core::print("hello from v0.1.1");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.1.expect
new file mode 100644
index 0000000..3e591c7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.1.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.2.expect
new file mode 100644
index 0000000..3e591c7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml.world.2.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "org-dartlang-test:///nonexisting.dart";
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///b.dart";
+
+}
+library from "org-dartlang-test:///nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///b.dart:1:8: Error: Error when reading 'org-dartlang-test:///nonexisting.dart': File org-dartlang-test:///nonexisting.dart does not exist.
+// import "nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml.world.1.expect
new file mode 100644
index 0000000..f259355
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml.world.1.expect
@@ -0,0 +1,9 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:foo/nonexisting.dart";
+
+}
+
+And 1 platform libraries:
+ - dart:foo/nonexisting.dart
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml.world.1.expect
new file mode 100644
index 0000000..34996e7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-untranslatable-uri:dart%3Afoo%2Fnonexisting.dart' as a part, because it has no 'part of' declaration.
+// part "dart:foo/nonexisting.dart";
+//      ^
+//
+
+  part dart:foo/nonexisting.dart;
+}
+
+And 1 platform libraries:
+ - dart:foo/nonexisting.dart
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml.world.1.expect
new file mode 100644
index 0000000..76e7779
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml.world.1.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-untranslatable-uri:package%3Afoo%2Fnonexisting.dart' as a part, because it has no 'part of' declaration.
+// part "package:foo/nonexisting.dart";
+//      ^
+//
+
+  part package:foo/nonexisting.dart;
+}
+library from "package:foo/nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Not found: 'package:foo/nonexisting.dart'
+// part "package:foo/nonexisting.dart";
+//      ^
+//
+
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml.world.1.expect
new file mode 100644
index 0000000..2ba0d73
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml.world.1.expect
@@ -0,0 +1,16 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:foo/nonexisting.dart";
+
+}
+library from "package:foo/nonexisting.dart" as non {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:8: Error: Not found: 'package:foo/nonexisting.dart'
+// import "package:foo/nonexisting.dart";
+//        ^
+//
+
+}
diff --git a/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect
deleted file mode 100644
index 68100f1..0000000
--- a/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/inference/assign_local.dart:14:32: Context: Write to x@320
-  var /*@ type=int* */ x1 = (x = 1);
-                               ^
-pkg/front_end/testcases/inference/assign_local.dart:15:35: Context: Write to x@320
-  var /*@ type=double* */ x2 = (x = 1.0);
-                                  ^
-pkg/front_end/testcases/inference/assign_local.dart:18:36: Context: Write to y@412
-  var /*@ type=A<int*>* */ y1 = (y = new /*@ typeArgs=int* */ A());
-                                   ^
-pkg/front_end/testcases/inference/assign_local.dart:19:36: Context: Write to y@412
-  var /*@ type=B<int*>* */ y2 = (y = new /*@ typeArgs=int* */ B());
-                                   ^
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect
deleted file mode 100644
index 35fb3a7..0000000
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart:11:5: Context: Write to g@326
-  g = /*@ returnType=String* */ () {
-    ^
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
deleted file mode 100644
index 2fa431c..0000000
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart:17:5: Context: Write to f@353
-  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@ returnType=Null? */ (/*@ type=Object* */ x) =>
-    ^
diff --git a/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect
deleted file mode 100644
index a6f22c3..0000000
--- a/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/bug30620.dart:14:13: Context: Possible promotion of other@335
-      other is A && /*@ promotedType=A* */ other
-            ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect
deleted file mode 100644
index c3d4ebc..0000000
--- a/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/bug30620_b.dart:14:13: Context: Possible promotion of other@335
-      other is A && /*@ promotedType=A* */ other
-            ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect
deleted file mode 100644
index f1d0bf3..0000000
--- a/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/bug30620_c.dart:14:15: Context: Possible promotion of other@335
-    if (other is A && /*@ promotedType=A* */ other
-              ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect
deleted file mode 100644
index bdbeb50..0000000
--- a/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/bug30620_d.dart:8:24: Context: Possible promotion of obj@273
-String foo(obj) => obj is String
-                       ^^
diff --git a/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect
deleted file mode 100644
index 3713459..0000000
--- a/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/bug31132.dart:15:28: Context: Possible promotion of x@318
-  var /*@ type=C* */ y = x is C ? /*@ promotedType=C* */ x : new C();
-                           ^^
diff --git a/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
deleted file mode 100644
index bf317e2..0000000
--- a/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-pkg/front_end/testcases/inference/bug31133.dart:10:31: Context: Write to i@299
-  for (i /*@ target=num::+ */ ++;
-                              ^^
-pkg/front_end/testcases/inference/bug31133.dart:12:30: Context: Write to i@299
-      i /*@ target=num::+ */ ++) {}
-                             ^^
-pkg/front_end/testcases/inference/bug31133.dart:13:29: Context: Write to i@299
-  for (/*@ target=num::+ */ ++i;
-                            ^^
-pkg/front_end/testcases/inference/bug31133.dart:15:30: Context: Write to i@299
-      i /*@ target=num::+ */ ++) {}
-                             ^^
-pkg/front_end/testcases/inference/bug31133.dart:16:31: Context: Write to i@299
-  for (i /*@ target=num::- */ --;
-                              ^^
-pkg/front_end/testcases/inference/bug31133.dart:18:30: Context: Write to i@299
-      i /*@ target=num::- */ --) {}
-                             ^^
-pkg/front_end/testcases/inference/bug31133.dart:19:29: Context: Write to i@299
-  for (/*@ target=num::- */ --i;
-                            ^^
-pkg/front_end/testcases/inference/bug31133.dart:21:30: Context: Write to i@299
-      i /*@ target=num::- */ --) {}
-                             ^^
diff --git a/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect
deleted file mode 100644
index d7cbb44..0000000
--- a/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect
+++ /dev/null
@@ -1,48 +0,0 @@
-pkg/front_end/testcases/inference/bug31436.dart:10:5: Context: Write to g@308
-  g = /*@ returnType=List<Object*>* */ () {
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:13:12: Context: Possible promotion of g@308
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:17:5: Context: Write to g@308
-  g = /*@ returnType=List<int*>* */ () {
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:20:12: Context: Possible promotion of g@308
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:21:12: Context: Possible promotion of g@308
-  assert(g is List<int> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:27:5: Context: Write to g@308
-  g = /*@ returnType=List<Object*>* */ () {
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:30:12: Context: Possible promotion of g@308
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:34:5: Context: Write to o@857
-  o = 3;
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:43:5: Context: Write to g@1323
-  g = /*@ returnType=List<Object*>* */ () => /*@ typeArgs=Object* */ [3];
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:44:12: Context: Possible promotion of g@1323
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:48:5: Context: Write to g@1323
-  g = /*@ returnType=List<int*>* */ () => l;
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:49:12: Context: Possible promotion of g@1323
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:50:12: Context: Possible promotion of g@1323
-  assert(g is List<int> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:56:5: Context: Write to g@1323
-  g = /*@ returnType=List<Object*>* */ () =>
-    ^
-pkg/front_end/testcases/inference/bug31436.dart:58:12: Context: Possible promotion of g@1323
-  assert(g is List<Object> Function());
-           ^^
-pkg/front_end/testcases/inference/bug31436.dart:62:5: Context: Write to o@1842
-  o = 3;
-    ^
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect b/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect
deleted file mode 100644
index 1d0fb56..0000000
--- a/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart:10:5: Context: Write to x@281
-  x = "hi";
-    ^
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect b/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect
deleted file mode 100644
index e2bfbdc..0000000
--- a/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart:10:5: Context: Write to x@295
-  x = "hi";
-    ^
-pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart:11:5: Context: Write to x@295
-  x = 3;
-    ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
deleted file mode 100644
index 40956e2b4..0000000
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart:16:30: Context: Write to i@372
-      i /*@ target=num::+ */ ++) {}
-                             ^^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
index 5002d4f..a003f3b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
@@ -8,7 +8,11 @@
     ;
 }
 static method test() → void {
-  function f<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → void {}
-  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null? {};
+  function f<@#C1 T extends core::Object* = dynamic>() → void {}
+  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = self::Foo {}
+}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
index 5002d4f..a003f3b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
@@ -8,7 +8,11 @@
     ;
 }
 static method test() → void {
-  function f<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → void {}
-  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null? {};
+  function f<@#C1 T extends core::Object* = dynamic>() → void {}
+  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = self::Foo {}
+}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect
deleted file mode 100644
index 19c94fa..0000000
--- a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:10:5: Context: Write to l@288
-  l = /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ "hello"];
-    ^
-pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:11:10: Context: Write to l@288
-  l = (l = /*@ typeArgs=int* */ [1]);
-         ^
-pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:11:5: Context: Write to l@288
-  l = (l = /*@ typeArgs=int* */ [1]);
-    ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect
deleted file mode 100644
index d06c6eb..0000000
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart:12:8: Context: Write to v1@368
-    v1 = <S> /*@returnType=main::::S*/ (/*@type=main::::S*/ x) => x;
-       ^
-pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart:17:8: Context: Write to v2@553
-    v2 = <S> /*@returnType=List<main::::S>*/
-       ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
deleted file mode 100644
index 370bfb82..0000000
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
+++ /dev/null
@@ -1,60 +0,0 @@
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:12:7: Context: Write to v@380
-    v = <T> /*@ returnType=Null? */ (int x) => null;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:13:7: Context: Write to v@380
-    v = <T> /*@ returnType=String* */ (int x) => "hello";
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:14:7: Context: Write to v@380
-    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@ returnType=String* */ (String x) =>
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:16:7: Context: Write to v@380
-    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@ returnType=String* */ (int x) => 3;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:17:7: Context: Write to v@380
-    v = <T> /*@ returnType=String* */ (int x) {
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:24:7: Context: Write to v@889
-    v = <T> /*@ returnType=Null? */ (/*@ type=int* */ x) => null;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:25:7: Context: Write to v@889
-    v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) => "hello";
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:26:7: Context: Write to v@889
-    v = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/ <
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:29:7: Context: Write to v@889
-    v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) {
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:32:7: Context: Write to v@889
-    v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) {
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:39:7: Context: Write to v@1531
-    v = <T> /*@ returnType=Null? */ (int x) => null;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:40:7: Context: Write to v@1531
-    v = <T> /*@ returnType=List<String*>* */ (int x) => /*@ typeArgs=String* */ [
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:43:7: Context: Write to v@1531
-    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@ returnType=List<String*>* */ (String
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:45:7: Context: Write to v@1531
-    v = <T> /*@ returnType=List<String*>* */ (int x) => /*@ typeArgs=String* */ [
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:48:7: Context: Write to v@1531
-    v = <T> /*@ returnType=List<String*>* */ (int x) {
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:59:7: Context: Write to x@2340
-    x = <T> /*@ returnType=int* */ (/*@ type=int* */ x) => x;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:60:7: Context: Write to x@2340
-    x = <T> /*@ returnType=int* */ (/*@ type=int* */ x) => x /*@target=num::+*/ + 1;
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:62:7: Context: Write to y@2568
-    y = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/ <
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:65:7: Context: Write to y@2568
-    y = <T> /*@ returnType=String* */ (/*@ type=int* */ x) => /*info:DYNAMIC_INVOKE, info:DYNAMIC_CAST*/ x
-      ^
-pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:69:7: Context: Write to z@2928
-    z = <T> /*@ returnType=String* */ (/*@ type=String* */ x) =>
-      ^
diff --git a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect
deleted file mode 100644
index 10398e9..0000000
--- a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/for_in_loop_promotion.dart:10:11: Context: Possible promotion of x@318
-    if (x is int) {
-          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
deleted file mode 100644
index 3f8990b..0000000
--- a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/for_loop_empty_condition.dart:9:43: Context: Write to x@287
-  for (num x = 0;; x /*@ target=num::+ */ ++) {
-                                          ^^
-pkg/front_end/testcases/inference/for_loop_empty_condition.dart:11:11: Context: Possible promotion of x@287
-    if (x is int) {
-          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
deleted file mode 100644
index 0a6dba0..0000000
--- a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:10: Context: Write to x@282
-  for (x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
-         ^
-pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:65: Context: Write to x@282
-  for (x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
-                                                                ^^
-pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:11:11: Context: Possible promotion of x@282
-    if (x is int) {
-          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
deleted file mode 100644
index 9171867..0000000
--- a/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/for_loop_promotion.dart:9:69: Context: Write to x@287
-  for (num x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
-                                                                    ^^
-pkg/front_end/testcases/inference/for_loop_promotion.dart:10:11: Context: Possible promotion of x@287
-    if (x is int) {
-          ^^
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect
deleted file mode 100644
index b21b39b..0000000
--- a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/future_then_downwards_method_target.dart:17:5: Context: Write to b@330
-  b = f. /*@ typeArgs=List<int*>* */ /*@target=Future::then*/ then(
-    ^
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect
deleted file mode 100644
index 37b52fb..0000000
--- a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/future_then_upwards_from_block.dart:21:5: Context: Write to b@721
-  b = g;
-    ^
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect
deleted file mode 100644
index a8f55d6..0000000
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart:18:8: Context: Write to list@717
-  list = result2;
-       ^
diff --git a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect
deleted file mode 100644
index b9f3609..0000000
--- a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/generic_functions_return_typedef.dart:15:12: Context: Write to takesInt@458
-  takesInt = y;
-           ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect
deleted file mode 100644
index c1b547d..0000000
--- a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart:20:5: Context: Write to y@448
-  y = /*info:DYNAMIC_CAST*/ z;
-    ^
-pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart:35:5: Context: Write to y@976
-  y = /*info:DYNAMIC_CAST*/ z;
-    ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect
deleted file mode 100644
index 7e3d35f..0000000
--- a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:13:5: Context: Write to y@427
-  y = "world";
-    ^
-pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:14:5: Context: Write to y@427
-  y = /*error:INVALID_ASSIGNMENT*/ 42;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
index 116991f..3f482e4 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.expect
@@ -45,13 +45,13 @@
     let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
     let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
     let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
-    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
-    self::A* v4 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
-    self::B* v3 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
-    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
-    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
-    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = this.{self::Test::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = this.{self::Test::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = this.{self::Test::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v4 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = this.{self::Test::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = this.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v3 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = this.{self::Test::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = this.{self::Test::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = this.{self::Test::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = this.{self::Test::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = this.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = this.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = this.{self::Test::[]}(#t28) in let final void #t30 = this.{self::Test::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
index 116991f..3f482e4 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.strong.transformed.expect
@@ -45,13 +45,13 @@
     let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
     let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
     let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
-    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
-    self::A* v4 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
-    self::B* v3 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
-    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
-    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
-    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = this.{self::Test::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = this.{self::Test::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = this.{self::Test::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v4 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = this.{self::Test::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = this.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v3 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = this.{self::Test::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = this.{self::Test::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = this.{self::Test::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = this.{self::Test::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = this.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = this.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = this.{self::Test::[]}(#t28) in let final void #t30 = this.{self::Test::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
deleted file mode 100644
index cd4a8a3..0000000
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
+++ /dev/null
@@ -1,42 +0,0 @@
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:23:9: Context: Write to local@474
-  local = /*@ typeArgs=B* */ f();
-        ^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:25:34: Context: Write to local@474
-  local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
-                                 ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:27:28: Context: Write to local@474
-  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
-                           ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:29:28: Context: Write to local@474
-  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
-                           ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:31:28: Context: Write to local@474
-  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
-                           ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:33:22: Context: Write to local@474
-  /*@ target=B::- */ --local;
-                     ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:35:28: Context: Write to local@474
-  local /*@ target=B::- */ --;
-                           ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:37:33: Context: Write to local@474
-  var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
-                                ^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:40:38: Context: Write to local@474
-      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
-                                     ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:42:52: Context: Write to local@474
-  var /*@ type=A* */ v3 = local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
-                                                   ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:44:52: Context: Write to local@474
-  var /*@ type=B* */ v4 = local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
-                                                   ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:46:52: Context: Write to local@474
-  var /*@ type=C* */ v5 = local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
-                                                   ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:48:46: Context: Write to local@474
-  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
-                                             ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:51:41: Context: Write to local@474
-      /*@ type=B* */ /*@ target=B::- */ --;
-                                        ^^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
deleted file mode 100644
index e4950d8..0000000
--- a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
+++ /dev/null
@@ -1,69 +0,0 @@
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:13:31: Context: Write to t@343
-  var /*@ type=int* */ v1 = t = getInt();
-                              ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:15:51: Context: Write to t@343
-  var /*@ type=int* */ v4 = t /*@target=num::==*/ ??= getInt();
-                                                  ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:17:50: Context: Write to t@343
-  var /*@ type=int* */ v7 = t /*@target=num::+*/ += getInt();
-                                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:19:49: Context: Write to t@343
-  var /*@ type=int* */ v10 = /*@target=num::+*/ ++t;
-                                                ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:22:43: Context: Write to t@343
-      /*@ type=int* */ /*@target=num::+*/ ++;
-                                          ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
-  var /*@ type=int* */ v1 = t = getInt();
-                              ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:28:31: Context: Write to t@343
-  var /*@ type=num* */ v2 = t = getNum();
-                              ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:30:34: Context: Write to t@343
-  var /*@ type=double* */ v3 = t = getDouble();
-                                 ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:32:51: Context: Write to t@343
-  var /*@ type=num* */ v4 = t /*@target=num::==*/ ??= getInt();
-                                                  ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:34:51: Context: Write to t@343
-  var /*@ type=num* */ v5 = t /*@target=num::==*/ ??= getNum();
-                                                  ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:36:51: Context: Write to t@343
-  var /*@ type=num* */ v6 = t /*@target=num::==*/ ??= getDouble();
-                                                  ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:38:50: Context: Write to t@343
-  var /*@ type=num* */ v7 = t /*@target=num::+*/ += getInt();
-                                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:40:50: Context: Write to t@343
-  var /*@ type=num* */ v8 = t /*@target=num::+*/ += getNum();
-                                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:42:50: Context: Write to t@343
-  var /*@ type=num* */ v9 = t /*@target=num::+*/ += getDouble();
-                                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:44:49: Context: Write to t@343
-  var /*@ type=num* */ v10 = /*@target=num::+*/ ++t;
-                                                ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:47:43: Context: Write to t@343
-      /*@ type=num* */ /*@target=num::+*/ ++;
-                                          ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:51:34: Context: Write to t@343
-  var /*@ type=double* */ v3 = t = getDouble();
-                                 ^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:53:54: Context: Write to t@343
-  var /*@ type=double* */ v6 = t /*@target=num::==*/ ??= getDouble();
-                                                     ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:55:56: Context: Write to t@343
-  var /*@ type=double* */ v7 = t /*@target=double::+*/ += getInt();
-                                                       ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:57:56: Context: Write to t@343
-  var /*@ type=double* */ v8 = t /*@target=double::+*/ += getNum();
-                                                       ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:59:56: Context: Write to t@343
-  var /*@ type=double* */ v9 = t /*@target=double::+*/ += getDouble();
-                                                       ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:61:55: Context: Write to t@343
-  var /*@ type=double* */ v10 = /*@target=double::+*/ ++t;
-                                                      ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:64:49: Context: Write to t@343
-      /*@ type=double* */ /*@target=double::+*/ ++;
-                                                ^^
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect
deleted file mode 100644
index d118f42..0000000
--- a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/infer_consts_transitively_2.dart:15:5: Context: Write to i@353
-  i = m1;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect
deleted file mode 100644
index eeb9f3c..0000000
--- a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:20:5: Context: Write to s@374
-  s = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:21:5: Context: Write to s@374
-  s = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::y*/ y;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:22:5: Context: Write to s@374
-  s = new B(). /*@target=B::z*/ z;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:23:5: Context: Write to s@374
-  s = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::w*/ w;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:25:5: Context: Write to i@383
-  i = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:26:5: Context: Write to i@383
-  i = new B(). /*@target=B::y*/ y;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:27:5: Context: Write to i@383
-  i = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::z*/ z;
-    ^
-pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:28:5: Context: Write to i@383
-  i = new B(). /*@target=B::w*/ w;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect
deleted file mode 100644
index ca48ff3..0000000
--- a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart:14:5: Context: Write to t@372
-  t = x;
-    ^
-pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart:15:5: Context: Write to t@372
-  t = y;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect
deleted file mode 100644
index 298131f..0000000
--- a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart:16:5: Context: Write to t@383
-  t = A.x;
-    ^
-pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart:17:5: Context: Write to t@383
-  t = B.y;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect
deleted file mode 100644
index f5e0605..0000000
--- a/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/infer_statics_transitively.dart:15:5: Context: Write to i@354
-  i = m1;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect
deleted file mode 100644
index bd4a813..0000000
--- a/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/infer_statics_transitively2.dart:15:5: Context: Write to i@335
-  i = y1;
-    ^
-pkg/front_end/testcases/inference/infer_statics_transitively2.dart:16:5: Context: Write to i@335
-  i = y2;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect
deleted file mode 100644
index 3a64db3..0000000
--- a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/inference/infer_statics_transitively3.dart:20:5: Context: Write to i@492
-  i = t1;
-    ^
-pkg/front_end/testcases/inference/infer_statics_transitively3.dart:21:5: Context: Write to i@492
-  i = t2;
-    ^
-pkg/front_end/testcases/inference/infer_statics_transitively3.dart:22:5: Context: Write to i@492
-  i = t3;
-    ^
-pkg/front_end/testcases/inference/infer_statics_transitively3.dart:23:5: Context: Write to i@492
-  i = t4;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect
deleted file mode 100644
index f8cd812..0000000
--- a/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/infer_type_on_var.dart:10:5: Context: Write to x@278
-  x = /*error:INVALID_ASSIGNMENT*/ "hi";
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect
deleted file mode 100644
index 6b30ef6..0000000
--- a/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/infer_type_on_var2.dart:10:5: Context: Write to x@295
-  x = /*error:INVALID_ASSIGNMENT*/ "hi";
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect
deleted file mode 100644
index 5f2268b..0000000
--- a/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:13:7: Context: Write to a@323
-    a = /*error:INVALID_ASSIGNMENT*/ "hi";
-      ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:14:7: Context: Write to a@323
-    a = 3;
-      ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:16:7: Context: Write to b@426
-    b = /*error:INVALID_ASSIGNMENT*/ "hi";
-      ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:17:7: Context: Write to b@426
-    b = 4;
-      ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:19:7: Context: Write to c@529
-    c = /*error:INVALID_ASSIGNMENT*/ "hi";
-      ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:20:7: Context: Write to c@529
-    c = 4;
-      ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect
deleted file mode 100644
index b899119..0000000
--- a/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:12:5: Context: Write to a@307
-  a = /*error:INVALID_ASSIGNMENT*/ "hi";
-    ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:13:5: Context: Write to a@307
-  a = 3;
-    ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:15:5: Context: Write to b@387
-  b = /*error:INVALID_ASSIGNMENT*/ "hi";
-    ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:16:5: Context: Write to b@387
-  b = 4;
-    ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:18:5: Context: Write to c@467
-  c = /*error:INVALID_ASSIGNMENT*/ "hi";
-    ^
-pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:19:5: Context: Write to c@467
-  c = 4;
-    ^
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
deleted file mode 100644
index dabdbac..0000000
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart:11:30: Context: Write to i@299
-      i /*@ target=num::+ */ ++) {
-                             ^^
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect
deleted file mode 100644
index b81ec02..0000000
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect
+++ /dev/null
@@ -1,15 +0,0 @@
-pkg/front_end/testcases/inference/instantiate_tearoff.dart:18:10: Context: Write to func@399
-    func = super. /*@target=C::f*/ f;
-         ^
-pkg/front_end/testcases/inference/instantiate_tearoff.dart:25:8: Context: Write to func@504
-  func = f;
-       ^
-pkg/front_end/testcases/inference/instantiate_tearoff.dart:26:8: Context: Write to func@504
-  func = new C(). /*@target=C::f*/ f;
-       ^
-pkg/front_end/testcases/inference/instantiate_tearoff.dart:27:8: Context: Write to func@504
-  func = C.g;
-       ^
-pkg/front_end/testcases/inference/instantiate_tearoff.dart:28:8: Context: Write to func@504
-  func = h;
-       ^
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect
deleted file mode 100644
index b654339..0000000
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart:10:8: Context: Write to func@314
-  func = f.call;
-       ^
diff --git a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect
deleted file mode 100644
index 82fc53b..0000000
--- a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart:19:10: Context: Write to list@531
-    list = <String>[];
-         ^
diff --git a/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect
deleted file mode 100644
index 88430c6..0000000
--- a/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/inference/logical_or_promotion.dart:16:11: Context: Possible promotion of o@338
-    if (o is A || o is B) {
-          ^^
-pkg/front_end/testcases/inference/logical_or_promotion.dart:16:21: Context: Possible promotion of o@338
-    if (o is A || o is B) {
-                    ^^
-pkg/front_end/testcases/inference/logical_or_promotion.dart:17:13: Context: Possible promotion of o@338
-      if (o is A) {
-            ^^
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.strong.expect b/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
index 1f1aeac..936f05f 100644
--- a/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
@@ -2,23 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
@@ -29,13 +29,13 @@
 static method test1() → dynamic {
   core::Map<core::int*, core::String*>* x = <core::int*, core::String*>{1: "x", 2: "y"};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::int*, "w");
-  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                              ^" in 4.0 as{TypeError} core::int*, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = x;
@@ -43,11 +43,11 @@
 static method test2() → dynamic {
   core::Map<core::num*, core::Pattern*>* x = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::num*, "w");
   x.{core::Map::[]=}(4.0, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::Pattern*);
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
index 1f1aeac..936f05f 100644
--- a/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
@@ -2,23 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
@@ -29,13 +29,13 @@
 static method test1() → dynamic {
   core::Map<core::int*, core::String*>* x = <core::int*, core::String*>{1: "x", 2: "y"};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::int*, "w");
-  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                              ^" in 4.0 as{TypeError} core::int*, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = x;
@@ -43,11 +43,11 @@
 static method test2() → dynamic {
   core::Map<core::num*, core::Pattern*>* x = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::num*, "w");
   x.{core::Map::[]=}(4.0, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::Pattern*);
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
index 4505766..edf1acd 100644
--- a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
@@ -2,23 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 //   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
 //   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
 //   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
@@ -30,24 +30,24 @@
 static field core::Map<core::num*, core::Pattern*>* x2 = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
 static method test1() → dynamic {
   self::x1.{core::Map::[]=}(3, "z");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::int*, "w");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                                                   ^" in 4.0 as{TypeError} core::int*, "u");
-  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = self::x1;
 }
 static method test2() → dynamic {
   self::x2.{core::Map::[]=}(3, "z");
-  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::num*, "w");
   self::x2.{core::Map::[]=}(4.0, "u");
-  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::Pattern*);
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
index 4505766..edf1acd 100644
--- a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
@@ -2,23 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 //   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
 //   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
 //   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
@@ -30,24 +30,24 @@
 static field core::Map<core::num*, core::Pattern*>* x2 = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
 static method test1() → dynamic {
   self::x1.{core::Map::[]=}(3, "z");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::int*, "w");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                                                   ^" in 4.0 as{TypeError} core::int*, "u");
-  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = self::x1;
 }
 static method test2() → dynamic {
   self::x2.{core::Map::[]=}(3, "z");
-  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::num*, "w");
   self::x2.{core::Map::[]=}(4.0, "u");
-  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
+  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::Pattern*);
diff --git a/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect b/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect
deleted file mode 100644
index d405d4e..0000000
--- a/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart:10:5: Context: Write to x@278
-  x = null;
-    ^
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
deleted file mode 100644
index 9262c18..0000000
--- a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:15:5: Context: Write to f@353
-  f = /*@ returnType=Null? */ (/*@ type=Object* */ x) => 'hello';
-    ^
-pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:18:5: Context: Write to g@537
-  g = 'hello';
-    ^
diff --git a/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect
deleted file mode 100644
index 90d61ac..0000000
--- a/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/promote_bounds.dart:17:9: Context: Possible promotion of a@366
-  if (a is String) {
-        ^^
-pkg/front_end/testcases/inference/promote_bounds.dart:21:9: Context: Possible promotion of a@366
-  if (a is C) {
-        ^^
diff --git a/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect
deleted file mode 100644
index dafde1f..0000000
--- a/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/promote_from_logical_rhs.dart:9:14: Context: Possible promotion of a@279
-  if (b && a is int) {
-             ^^
diff --git a/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect
deleted file mode 100644
index acd3603..0000000
--- a/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/inference/promotion_subtype_check.dart:9:9: Context: Possible promotion of x@276
-  if (x is int) {
-        ^^
-pkg/front_end/testcases/inference/promotion_subtype_check.dart:10:36: Context: Possible promotion of x@276
-    if (/*@ promotedType=int* */ x is String) {
-                                   ^^
-pkg/front_end/testcases/inference/promotion_subtype_check.dart:18:9: Context: Possible promotion of x@276
-  if (x is String) {
-        ^^
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect
deleted file mode 100644
index d34e2ca..0000000
--- a/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/try_catch_promotion.dart:20:11: Context: Possible promotion of x@382
-    if (x is D) {
-          ^^
-pkg/front_end/testcases/inference/try_catch_promotion.dart:23:11: Context: Possible promotion of y@385
-    if (y is E) {
-          ^^
diff --git a/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect
deleted file mode 100644
index 364cd86..0000000
--- a/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/inference/type_promotion_simple.dart:10:9: Context: Possible promotion of n@279
-  if (n is int) {
-        ^^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect
deleted file mode 100644
index d1dd6f5..0000000
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart:10:9: Context: Possible promotion of n@279
-  if (n is int) {
-        ^^
-pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart:16:5: Context: Write to n@279
-  n = null;
-    ^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect
deleted file mode 100644
index 3a7414e..0000000
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart:10:9: Context: Possible promotion of n@279
-  if (n is int) {
-        ^^
-pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart:12:7: Context: Write to n@279
-    n = null;
-      ^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect
deleted file mode 100644
index c5a50d4..0000000
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart:10:9: Context: Possible promotion of n@279
-  if (n is int) {
-        ^^
-pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart:14:7: Context: Write to n@279
-    n = null;
-      ^
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect
deleted file mode 100644
index 36b568a..0000000
--- a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:29:5: Context: Write to x@543
-  x = 123;
-    ^
-pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:30:5: Context: Write to x@543
-  x = 'hi';
-    ^
-pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:31:5: Context: Write to y@598
-  y = /*error:INVALID_ASSIGNMENT*/ 123;
-    ^
-pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:32:5: Context: Write to y@598
-  y = /*error:INVALID_ASSIGNMENT*/ 'hi';
-    ^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
index 909ee1a..6b50461 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.expect
@@ -45,13 +45,13 @@
     let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
     let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
     let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
-    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
-    self::A* v3 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
-    self::B* v4 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
-    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
-    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
-    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = this.{self::Test::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = this.{self::Test::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = this.{self::Test::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = this.{self::Test::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = this.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = this.{self::Test::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = this.{self::Test::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = this.{self::Test::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = this.{self::Test::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = this.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = this.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = this.{self::Test::[]}(#t28) in let final void #t30 = this.{self::Test::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
index 909ee1a..6b50461 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.strong.transformed.expect
@@ -45,13 +45,13 @@
     let final self::Index* #t4 = self::f<self::Index*>() in this.{self::Test::[]=}(#t4, this.{self::Test::[]}(#t4).{self::B::&}(self::f<self::A*>()));
     let final self::Index* #t5 = self::f<self::Index*>() in let final self::B* #t6 = this.{self::Test::[]}(#t5).{self::B::-}(1) in let final void #t7 = this.{self::Test::[]=}(#t5, #t6) in #t6;
     let final self::Index* #t8 = self::f<self::Index*>() in this.{self::Test::[]=}(#t8, this.{self::Test::[]}(#t8).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t9 = this in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = self::f<self::B*>() in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
-    self::B* v2 = let final self::Index* #t13 = self::f<self::Index*>() in let final self::B* #t14 = this.{self::Test::[]}(#t13) in #t14.{core::Object::==}(null) ?{self::B*} let final self::B* #t15 = self::f<self::B*>() in let final void #t16 = this.{self::Test::[]=}(#t13, #t15) in #t15 : #t14;
-    self::A* v3 = let final self::Index* #t17 = self::f<self::Index*>() in let final self::A* #t18 = this.{self::Test::[]}(#t17).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t19 = this.{self::Test::[]=}(#t17, #t18) in #t18;
-    self::B* v4 = let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = this.{self::Test::[]}(#t20).{self::B::*}(self::f<self::B*>()) in let final void #t22 = this.{self::Test::[]=}(#t20, #t21) in #t21;
-    self::C* v5 = let final self::Index* #t23 = self::f<self::Index*>() in let final self::C* #t24 = this.{self::Test::[]}(#t23).{self::B::&}(self::f<self::A*>()) in let final void #t25 = this.{self::Test::[]=}(#t23, #t24) in #t24;
-    self::B* v6 = let final self::Index* #t26 = self::f<self::Index*>() in let final self::B* #t27 = this.{self::Test::[]}(#t26).{self::B::-}(1) in let final void #t28 = this.{self::Test::[]=}(#t26, #t27) in #t27;
-    self::B* v7 = let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = this.{self::Test::[]}(#t29) in let final void #t31 = this.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
+    self::B* v1 = let final self::Index* #t9 = self::f<self::Index*>() in let final self::B* #t10 = self::f<self::B*>() in let final void #t11 = this.{self::Test::[]=}(#t9, #t10) in #t10;
+    self::B* v2 = let final self::Index* #t12 = self::f<self::Index*>() in let final self::B* #t13 = this.{self::Test::[]}(#t12) in #t13.{core::Object::==}(null) ?{self::B*} let final self::B* #t14 = self::f<self::B*>() in let final void #t15 = this.{self::Test::[]=}(#t12, #t14) in #t14 : #t13;
+    self::A* v3 = let final self::Index* #t16 = self::f<self::Index*>() in let final self::A* #t17 = this.{self::Test::[]}(#t16).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t18 = this.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v4 = let final self::Index* #t19 = self::f<self::Index*>() in let final self::B* #t20 = this.{self::Test::[]}(#t19).{self::B::*}(self::f<self::B*>()) in let final void #t21 = this.{self::Test::[]=}(#t19, #t20) in #t20;
+    self::C* v5 = let final self::Index* #t22 = self::f<self::Index*>() in let final self::C* #t23 = this.{self::Test::[]}(#t22).{self::B::&}(self::f<self::A*>()) in let final void #t24 = this.{self::Test::[]=}(#t22, #t23) in #t23;
+    self::B* v6 = let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = this.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = this.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v7 = let final self::Index* #t28 = self::f<self::Index*>() in let final self::B* #t29 = this.{self::Test::[]}(#t28) in let final void #t30 = this.{self::Test::[]=}(#t28, #t29.{self::B::-}(1)) in #t29;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
index e9c7b8e..bcb1a68 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.strong.expect
@@ -40,14 +40,14 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test1* #t1 = this in let final core::String* #t2 = "x" in let final core::int* #t3 = self::getInt() in let final void #t4 = #t1.{self::Test1::[]=}(#t2, #t3) in #t3;
-    core::num* v2 = let final self::Test1* #t5 = this in let final core::String* #t6 = "x" in let final core::num* #t7 = self::getNum() as{TypeError} core::int* in let final void #t8 = #t5.{self::Test1::[]=}(#t6, #t7) in #t7;
-    core::int* v4 = let final core::String* #t9 = "x" in let final core::int* #t10 = this.{self::Test1::[]}(#t9) in #t10.{core::num::==}(null) ?{core::int*} let final core::int* #t11 = self::getInt() in let final void #t12 = this.{self::Test1::[]=}(#t9, #t11) in #t11 : #t10;
-    core::num* v5 = let final core::String* #t13 = "x" in let final core::int* #t14 = this.{self::Test1::[]}(#t13) in #t14.{core::num::==}(null) ?{core::num*} let final core::num* #t15 = self::getNum() as{TypeError} core::int* in let final void #t16 = this.{self::Test1::[]=}(#t13, #t15) in #t15 : #t14;
-    core::int* v7 = let final core::String* #t17 = "x" in let final core::int* #t18 = this.{self::Test1::[]}(#t17).{core::num::+}(self::getInt()) in let final void #t19 = this.{self::Test1::[]=}(#t17, #t18) in #t18;
-    core::num* v8 = let final core::String* #t20 = "x" in let final core::num* #t21 = this.{self::Test1::[]}(#t20).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t22 = this.{self::Test1::[]=}(#t20, #t21) in #t21;
-    core::int* v10 = let final core::String* #t23 = "x" in let final core::int* #t24 = this.{self::Test1::[]}(#t23).{core::num::+}(1) in let final void #t25 = this.{self::Test1::[]=}(#t23, #t24) in #t24;
-    core::int* v11 = let final core::String* #t26 = "x" in let final core::int* #t27 = this.{self::Test1::[]}(#t26) in let final void #t28 = this.{self::Test1::[]=}(#t26, #t27.{core::num::+}(1)) in #t27;
+    core::int* v1 = let final core::String* #t1 = "x" in let final core::int* #t2 = self::getInt() in let final void #t3 = this.{self::Test1::[]=}(#t1, #t2) in #t2;
+    core::num* v2 = let final core::String* #t4 = "x" in let final core::num* #t5 = self::getNum() as{TypeError} core::int* in let final void #t6 = this.{self::Test1::[]=}(#t4, #t5) in #t5;
+    core::int* v4 = let final core::String* #t7 = "x" in let final core::int* #t8 = this.{self::Test1::[]}(#t7) in #t8.{core::num::==}(null) ?{core::int*} let final core::int* #t9 = self::getInt() in let final void #t10 = this.{self::Test1::[]=}(#t7, #t9) in #t9 : #t8;
+    core::num* v5 = let final core::String* #t11 = "x" in let final core::int* #t12 = this.{self::Test1::[]}(#t11) in #t12.{core::num::==}(null) ?{core::num*} let final core::num* #t13 = self::getNum() as{TypeError} core::int* in let final void #t14 = this.{self::Test1::[]=}(#t11, #t13) in #t13 : #t12;
+    core::int* v7 = let final core::String* #t15 = "x" in let final core::int* #t16 = this.{self::Test1::[]}(#t15).{core::num::+}(self::getInt()) in let final void #t17 = this.{self::Test1::[]=}(#t15, #t16) in #t16;
+    core::num* v8 = let final core::String* #t18 = "x" in let final core::num* #t19 = this.{self::Test1::[]}(#t18).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t20 = this.{self::Test1::[]=}(#t18, #t19) in #t19;
+    core::int* v10 = let final core::String* #t21 = "x" in let final core::int* #t22 = this.{self::Test1::[]}(#t21).{core::num::+}(1) in let final void #t23 = this.{self::Test1::[]=}(#t21, #t22) in #t22;
+    core::int* v11 = let final core::String* #t24 = "x" in let final core::int* #t25 = this.{self::Test1::[]}(#t24) in let final void #t26 = this.{self::Test1::[]=}(#t24, #t25.{core::num::+}(1)) in #t25;
   }
 }
 abstract class Test2 extends core::Object {
@@ -57,17 +57,17 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test2* #t29 = this in let final core::String* #t30 = "x" in let final core::int* #t31 = self::getInt() in let final void #t32 = #t29.{self::Test2::[]=}(#t30, #t31) in #t31;
-    core::num* v2 = let final self::Test2* #t33 = this in let final core::String* #t34 = "x" in let final core::num* #t35 = self::getNum() in let final void #t36 = #t33.{self::Test2::[]=}(#t34, #t35) in #t35;
-    core::double* v3 = let final self::Test2* #t37 = this in let final core::String* #t38 = "x" in let final core::double* #t39 = self::getDouble() in let final void #t40 = #t37.{self::Test2::[]=}(#t38, #t39) in #t39;
-    core::int* v4 = let final core::String* #t41 = "x" in let final core::int* #t42 = this.{self::Test2::[]}(#t41) in #t42.{core::num::==}(null) ?{core::int*} let final core::int* #t43 = self::getInt() in let final void #t44 = this.{self::Test2::[]=}(#t41, #t43) in #t43 : #t42;
-    core::num* v5 = let final core::String* #t45 = "x" in let final core::int* #t46 = this.{self::Test2::[]}(#t45) in #t46.{core::num::==}(null) ?{core::num*} let final core::num* #t47 = self::getNum() in let final void #t48 = this.{self::Test2::[]=}(#t45, #t47) in #t47 : #t46;
-    core::num* v6 = let final core::String* #t49 = "x" in let final core::int* #t50 = this.{self::Test2::[]}(#t49) in #t50.{core::num::==}(null) ?{core::num*} let final core::double* #t51 = self::getDouble() in let final void #t52 = this.{self::Test2::[]=}(#t49, #t51) in #t51 : #t50;
-    core::int* v7 = let final core::String* #t53 = "x" in let final core::int* #t54 = this.{self::Test2::[]}(#t53).{core::num::+}(self::getInt()) in let final void #t55 = this.{self::Test2::[]=}(#t53, #t54) in #t54;
-    core::num* v8 = let final core::String* #t56 = "x" in let final core::num* #t57 = this.{self::Test2::[]}(#t56).{core::num::+}(self::getNum()) in let final void #t58 = this.{self::Test2::[]=}(#t56, #t57) in #t57;
-    core::double* v9 = let final core::String* #t59 = "x" in let final core::double* #t60 = this.{self::Test2::[]}(#t59).{core::num::+}(self::getDouble()) in let final void #t61 = this.{self::Test2::[]=}(#t59, #t60) in #t60;
-    core::int* v10 = let final core::String* #t62 = "x" in let final core::int* #t63 = this.{self::Test2::[]}(#t62).{core::num::+}(1) in let final void #t64 = this.{self::Test2::[]=}(#t62, #t63) in #t63;
-    core::int* v11 = let final core::String* #t65 = "x" in let final core::int* #t66 = this.{self::Test2::[]}(#t65) in let final void #t67 = this.{self::Test2::[]=}(#t65, #t66.{core::num::+}(1)) in #t66;
+    core::int* v1 = let final core::String* #t27 = "x" in let final core::int* #t28 = self::getInt() in let final void #t29 = this.{self::Test2::[]=}(#t27, #t28) in #t28;
+    core::num* v2 = let final core::String* #t30 = "x" in let final core::num* #t31 = self::getNum() in let final void #t32 = this.{self::Test2::[]=}(#t30, #t31) in #t31;
+    core::double* v3 = let final core::String* #t33 = "x" in let final core::double* #t34 = self::getDouble() in let final void #t35 = this.{self::Test2::[]=}(#t33, #t34) in #t34;
+    core::int* v4 = let final core::String* #t36 = "x" in let final core::int* #t37 = this.{self::Test2::[]}(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final core::int* #t38 = self::getInt() in let final void #t39 = this.{self::Test2::[]=}(#t36, #t38) in #t38 : #t37;
+    core::num* v5 = let final core::String* #t40 = "x" in let final core::int* #t41 = this.{self::Test2::[]}(#t40) in #t41.{core::num::==}(null) ?{core::num*} let final core::num* #t42 = self::getNum() in let final void #t43 = this.{self::Test2::[]=}(#t40, #t42) in #t42 : #t41;
+    core::num* v6 = let final core::String* #t44 = "x" in let final core::int* #t45 = this.{self::Test2::[]}(#t44) in #t45.{core::num::==}(null) ?{core::num*} let final core::double* #t46 = self::getDouble() in let final void #t47 = this.{self::Test2::[]=}(#t44, #t46) in #t46 : #t45;
+    core::int* v7 = let final core::String* #t48 = "x" in let final core::int* #t49 = this.{self::Test2::[]}(#t48).{core::num::+}(self::getInt()) in let final void #t50 = this.{self::Test2::[]=}(#t48, #t49) in #t49;
+    core::num* v8 = let final core::String* #t51 = "x" in let final core::num* #t52 = this.{self::Test2::[]}(#t51).{core::num::+}(self::getNum()) in let final void #t53 = this.{self::Test2::[]=}(#t51, #t52) in #t52;
+    core::double* v9 = let final core::String* #t54 = "x" in let final core::double* #t55 = this.{self::Test2::[]}(#t54).{core::num::+}(self::getDouble()) in let final void #t56 = this.{self::Test2::[]=}(#t54, #t55) in #t55;
+    core::int* v10 = let final core::String* #t57 = "x" in let final core::int* #t58 = this.{self::Test2::[]}(#t57).{core::num::+}(1) in let final void #t59 = this.{self::Test2::[]=}(#t57, #t58) in #t58;
+    core::int* v11 = let final core::String* #t60 = "x" in let final core::int* #t61 = this.{self::Test2::[]}(#t60) in let final void #t62 = this.{self::Test2::[]=}(#t60, #t61.{core::num::+}(1)) in #t61;
   }
 }
 abstract class Test3 extends core::Object {
@@ -77,21 +77,21 @@
   abstract operator [](core::String* s) → core::int*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final self::Test3* #t68 = this in let final core::String* #t69 = "x" in let final core::num* #t70 = self::getNum() as{TypeError} core::double* in let final void #t71 = #t68.{self::Test3::[]=}(#t69, #t70) in #t70;
-    core::double* v3 = let final self::Test3* #t72 = this in let final core::String* #t73 = "x" in let final core::double* #t74 = self::getDouble() in let final void #t75 = #t72.{self::Test3::[]=}(#t73, #t74) in #t74;
-    core::num* v5 = let final core::String* #t76 = "x" in let final core::int* #t77 = this.{self::Test3::[]}(#t76) in #t77.{core::num::==}(null) ?{core::num*} let final core::num* #t78 = self::getNum() as{TypeError} core::double* in let final void #t79 = this.{self::Test3::[]=}(#t76, #t78) in #t78 : #t77;
-    core::num* v6 = let final core::String* #t80 = "x" in let final core::int* #t81 = this.{self::Test3::[]}(#t80) in #t81.{core::num::==}(null) ?{core::num*} let final core::double* #t82 = self::getDouble() in let final void #t83 = this.{self::Test3::[]=}(#t80, #t82) in #t82 : #t81;
-    core::int* v7 = let final core::String* #t84 = "x" in let final core::int* #t85 = let final<BottomType> #t86 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:111:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+    core::num* v2 = let final core::String* #t63 = "x" in let final core::num* #t64 = self::getNum() as{TypeError} core::double* in let final void #t65 = this.{self::Test3::[]=}(#t63, #t64) in #t64;
+    core::double* v3 = let final core::String* #t66 = "x" in let final core::double* #t67 = self::getDouble() in let final void #t68 = this.{self::Test3::[]=}(#t66, #t67) in #t67;
+    core::num* v5 = let final core::String* #t69 = "x" in let final core::int* #t70 = this.{self::Test3::[]}(#t69) in #t70.{core::num::==}(null) ?{core::num*} let final core::num* #t71 = self::getNum() as{TypeError} core::double* in let final void #t72 = this.{self::Test3::[]=}(#t69, #t71) in #t71 : #t70;
+    core::num* v6 = let final core::String* #t73 = "x" in let final core::int* #t74 = this.{self::Test3::[]}(#t73) in #t74.{core::num::==}(null) ?{core::num*} let final core::double* #t75 = self::getDouble() in let final void #t76 = this.{self::Test3::[]=}(#t73, #t75) in #t75 : #t74;
+    core::int* v7 = let final core::String* #t77 = "x" in let final core::int* #t78 = let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:111:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
         /*@target=num::+*/ += getInt();
-                           ^" in this.{self::Test3::[]}(#t84).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t87 = this.{self::Test3::[]=}(#t84, #t85) in #t85;
-    core::num* v8 = let final core::String* #t88 = "x" in let final core::num* #t89 = this.{self::Test3::[]}(#t88).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t90 = this.{self::Test3::[]=}(#t88, #t89) in #t89;
-    core::double* v9 = let final core::String* #t91 = "x" in let final core::double* #t92 = this.{self::Test3::[]}(#t91).{core::num::+}(self::getDouble()) in let final void #t93 = this.{self::Test3::[]=}(#t91, #t92) in #t92;
-    core::int* v10 = let final core::String* #t94 = "x" in let final core::int* #t95 = let final<BottomType> #t96 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:121:51: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+                           ^" in this.{self::Test3::[]}(#t77).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t80 = this.{self::Test3::[]=}(#t77, #t78) in #t78;
+    core::num* v8 = let final core::String* #t81 = "x" in let final core::num* #t82 = this.{self::Test3::[]}(#t81).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t83 = this.{self::Test3::[]=}(#t81, #t82) in #t82;
+    core::double* v9 = let final core::String* #t84 = "x" in let final core::double* #t85 = this.{self::Test3::[]}(#t84).{core::num::+}(self::getDouble()) in let final void #t86 = this.{self::Test3::[]=}(#t84, #t85) in #t85;
+    core::int* v10 = let final core::String* #t87 = "x" in let final core::int* #t88 = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:121:51: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
     var /*@ type=int* */ v10 = /*@target=num::+*/ ++this
-                                                  ^" in this.{self::Test3::[]}(#t94).{core::num::+}(1) as{TypeError} core::double* in let final void #t97 = this.{self::Test3::[]=}(#t94, #t95) in #t95;
-    core::int* v11 = let final core::String* #t98 = "x" in let final core::int* #t99 = this.{self::Test3::[]}(#t98) in let final void #t100 = this.{self::Test3::[]=}(#t98, let final<BottomType> #t101 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:126:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+                                                  ^" in this.{self::Test3::[]}(#t87).{core::num::+}(1) as{TypeError} core::double* in let final void #t90 = this.{self::Test3::[]=}(#t87, #t88) in #t88;
+    core::int* v11 = let final core::String* #t91 = "x" in let final core::int* #t92 = this.{self::Test3::[]}(#t91) in let final void #t93 = this.{self::Test3::[]=}(#t91, let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:126:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
         /*@target=num::+*/ ++;
-                           ^" in #t99.{core::num::+}(1) as{TypeError} core::double*) in #t99;
+                           ^" in #t92.{core::num::+}(1) as{TypeError} core::double*) in #t92;
   }
 }
 abstract class Test4 extends core::Object {
@@ -101,14 +101,14 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test4* #t102 = this in let final core::String* #t103 = "x" in let final core::int* #t104 = self::getInt() in let final void #t105 = #t102.{self::Test4::[]=}(#t103, #t104) in #t104;
-    core::num* v2 = let final self::Test4* #t106 = this in let final core::String* #t107 = "x" in let final core::num* #t108 = self::getNum() as{TypeError} core::int* in let final void #t109 = #t106.{self::Test4::[]=}(#t107, #t108) in #t108;
-    core::num* v4 = let final core::String* #t110 = "x" in let final core::num* #t111 = this.{self::Test4::[]}(#t110) in #t111.{core::num::==}(null) ?{core::num*} let final core::int* #t112 = self::getInt() in let final void #t113 = this.{self::Test4::[]=}(#t110, #t112) in #t112 : #t111;
-    core::num* v5 = let final core::String* #t114 = "x" in let final core::num* #t115 = this.{self::Test4::[]}(#t114) in #t115.{core::num::==}(null) ?{core::num*} let final core::num* #t116 = self::getNum() as{TypeError} core::int* in let final void #t117 = this.{self::Test4::[]=}(#t114, #t116) in #t116 : #t115;
-    core::num* v7 = let final core::String* #t118 = "x" in let final core::num* #t119 = this.{self::Test4::[]}(#t118).{core::num::+}(self::getInt()) as{TypeError} core::int* in let final void #t120 = this.{self::Test4::[]=}(#t118, #t119) in #t119;
-    core::num* v8 = let final core::String* #t121 = "x" in let final core::num* #t122 = this.{self::Test4::[]}(#t121).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t123 = this.{self::Test4::[]=}(#t121, #t122) in #t122;
-    core::num* v10 = let final core::String* #t124 = "x" in let final core::num* #t125 = this.{self::Test4::[]}(#t124).{core::num::+}(1) as{TypeError} core::int* in let final void #t126 = this.{self::Test4::[]=}(#t124, #t125) in #t125;
-    core::num* v11 = let final core::String* #t127 = "x" in let final core::num* #t128 = this.{self::Test4::[]}(#t127) in let final void #t129 = this.{self::Test4::[]=}(#t127, #t128.{core::num::+}(1) as{TypeError} core::int*) in #t128;
+    core::int* v1 = let final core::String* #t95 = "x" in let final core::int* #t96 = self::getInt() in let final void #t97 = this.{self::Test4::[]=}(#t95, #t96) in #t96;
+    core::num* v2 = let final core::String* #t98 = "x" in let final core::num* #t99 = self::getNum() as{TypeError} core::int* in let final void #t100 = this.{self::Test4::[]=}(#t98, #t99) in #t99;
+    core::num* v4 = let final core::String* #t101 = "x" in let final core::num* #t102 = this.{self::Test4::[]}(#t101) in #t102.{core::num::==}(null) ?{core::num*} let final core::int* #t103 = self::getInt() in let final void #t104 = this.{self::Test4::[]=}(#t101, #t103) in #t103 : #t102;
+    core::num* v5 = let final core::String* #t105 = "x" in let final core::num* #t106 = this.{self::Test4::[]}(#t105) in #t106.{core::num::==}(null) ?{core::num*} let final core::num* #t107 = self::getNum() as{TypeError} core::int* in let final void #t108 = this.{self::Test4::[]=}(#t105, #t107) in #t107 : #t106;
+    core::num* v7 = let final core::String* #t109 = "x" in let final core::num* #t110 = this.{self::Test4::[]}(#t109).{core::num::+}(self::getInt()) as{TypeError} core::int* in let final void #t111 = this.{self::Test4::[]=}(#t109, #t110) in #t110;
+    core::num* v8 = let final core::String* #t112 = "x" in let final core::num* #t113 = this.{self::Test4::[]}(#t112).{core::num::+}(self::getNum()) as{TypeError} core::int* in let final void #t114 = this.{self::Test4::[]=}(#t112, #t113) in #t113;
+    core::num* v10 = let final core::String* #t115 = "x" in let final core::num* #t116 = this.{self::Test4::[]}(#t115).{core::num::+}(1) as{TypeError} core::int* in let final void #t117 = this.{self::Test4::[]=}(#t115, #t116) in #t116;
+    core::num* v11 = let final core::String* #t118 = "x" in let final core::num* #t119 = this.{self::Test4::[]}(#t118) in let final void #t120 = this.{self::Test4::[]=}(#t118, #t119.{core::num::+}(1) as{TypeError} core::int*) in #t119;
   }
 }
 abstract class Test5 extends core::Object {
@@ -118,17 +118,17 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test5* #t130 = this in let final core::String* #t131 = "x" in let final core::int* #t132 = self::getInt() in let final void #t133 = #t130.{self::Test5::[]=}(#t131, #t132) in #t132;
-    core::num* v2 = let final self::Test5* #t134 = this in let final core::String* #t135 = "x" in let final core::num* #t136 = self::getNum() in let final void #t137 = #t134.{self::Test5::[]=}(#t135, #t136) in #t136;
-    core::double* v3 = let final self::Test5* #t138 = this in let final core::String* #t139 = "x" in let final core::double* #t140 = self::getDouble() in let final void #t141 = #t138.{self::Test5::[]=}(#t139, #t140) in #t140;
-    core::num* v4 = let final core::String* #t142 = "x" in let final core::num* #t143 = this.{self::Test5::[]}(#t142) in #t143.{core::num::==}(null) ?{core::num*} let final core::int* #t144 = self::getInt() in let final void #t145 = this.{self::Test5::[]=}(#t142, #t144) in #t144 : #t143;
-    core::num* v5 = let final core::String* #t146 = "x" in let final core::num* #t147 = this.{self::Test5::[]}(#t146) in #t147.{core::num::==}(null) ?{core::num*} let final core::num* #t148 = self::getNum() in let final void #t149 = this.{self::Test5::[]=}(#t146, #t148) in #t148 : #t147;
-    core::num* v6 = let final core::String* #t150 = "x" in let final core::num* #t151 = this.{self::Test5::[]}(#t150) in #t151.{core::num::==}(null) ?{core::num*} let final core::double* #t152 = self::getDouble() in let final void #t153 = this.{self::Test5::[]=}(#t150, #t152) in #t152 : #t151;
-    core::num* v7 = let final core::String* #t154 = "x" in let final core::num* #t155 = this.{self::Test5::[]}(#t154).{core::num::+}(self::getInt()) in let final void #t156 = this.{self::Test5::[]=}(#t154, #t155) in #t155;
-    core::num* v8 = let final core::String* #t157 = "x" in let final core::num* #t158 = this.{self::Test5::[]}(#t157).{core::num::+}(self::getNum()) in let final void #t159 = this.{self::Test5::[]=}(#t157, #t158) in #t158;
-    core::num* v9 = let final core::String* #t160 = "x" in let final core::num* #t161 = this.{self::Test5::[]}(#t160).{core::num::+}(self::getDouble()) in let final void #t162 = this.{self::Test5::[]=}(#t160, #t161) in #t161;
-    core::num* v10 = let final core::String* #t163 = "x" in let final core::num* #t164 = this.{self::Test5::[]}(#t163).{core::num::+}(1) in let final void #t165 = this.{self::Test5::[]=}(#t163, #t164) in #t164;
-    core::num* v11 = let final core::String* #t166 = "x" in let final core::num* #t167 = this.{self::Test5::[]}(#t166) in let final void #t168 = this.{self::Test5::[]=}(#t166, #t167.{core::num::+}(1)) in #t167;
+    core::int* v1 = let final core::String* #t121 = "x" in let final core::int* #t122 = self::getInt() in let final void #t123 = this.{self::Test5::[]=}(#t121, #t122) in #t122;
+    core::num* v2 = let final core::String* #t124 = "x" in let final core::num* #t125 = self::getNum() in let final void #t126 = this.{self::Test5::[]=}(#t124, #t125) in #t125;
+    core::double* v3 = let final core::String* #t127 = "x" in let final core::double* #t128 = self::getDouble() in let final void #t129 = this.{self::Test5::[]=}(#t127, #t128) in #t128;
+    core::num* v4 = let final core::String* #t130 = "x" in let final core::num* #t131 = this.{self::Test5::[]}(#t130) in #t131.{core::num::==}(null) ?{core::num*} let final core::int* #t132 = self::getInt() in let final void #t133 = this.{self::Test5::[]=}(#t130, #t132) in #t132 : #t131;
+    core::num* v5 = let final core::String* #t134 = "x" in let final core::num* #t135 = this.{self::Test5::[]}(#t134) in #t135.{core::num::==}(null) ?{core::num*} let final core::num* #t136 = self::getNum() in let final void #t137 = this.{self::Test5::[]=}(#t134, #t136) in #t136 : #t135;
+    core::num* v6 = let final core::String* #t138 = "x" in let final core::num* #t139 = this.{self::Test5::[]}(#t138) in #t139.{core::num::==}(null) ?{core::num*} let final core::double* #t140 = self::getDouble() in let final void #t141 = this.{self::Test5::[]=}(#t138, #t140) in #t140 : #t139;
+    core::num* v7 = let final core::String* #t142 = "x" in let final core::num* #t143 = this.{self::Test5::[]}(#t142).{core::num::+}(self::getInt()) in let final void #t144 = this.{self::Test5::[]=}(#t142, #t143) in #t143;
+    core::num* v8 = let final core::String* #t145 = "x" in let final core::num* #t146 = this.{self::Test5::[]}(#t145).{core::num::+}(self::getNum()) in let final void #t147 = this.{self::Test5::[]=}(#t145, #t146) in #t146;
+    core::num* v9 = let final core::String* #t148 = "x" in let final core::num* #t149 = this.{self::Test5::[]}(#t148).{core::num::+}(self::getDouble()) in let final void #t150 = this.{self::Test5::[]=}(#t148, #t149) in #t149;
+    core::num* v10 = let final core::String* #t151 = "x" in let final core::num* #t152 = this.{self::Test5::[]}(#t151).{core::num::+}(1) in let final void #t153 = this.{self::Test5::[]=}(#t151, #t152) in #t152;
+    core::num* v11 = let final core::String* #t154 = "x" in let final core::num* #t155 = this.{self::Test5::[]}(#t154) in let final void #t156 = this.{self::Test5::[]=}(#t154, #t155.{core::num::+}(1)) in #t155;
   }
 }
 abstract class Test6 extends core::Object {
@@ -138,15 +138,15 @@
   abstract operator [](core::String* s) → core::num*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final self::Test6* #t169 = this in let final core::String* #t170 = "x" in let final core::num* #t171 = self::getNum() as{TypeError} core::double* in let final void #t172 = #t169.{self::Test6::[]=}(#t170, #t171) in #t171;
-    core::double* v3 = let final self::Test6* #t173 = this in let final core::String* #t174 = "x" in let final core::double* #t175 = self::getDouble() in let final void #t176 = #t173.{self::Test6::[]=}(#t174, #t175) in #t175;
-    core::num* v5 = let final core::String* #t177 = "x" in let final core::num* #t178 = this.{self::Test6::[]}(#t177) in #t178.{core::num::==}(null) ?{core::num*} let final core::num* #t179 = self::getNum() as{TypeError} core::double* in let final void #t180 = this.{self::Test6::[]=}(#t177, #t179) in #t179 : #t178;
-    core::num* v6 = let final core::String* #t181 = "x" in let final core::num* #t182 = this.{self::Test6::[]}(#t181) in #t182.{core::num::==}(null) ?{core::num*} let final core::double* #t183 = self::getDouble() in let final void #t184 = this.{self::Test6::[]=}(#t181, #t183) in #t183 : #t182;
-    core::num* v7 = let final core::String* #t185 = "x" in let final core::num* #t186 = this.{self::Test6::[]}(#t185).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t187 = this.{self::Test6::[]=}(#t185, #t186) in #t186;
-    core::num* v8 = let final core::String* #t188 = "x" in let final core::num* #t189 = this.{self::Test6::[]}(#t188).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t190 = this.{self::Test6::[]=}(#t188, #t189) in #t189;
-    core::num* v9 = let final core::String* #t191 = "x" in let final core::num* #t192 = this.{self::Test6::[]}(#t191).{core::num::+}(self::getDouble()) as{TypeError} core::double* in let final void #t193 = this.{self::Test6::[]=}(#t191, #t192) in #t192;
-    core::num* v10 = let final core::String* #t194 = "x" in let final core::num* #t195 = this.{self::Test6::[]}(#t194).{core::num::+}(1) as{TypeError} core::double* in let final void #t196 = this.{self::Test6::[]=}(#t194, #t195) in #t195;
-    core::num* v11 = let final core::String* #t197 = "x" in let final core::num* #t198 = this.{self::Test6::[]}(#t197) in let final void #t199 = this.{self::Test6::[]=}(#t197, #t198.{core::num::+}(1) as{TypeError} core::double*) in #t198;
+    core::num* v2 = let final core::String* #t157 = "x" in let final core::num* #t158 = self::getNum() as{TypeError} core::double* in let final void #t159 = this.{self::Test6::[]=}(#t157, #t158) in #t158;
+    core::double* v3 = let final core::String* #t160 = "x" in let final core::double* #t161 = self::getDouble() in let final void #t162 = this.{self::Test6::[]=}(#t160, #t161) in #t161;
+    core::num* v5 = let final core::String* #t163 = "x" in let final core::num* #t164 = this.{self::Test6::[]}(#t163) in #t164.{core::num::==}(null) ?{core::num*} let final core::num* #t165 = self::getNum() as{TypeError} core::double* in let final void #t166 = this.{self::Test6::[]=}(#t163, #t165) in #t165 : #t164;
+    core::num* v6 = let final core::String* #t167 = "x" in let final core::num* #t168 = this.{self::Test6::[]}(#t167) in #t168.{core::num::==}(null) ?{core::num*} let final core::double* #t169 = self::getDouble() in let final void #t170 = this.{self::Test6::[]=}(#t167, #t169) in #t169 : #t168;
+    core::num* v7 = let final core::String* #t171 = "x" in let final core::num* #t172 = this.{self::Test6::[]}(#t171).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t173 = this.{self::Test6::[]=}(#t171, #t172) in #t172;
+    core::num* v8 = let final core::String* #t174 = "x" in let final core::num* #t175 = this.{self::Test6::[]}(#t174).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t176 = this.{self::Test6::[]=}(#t174, #t175) in #t175;
+    core::num* v9 = let final core::String* #t177 = "x" in let final core::num* #t178 = this.{self::Test6::[]}(#t177).{core::num::+}(self::getDouble()) as{TypeError} core::double* in let final void #t179 = this.{self::Test6::[]=}(#t177, #t178) in #t178;
+    core::num* v10 = let final core::String* #t180 = "x" in let final core::num* #t181 = this.{self::Test6::[]}(#t180).{core::num::+}(1) as{TypeError} core::double* in let final void #t182 = this.{self::Test6::[]=}(#t180, #t181) in #t181;
+    core::num* v11 = let final core::String* #t183 = "x" in let final core::num* #t184 = this.{self::Test6::[]}(#t183) in let final void #t185 = this.{self::Test6::[]=}(#t183, #t184.{core::num::+}(1) as{TypeError} core::double*) in #t184;
   }
 }
 abstract class Test7 extends core::Object {
@@ -156,22 +156,22 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::int* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test7* #t200 = this in let final core::String* #t201 = "x" in let final core::int* #t202 = self::getInt() in let final void #t203 = #t200.{self::Test7::[]=}(#t201, #t202) in #t202;
-    core::num* v2 = let final self::Test7* #t204 = this in let final core::String* #t205 = "x" in let final core::num* #t206 = self::getNum() as{TypeError} core::int* in let final void #t207 = #t204.{self::Test7::[]=}(#t205, #t206) in #t206;
-    core::num* v4 = let final core::String* #t208 = "x" in let final core::double* #t209 = this.{self::Test7::[]}(#t208) in #t209.{core::num::==}(null) ?{core::num*} let final core::int* #t210 = self::getInt() in let final void #t211 = this.{self::Test7::[]=}(#t208, #t210) in #t210 : #t209;
-    core::num* v5 = let final core::String* #t212 = "x" in let final core::double* #t213 = this.{self::Test7::[]}(#t212) in #t213.{core::num::==}(null) ?{core::num*} let final core::num* #t214 = self::getNum() as{TypeError} core::int* in let final void #t215 = this.{self::Test7::[]=}(#t212, #t214) in #t214 : #t213;
-    core::double* v7 = let final core::String* #t216 = "x" in let final core::double* #t217 = let final<BottomType> #t218 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:268:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+    core::int* v1 = let final core::String* #t186 = "x" in let final core::int* #t187 = self::getInt() in let final void #t188 = this.{self::Test7::[]=}(#t186, #t187) in #t187;
+    core::num* v2 = let final core::String* #t189 = "x" in let final core::num* #t190 = self::getNum() as{TypeError} core::int* in let final void #t191 = this.{self::Test7::[]=}(#t189, #t190) in #t190;
+    core::num* v4 = let final core::String* #t192 = "x" in let final core::double* #t193 = this.{self::Test7::[]}(#t192) in #t193.{core::num::==}(null) ?{core::num*} let final core::int* #t194 = self::getInt() in let final void #t195 = this.{self::Test7::[]=}(#t192, #t194) in #t194 : #t193;
+    core::num* v5 = let final core::String* #t196 = "x" in let final core::double* #t197 = this.{self::Test7::[]}(#t196) in #t197.{core::num::==}(null) ?{core::num*} let final core::num* #t198 = self::getNum() as{TypeError} core::int* in let final void #t199 = this.{self::Test7::[]=}(#t196, #t198) in #t198 : #t197;
+    core::double* v7 = let final core::String* #t200 = "x" in let final core::double* #t201 = let final<BottomType> #t202 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:268:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
         /*@target=double::+*/ += getInt();
-                              ^" in this.{self::Test7::[]}(#t216).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t219 = this.{self::Test7::[]=}(#t216, #t217) in #t217;
-    core::double* v8 = let final core::String* #t220 = "x" in let final core::double* #t221 = let final<BottomType> #t222 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:272:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+                              ^" in this.{self::Test7::[]}(#t200).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t203 = this.{self::Test7::[]=}(#t200, #t201) in #t201;
+    core::double* v8 = let final core::String* #t204 = "x" in let final core::double* #t205 = let final<BottomType> #t206 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:272:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
         /*@target=double::+*/ += getNum();
-                              ^" in this.{self::Test7::[]}(#t220).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t223 = this.{self::Test7::[]=}(#t220, #t221) in #t221;
-    core::double* v10 = let final core::String* #t224 = "x" in let final core::double* #t225 = let final<BottomType> #t226 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:274:57: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+                              ^" in this.{self::Test7::[]}(#t204).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t207 = this.{self::Test7::[]=}(#t204, #t205) in #t205;
+    core::double* v10 = let final core::String* #t208 = "x" in let final core::double* #t209 = let final<BottomType> #t210 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:274:57: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
     var /*@ type=double* */ v10 = /*@target=double::+*/ ++this
-                                                        ^" in this.{self::Test7::[]}(#t224).{core::double::+}(1) as{TypeError} core::int* in let final void #t227 = this.{self::Test7::[]=}(#t224, #t225) in #t225;
-    core::double* v11 = let final core::String* #t228 = "x" in let final core::double* #t229 = this.{self::Test7::[]}(#t228) in let final void #t230 = this.{self::Test7::[]=}(#t228, let final<BottomType> #t231 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:279:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+                                                        ^" in this.{self::Test7::[]}(#t208).{core::double::+}(1) as{TypeError} core::int* in let final void #t211 = this.{self::Test7::[]=}(#t208, #t209) in #t209;
+    core::double* v11 = let final core::String* #t212 = "x" in let final core::double* #t213 = this.{self::Test7::[]}(#t212) in let final void #t214 = this.{self::Test7::[]=}(#t212, let final<BottomType> #t215 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart:279:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
         /*@target=double::+*/ ++;
-                              ^" in #t229.{core::double::+}(1) as{TypeError} core::int*) in #t229;
+                              ^" in #t213.{core::double::+}(1) as{TypeError} core::int*) in #t213;
   }
 }
 abstract class Test8 extends core::Object {
@@ -181,17 +181,17 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::num* v) → void;
   method test() → void {
-    core::int* v1 = let final self::Test8* #t232 = this in let final core::String* #t233 = "x" in let final core::int* #t234 = self::getInt() in let final void #t235 = #t232.{self::Test8::[]=}(#t233, #t234) in #t234;
-    core::num* v2 = let final self::Test8* #t236 = this in let final core::String* #t237 = "x" in let final core::num* #t238 = self::getNum() in let final void #t239 = #t236.{self::Test8::[]=}(#t237, #t238) in #t238;
-    core::double* v3 = let final self::Test8* #t240 = this in let final core::String* #t241 = "x" in let final core::double* #t242 = self::getDouble() in let final void #t243 = #t240.{self::Test8::[]=}(#t241, #t242) in #t242;
-    core::num* v4 = let final core::String* #t244 = "x" in let final core::double* #t245 = this.{self::Test8::[]}(#t244) in #t245.{core::num::==}(null) ?{core::num*} let final core::int* #t246 = self::getInt() in let final void #t247 = this.{self::Test8::[]=}(#t244, #t246) in #t246 : #t245;
-    core::num* v5 = let final core::String* #t248 = "x" in let final core::double* #t249 = this.{self::Test8::[]}(#t248) in #t249.{core::num::==}(null) ?{core::num*} let final core::num* #t250 = self::getNum() in let final void #t251 = this.{self::Test8::[]=}(#t248, #t250) in #t250 : #t249;
-    core::double* v6 = let final core::String* #t252 = "x" in let final core::double* #t253 = this.{self::Test8::[]}(#t252) in #t253.{core::num::==}(null) ?{core::double*} let final core::double* #t254 = self::getDouble() in let final void #t255 = this.{self::Test8::[]=}(#t252, #t254) in #t254 : #t253;
-    core::double* v7 = let final core::String* #t256 = "x" in let final core::double* #t257 = this.{self::Test8::[]}(#t256).{core::double::+}(self::getInt()) in let final void #t258 = this.{self::Test8::[]=}(#t256, #t257) in #t257;
-    core::double* v8 = let final core::String* #t259 = "x" in let final core::double* #t260 = this.{self::Test8::[]}(#t259).{core::double::+}(self::getNum()) in let final void #t261 = this.{self::Test8::[]=}(#t259, #t260) in #t260;
-    core::double* v9 = let final core::String* #t262 = "x" in let final core::double* #t263 = this.{self::Test8::[]}(#t262).{core::double::+}(self::getDouble()) in let final void #t264 = this.{self::Test8::[]=}(#t262, #t263) in #t263;
-    core::double* v10 = let final core::String* #t265 = "x" in let final core::double* #t266 = this.{self::Test8::[]}(#t265).{core::double::+}(1) in let final void #t267 = this.{self::Test8::[]=}(#t265, #t266) in #t266;
-    core::double* v11 = let final core::String* #t268 = "x" in let final core::double* #t269 = this.{self::Test8::[]}(#t268) in let final void #t270 = this.{self::Test8::[]=}(#t268, #t269.{core::double::+}(1)) in #t269;
+    core::int* v1 = let final core::String* #t216 = "x" in let final core::int* #t217 = self::getInt() in let final void #t218 = this.{self::Test8::[]=}(#t216, #t217) in #t217;
+    core::num* v2 = let final core::String* #t219 = "x" in let final core::num* #t220 = self::getNum() in let final void #t221 = this.{self::Test8::[]=}(#t219, #t220) in #t220;
+    core::double* v3 = let final core::String* #t222 = "x" in let final core::double* #t223 = self::getDouble() in let final void #t224 = this.{self::Test8::[]=}(#t222, #t223) in #t223;
+    core::num* v4 = let final core::String* #t225 = "x" in let final core::double* #t226 = this.{self::Test8::[]}(#t225) in #t226.{core::num::==}(null) ?{core::num*} let final core::int* #t227 = self::getInt() in let final void #t228 = this.{self::Test8::[]=}(#t225, #t227) in #t227 : #t226;
+    core::num* v5 = let final core::String* #t229 = "x" in let final core::double* #t230 = this.{self::Test8::[]}(#t229) in #t230.{core::num::==}(null) ?{core::num*} let final core::num* #t231 = self::getNum() in let final void #t232 = this.{self::Test8::[]=}(#t229, #t231) in #t231 : #t230;
+    core::double* v6 = let final core::String* #t233 = "x" in let final core::double* #t234 = this.{self::Test8::[]}(#t233) in #t234.{core::num::==}(null) ?{core::double*} let final core::double* #t235 = self::getDouble() in let final void #t236 = this.{self::Test8::[]=}(#t233, #t235) in #t235 : #t234;
+    core::double* v7 = let final core::String* #t237 = "x" in let final core::double* #t238 = this.{self::Test8::[]}(#t237).{core::double::+}(self::getInt()) in let final void #t239 = this.{self::Test8::[]=}(#t237, #t238) in #t238;
+    core::double* v8 = let final core::String* #t240 = "x" in let final core::double* #t241 = this.{self::Test8::[]}(#t240).{core::double::+}(self::getNum()) in let final void #t242 = this.{self::Test8::[]=}(#t240, #t241) in #t241;
+    core::double* v9 = let final core::String* #t243 = "x" in let final core::double* #t244 = this.{self::Test8::[]}(#t243).{core::double::+}(self::getDouble()) in let final void #t245 = this.{self::Test8::[]=}(#t243, #t244) in #t244;
+    core::double* v10 = let final core::String* #t246 = "x" in let final core::double* #t247 = this.{self::Test8::[]}(#t246).{core::double::+}(1) in let final void #t248 = this.{self::Test8::[]=}(#t246, #t247) in #t247;
+    core::double* v11 = let final core::String* #t249 = "x" in let final core::double* #t250 = this.{self::Test8::[]}(#t249) in let final void #t251 = this.{self::Test8::[]=}(#t249, #t250.{core::double::+}(1)) in #t250;
   }
 }
 abstract class Test9 extends core::Object {
@@ -201,15 +201,15 @@
   abstract operator [](core::String* s) → core::double*;
   abstract operator []=(core::String* s, core::double* v) → void;
   method test() → void {
-    core::num* v2 = let final self::Test9* #t271 = this in let final core::String* #t272 = "x" in let final core::num* #t273 = self::getNum() as{TypeError} core::double* in let final void #t274 = #t271.{self::Test9::[]=}(#t272, #t273) in #t273;
-    core::double* v3 = let final self::Test9* #t275 = this in let final core::String* #t276 = "x" in let final core::double* #t277 = self::getDouble() in let final void #t278 = #t275.{self::Test9::[]=}(#t276, #t277) in #t277;
-    core::num* v5 = let final core::String* #t279 = "x" in let final core::double* #t280 = this.{self::Test9::[]}(#t279) in #t280.{core::num::==}(null) ?{core::num*} let final core::num* #t281 = self::getNum() as{TypeError} core::double* in let final void #t282 = this.{self::Test9::[]=}(#t279, #t281) in #t281 : #t280;
-    core::double* v6 = let final core::String* #t283 = "x" in let final core::double* #t284 = this.{self::Test9::[]}(#t283) in #t284.{core::num::==}(null) ?{core::double*} let final core::double* #t285 = self::getDouble() in let final void #t286 = this.{self::Test9::[]=}(#t283, #t285) in #t285 : #t284;
-    core::double* v7 = let final core::String* #t287 = "x" in let final core::double* #t288 = this.{self::Test9::[]}(#t287).{core::double::+}(self::getInt()) in let final void #t289 = this.{self::Test9::[]=}(#t287, #t288) in #t288;
-    core::double* v8 = let final core::String* #t290 = "x" in let final core::double* #t291 = this.{self::Test9::[]}(#t290).{core::double::+}(self::getNum()) in let final void #t292 = this.{self::Test9::[]=}(#t290, #t291) in #t291;
-    core::double* v9 = let final core::String* #t293 = "x" in let final core::double* #t294 = this.{self::Test9::[]}(#t293).{core::double::+}(self::getDouble()) in let final void #t295 = this.{self::Test9::[]=}(#t293, #t294) in #t294;
-    core::double* v10 = let final core::String* #t296 = "x" in let final core::double* #t297 = this.{self::Test9::[]}(#t296).{core::double::+}(1) in let final void #t298 = this.{self::Test9::[]=}(#t296, #t297) in #t297;
-    core::double* v11 = let final core::String* #t299 = "x" in let final core::double* #t300 = this.{self::Test9::[]}(#t299) in let final void #t301 = this.{self::Test9::[]=}(#t299, #t300.{core::double::+}(1)) in #t300;
+    core::num* v2 = let final core::String* #t252 = "x" in let final core::num* #t253 = self::getNum() as{TypeError} core::double* in let final void #t254 = this.{self::Test9::[]=}(#t252, #t253) in #t253;
+    core::double* v3 = let final core::String* #t255 = "x" in let final core::double* #t256 = self::getDouble() in let final void #t257 = this.{self::Test9::[]=}(#t255, #t256) in #t256;
+    core::num* v5 = let final core::String* #t258 = "x" in let final core::double* #t259 = this.{self::Test9::[]}(#t258) in #t259.{core::num::==}(null) ?{core::num*} let final core::num* #t260 = self::getNum() as{TypeError} core::double* in let final void #t261 = this.{self::Test9::[]=}(#t258, #t260) in #t260 : #t259;
+    core::double* v6 = let final core::String* #t262 = "x" in let final core::double* #t263 = this.{self::Test9::[]}(#t262) in #t263.{core::num::==}(null) ?{core::double*} let final core::double* #t264 = self::getDouble() in let final void #t265 = this.{self::Test9::[]=}(#t262, #t264) in #t264 : #t263;
+    core::double* v7 = let final core::String* #t266 = "x" in let final core::double* #t267 = this.{self::Test9::[]}(#t266).{core::double::+}(self::getInt()) in let final void #t268 = this.{self::Test9::[]=}(#t266, #t267) in #t267;
+    core::double* v8 = let final core::String* #t269 = "x" in let final core::double* #t270 = this.{self::Test9::[]}(#t269).{core::double::+}(self::getNum()) in let final void #t271 = this.{self::Test9::[]=}(#t269, #t270) in #t270;
+    core::double* v9 = let final core::String* #t272 = "x" in let final core::double* #t273 = this.{self::Test9::[]}(#t272).{core::double::+}(self::getDouble()) in let final void #t274 = this.{self::Test9::[]=}(#t272, #t273) in #t273;
+    core::double* v10 = let final core::String* #t275 = "x" in let final core::double* #t276 = this.{self::Test9::[]}(#t275).{core::double::+}(1) in let final void #t277 = this.{self::Test9::[]=}(#t275, #t276) in #t276;
+    core::double* v11 = let final core::String* #t278 = "x" in let final core::double* #t279 = this.{self::Test9::[]}(#t278) in let final void #t280 = this.{self::Test9::[]=}(#t278, #t279.{core::double::+}(1)) in #t279;
   }
 }
 static method getInt() → core::int*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
deleted file mode 100644
index 64f43c5..0000000
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
+++ /dev/null
@@ -1,42 +0,0 @@
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:23:9: Context: Write to local@474
-  local = /*@ typeArgs=B* */ f();
-        ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:25:34: Context: Write to local@474
-  local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
-                                 ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:27:28: Context: Write to local@474
-  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
-                           ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:29:28: Context: Write to local@474
-  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
-                           ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:31:28: Context: Write to local@474
-  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
-                           ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:33:22: Context: Write to local@474
-  /*@ target=B::- */ --local;
-                     ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:35:28: Context: Write to local@474
-  local /*@ target=B::- */ --;
-                           ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:37:33: Context: Write to local@474
-  var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
-                                ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:40:38: Context: Write to local@474
-      local /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
-                                     ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:43:26: Context: Write to local@474
-      /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
-                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:46:26: Context: Write to local@474
-      /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
-                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:49:26: Context: Write to local@474
-      /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
-                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:51:46: Context: Write to local@474
-  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
-                                             ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:54:41: Context: Write to local@474
-      /*@ type=B* */ /*@ target=B::- */ --;
-                                        ^^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
deleted file mode 100644
index db044b6..0000000
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
+++ /dev/null
@@ -1,84 +0,0 @@
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:13:31: Context: Write to t@343
-  var /*@ type=int* */ v1 = t = getInt();
-                              ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:15:31: Context: Write to t@343
-  var /*@ type=num* */ v2 = t = getNum();
-                              ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:17:53: Context: Write to t@343
-  var /*@ type=int* */ v4 = t /*@ target=num::== */ ??= getInt();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:19:53: Context: Write to t@343
-  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:21:52: Context: Write to t@343
-  var /*@ type=int* */ v7 = t /*@ target=num::+ */ += getInt();
-                                                   ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:23:52: Context: Write to t@343
-  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
-                                                   ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:25:51: Context: Write to t@343
-  var /*@ type=int* */ v10 = /*@ target=num::+ */ ++t;
-                                                  ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:28:64: Context: Write to t@343
-      /*@ type=int* */ t /*@ type=int* */ /*@ target=num::+ */ ++;
-                                                               ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:32:31: Context: Write to t@343
-  var /*@ type=int* */ v1 = t = getInt();
-                              ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:34:31: Context: Write to t@343
-  var /*@ type=num* */ v2 = t = getNum();
-                              ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:36:34: Context: Write to t@343
-  var /*@ type=double* */ v3 = t = getDouble();
-                                 ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:38:53: Context: Write to t@343
-  var /*@ type=num* */ v4 = t /*@ target=num::== */ ??= getInt();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:40:53: Context: Write to t@343
-  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:42:53: Context: Write to t@343
-  var /*@ type=num* */ v6 = t /*@ target=num::== */ ??= getDouble();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:44:52: Context: Write to t@343
-  var /*@ type=num* */ v7 = t /*@ target=num::+ */ += getInt();
-                                                   ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:46:52: Context: Write to t@343
-  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
-                                                   ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:48:52: Context: Write to t@343
-  var /*@ type=num* */ v9 = t /*@ target=num::+ */ += getDouble();
-                                                   ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:50:51: Context: Write to t@343
-  var /*@ type=num* */ v10 = /*@ target=num::+ */ ++t;
-                                                  ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:53:64: Context: Write to t@343
-      /*@ type=num* */ t /*@ type=num* */ /*@ target=num::+ */ ++;
-                                                               ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:57:31: Context: Write to t@343
-  var /*@ type=num* */ v2 = t = getNum();
-                              ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:59:34: Context: Write to t@343
-  var /*@ type=double* */ v3 = t = getDouble();
-                                 ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:61:53: Context: Write to t@343
-  var /*@ type=num* */ v5 = t /*@ target=num::== */ ??= getNum();
-                                                    ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:63:56: Context: Write to t@343
-  var /*@ type=double* */ v6 = t /*@ target=num::== */ ??= getDouble();
-                                                       ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:65:58: Context: Write to t@343
-  var /*@ type=double* */ v7 = t /*@ target=double::+ */ += getInt();
-                                                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:67:58: Context: Write to t@343
-  var /*@ type=double* */ v8 = t /*@ target=double::+ */ += getNum();
-                                                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:69:58: Context: Write to t@343
-  var /*@ type=double* */ v9 = t /*@ target=double::+ */ += getDouble();
-                                                         ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:71:57: Context: Write to t@343
-  var /*@ type=double* */ v10 = /*@ target=double::+ */ ++t;
-                                                        ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:74:73: Context: Write to t@343
-      /*@ type=double* */ t /*@ type=double* */ /*@ target=double::+ */ ++;
-                                                                        ^^
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart
new file mode 100644
index 0000000..8a69a3c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'inheritance_from_opt_out_lib.dart';
+
+class Class1 extends LegacyClass1 {}
+
+class Class2<T> extends LegacyClass2<T> {}
+
+class Class3a<T> extends LegacyClass3<T> {}
+
+class Class3b<T> extends LegacyClass3<T> implements GenericInterface<T> {}
+
+class Class4a extends LegacyClass4 {}
+
+class Class4b implements GenericInterface<num> {}
+
+class Class4c implements GenericInterface<num?> {}
+
+class Class4d extends LegacyClass4 implements GenericInterface<num> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..b279e44
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
@@ -0,0 +1,79 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart:13:7: Error: 'Class3b' can't implement both 'GenericInterface<T>' and 'GenericInterface<T>'
+//  - 'GenericInterface' is from 'pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart'.
+// class Class3b<T> extends LegacyClass3<T> implements GenericInterface<T> {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart:21:7: Error: 'Class4d' can't implement both 'GenericInterface<num>' and 'GenericInterface<num>'
+//  - 'GenericInterface' is from 'pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart'.
+// class Class4d extends LegacyClass4 implements GenericInterface<num> {}
+//       ^
+//
+library;
+import self as self;
+import "inheritance_from_opt_out_lib.dart" as inh;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///inheritance_from_opt_out_lib.dart";
+
+class Class1 extends inh::LegacyClass1 {
+  synthetic constructor •() → self::Class1*
+    ;
+}
+class Class2<T extends core::Object? = dynamic> extends inh::LegacyClass2<self::Class2::T%> {
+  synthetic constructor •() → self::Class2<self::Class2::T*>*
+    ;
+}
+class Class3a<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3a::T%> {
+  synthetic constructor •() → self::Class3a<self::Class3a::T*>*
+    ;
+}
+class Class3b<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3b::T%> implements inh::GenericInterface<self::Class3b::T%> {
+  synthetic constructor •() → self::Class3b<self::Class3b::T*>*
+    ;
+}
+class Class4a extends inh::LegacyClass4 {
+  synthetic constructor •() → self::Class4a*
+    ;
+}
+class Class4b extends core::Object implements inh::GenericInterface<core::num> {
+  synthetic constructor •() → self::Class4b*
+    ;
+}
+class Class4c extends core::Object implements inh::GenericInterface<core::num?> {
+  synthetic constructor •() → self::Class4c*
+    ;
+}
+class Class4d extends inh::LegacyClass4 implements inh::GenericInterface<core::num> {
+  synthetic constructor •() → self::Class4d*
+    ;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as inh;
+import "dart:core" as core;
+
+abstract class GenericInterface<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → inh::GenericInterface<inh::GenericInterface::T*>*
+    ;
+}
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → inh::LegacyClass1*
+    ;
+}
+class LegacyClass2<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → inh::LegacyClass2<inh::LegacyClass2::T*>*
+    ;
+}
+class LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::GenericInterface<inh::LegacyClass3::T*> {
+  synthetic constructor •() → inh::LegacyClass3<inh::LegacyClass3::T*>*
+    ;
+}
+class LegacyClass4 extends core::Object implements inh::GenericInterface<core::num*> {
+  synthetic constructor •() → inh::LegacyClass4*
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..c729feb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
@@ -0,0 +1,91 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart:13:7: Error: 'Class3b' can't implement both 'GenericInterface<T>' and 'GenericInterface<T>'
+//  - 'GenericInterface' is from 'pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart'.
+// class Class3b<T> extends LegacyClass3<T> implements GenericInterface<T> {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart:21:7: Error: 'Class4d' can't implement both 'GenericInterface<num>' and 'GenericInterface<num>'
+//  - 'GenericInterface' is from 'pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart'.
+// class Class4d extends LegacyClass4 implements GenericInterface<num> {}
+//       ^
+//
+library;
+import self as self;
+import "inheritance_from_opt_out_lib.dart" as inh;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///inheritance_from_opt_out_lib.dart";
+
+class Class1 extends inh::LegacyClass1 {
+  synthetic constructor •() → self::Class1*
+    : super inh::LegacyClass1::•()
+    ;
+}
+class Class2<T extends core::Object? = dynamic> extends inh::LegacyClass2<self::Class2::T%> {
+  synthetic constructor •() → self::Class2<self::Class2::T*>*
+    : super inh::LegacyClass2::•()
+    ;
+}
+class Class3a<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3a::T%> {
+  synthetic constructor •() → self::Class3a<self::Class3a::T*>*
+    : super inh::LegacyClass3::•()
+    ;
+}
+class Class3b<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3b::T%> implements inh::GenericInterface<self::Class3b::T%> {
+  synthetic constructor •() → self::Class3b<self::Class3b::T*>*
+    : super inh::LegacyClass3::•()
+    ;
+}
+class Class4a extends inh::LegacyClass4 {
+  synthetic constructor •() → self::Class4a*
+    : super inh::LegacyClass4::•()
+    ;
+}
+class Class4b extends core::Object implements inh::GenericInterface<core::num> {
+  synthetic constructor •() → self::Class4b*
+    : super core::Object::•()
+    ;
+}
+class Class4c extends core::Object implements inh::GenericInterface<core::num?> {
+  synthetic constructor •() → self::Class4c*
+    : super core::Object::•()
+    ;
+}
+class Class4d extends inh::LegacyClass4 implements inh::GenericInterface<core::num> {
+  synthetic constructor •() → self::Class4d*
+    : super inh::LegacyClass4::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as inh;
+import "dart:core" as core;
+
+abstract class GenericInterface<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → inh::GenericInterface<inh::GenericInterface::T*>*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → inh::LegacyClass1*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass2<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → inh::LegacyClass2<inh::LegacyClass2::T*>*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::GenericInterface<inh::LegacyClass3::T*> {
+  synthetic constructor •() → inh::LegacyClass3<inh::LegacyClass3::T*>*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass4 extends core::Object implements inh::GenericInterface<core::num*> {
+  synthetic constructor •() → inh::LegacyClass4*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart
new file mode 100644
index 0000000..6324c15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out_lib.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+abstract class GenericInterface<T> {}
+
+class LegacyClass1 {}
+
+class LegacyClass2<T> {}
+
+class LegacyClass3<T> implements GenericInterface<T> {}
+
+class LegacyClass4 implements GenericInterface<num> {}
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.type_promotion.expect
deleted file mode 100644
index ffa128e..0000000
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/nnbd/intersection_types.dart:13:11: Context: Possible promotion of t@403
-    if (t is B?) {
-          ^^
-pkg/front_end/testcases/nnbd/intersection_types.dart:15:13: Context: Possible promotion of t@403
-      if (t is C?) {
-            ^^
-pkg/front_end/testcases/nnbd/intersection_types.dart:22:11: Context: Possible promotion of t@403
-    if (t is B) {
-          ^^
-pkg/front_end/testcases/nnbd/intersection_types.dart:24:13: Context: Possible promotion of t@403
-      if (t is C) {
-            ^^
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart b/pkg/front_end/testcases/nnbd/issue_39286.dart
new file mode 100644
index 0000000..89da27c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  D? f() => new D();
+  void h() {}
+}
+
+class D {
+  void g() {}
+}
+
+void test(C x) {
+  x..f()!.g()..h();
+}
+
+main() {
+  test(new C());
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect
new file mode 100644
index 0000000..acfeb30
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    ;
+  method f() → self::D?
+    ;
+  method h() → void
+    ;
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    ;
+  method g() → void
+    ;
+}
+static method test(self::C x) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect
new file mode 100644
index 0000000..108244e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  method f() → self::D?
+    return new self::D::•();
+  method h() → void {}
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+  method g() → void {}
+}
+static method test(self::C x) → void {
+  let final self::C #t1 = x in let final void #t2 = #t1.{self::C::f}()!.{self::D::g}() in let final void #t3 = #t1.{self::C::h}() in #t1;
+}
+static method main() → dynamic {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect
new file mode 100644
index 0000000..108244e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  method f() → self::D?
+    return new self::D::•();
+  method h() → void {}
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+  method g() → void {}
+}
+static method test(self::C x) → void {
+  let final self::C #t1 = x in let final void #t2 = #t1.{self::C::f}()!.{self::D::g}() in let final void #t3 = #t1.{self::C::h}() in #t1;
+}
+static method main() → dynamic {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart b/pkg/front_end/testcases/nnbd/issue_39286_2.dart
new file mode 100644
index 0000000..b241823
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  int y;
+  D? f() => new D();
+  C h() => this;
+}
+class D {
+  D g() => this;
+  String operator [](String s) { return "!$s!";}
+}
+void test(C x) {
+  x..f()!.g()['Hi!']!..h()!.y = 2;
+}
+main() {
+  test(new C());
+}
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect
new file mode 100644
index 0000000..f2c2b39
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int y;
+  synthetic constructor •() → self::C*
+    ;
+  method f() → self::D?
+    ;
+  method h() → self::C
+    ;
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    ;
+  method g() → self::D
+    ;
+  operator [](core::String s) → core::String
+    ;
+}
+static method test(self::C x) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect
new file mode 100644
index 0000000..37e9149
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int y = null;
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  method f() → self::D?
+    return new self::D::•();
+  method h() → self::C
+    return this;
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+  method g() → self::D
+    return this;
+  operator [](core::String s) → core::String {
+    return "!${s}!";
+  }
+}
+static method test(self::C x) → void {
+  let final self::C #t1 = x in let final void #t2 = #t1.{self::C::f}()!.{self::D::g}().{self::D::[]}("Hi!")! in let final void #t3 = #t1.{self::C::h}()!.{self::C::y} = 2 in #t1;
+}
+static method main() → dynamic {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..37e9149
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::int y = null;
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  method f() → self::D?
+    return new self::D::•();
+  method h() → self::C
+    return this;
+}
+class D extends core::Object {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+  method g() → self::D
+    return this;
+  operator [](core::String s) → core::String {
+    return "!${s}!";
+  }
+}
+static method test(self::C x) → void {
+  let final self::C #t1 = x in let final void #t2 = #t1.{self::C::f}()!.{self::D::g}().{self::D::[]}("Hi!")! in let final void #t3 = #t1.{self::C::h}()!.{self::C::y} = 2 in #t1;
+}
+static method main() → dynamic {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect
deleted file mode 100644
index d8c4180..0000000
--- a/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/nnbd/late.dart:29:23: Context: Write to lateFinalVariable@862
-    lateFinalVariable = 0;
-                      ^
-pkg/front_end/testcases/nnbd/late.dart:40:31: Context: Write to lateFinalVariableWithInit@1146
-    lateFinalVariableWithInit = 0;
-                              ^
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
index d9dcefa..8e7b90e 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -15,17 +15,17 @@
 static method main() → dynamic {
   self::Class? c = new self::Class::•();
   c!;
-  c!.{self::Class::field};
-  c!.{self::Class::field} = 42;
-  c!.{self::Class::method};
-  c!.{self::Class::method}();
-  c!.{self::Class::field}!.{core::int::toString}();
-  c!.{self::Class::method}()!.{core::int::toString}();
-  c!.{self::Class::+}(c);
-  c!.{self::Class::+}(c!);
-  c.{self::Class::+}(c!);
-  c.{self::Class::+}(c)!;
+  c{self::Class}!.{self::Class::field};
+  c{self::Class}!.{self::Class::field} = 42;
+  c{self::Class}!.{self::Class::method};
+  c{self::Class}!.{self::Class::method}();
+  c{self::Class}!.{self::Class::field}!.{core::int::toString}();
+  c{self::Class}!.{self::Class::method}()!.{core::int::toString}();
+  c{self::Class}!.{self::Class::+}(c{self::Class});
+  c{self::Class}!.{self::Class::+}(c{self::Class}!);
+  c{self::Class}.{self::Class::+}(c{self::Class}!);
+  c{self::Class}.{self::Class::+}(c{self::Class})!;
   core::bool? o = true;
-  !o! ?{core::bool} !o! : !!o!!;
-  !o! ?{core::bool} (!o)! : (!(!o)!)!;
+  !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
+  !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
index d9dcefa..8e7b90e 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
@@ -15,17 +15,17 @@
 static method main() → dynamic {
   self::Class? c = new self::Class::•();
   c!;
-  c!.{self::Class::field};
-  c!.{self::Class::field} = 42;
-  c!.{self::Class::method};
-  c!.{self::Class::method}();
-  c!.{self::Class::field}!.{core::int::toString}();
-  c!.{self::Class::method}()!.{core::int::toString}();
-  c!.{self::Class::+}(c);
-  c!.{self::Class::+}(c!);
-  c.{self::Class::+}(c!);
-  c.{self::Class::+}(c)!;
+  c{self::Class}!.{self::Class::field};
+  c{self::Class}!.{self::Class::field} = 42;
+  c{self::Class}!.{self::Class::method};
+  c{self::Class}!.{self::Class::method}();
+  c{self::Class}!.{self::Class::field}!.{core::int::toString}();
+  c{self::Class}!.{self::Class::method}()!.{core::int::toString}();
+  c{self::Class}!.{self::Class::+}(c{self::Class});
+  c{self::Class}!.{self::Class::+}(c{self::Class}!);
+  c{self::Class}.{self::Class::+}(c{self::Class}!);
+  c{self::Class}.{self::Class::+}(c{self::Class})!;
   core::bool? o = true;
-  !o! ?{core::bool} !o! : !!o!!;
-  !o! ?{core::bool} (!o)! : (!(!o)!)!;
+  !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
+  !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart b/pkg/front_end/testcases/nnbd/null_shorting.dart
index 3f9a93b..681c577 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart
@@ -12,6 +12,8 @@
   }
 
   Class? operator +(int value) => field;
+
+  Class? operator -() => field;
 }
 
 main() {
@@ -29,6 +31,9 @@
 
   c?.field.field;
   c?.field.field = new Class();
+  throws(() => (c?.field).field);
+  throws(() => (c?.field = new Class()).field);
+  throws(() => (c?.method()).field);
   c = c?.field.field = new Class();
   c?.field.method();
   c?.field = new Class().field;
@@ -109,8 +114,8 @@
 }
 
 void operatorAccess(Class? c) {
-  // TODO(johnniwinther): + should _not_ be null-shortened.
-  c?.field + 0;
+  throws(() => c?.field + 0);
+  throws(() => -c?.field);
   c?.field += 0;
   c = c?.field += 0;
   c?.field.field += 0;
@@ -128,3 +133,12 @@
   c = c?.field ??= c;
   c?.field[c] ??= c;
 }
+
+void throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Expected exception.';
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
index 707d670..4e95ca9d 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
@@ -14,6 +14,8 @@
     ;
   operator +(core::int value) → self::Class?
     ;
+  operator unary-() → self::Class?
+    ;
 }
 static method main() → dynamic
   ;
@@ -25,3 +27,5 @@
   ;
 static method ifNull(self::Class? c) → void
   ;
+static method throws(() → void f) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
index 45eb1bf..e1af1bb 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
@@ -16,6 +16,8 @@
   }
   operator +(core::int value) → self::Class?
     return this.{self::Class::field};
+  operator unary-() → self::Class?
+    return this.{self::Class::field};
 }
 static method main() → dynamic {
   self::propertyAccess(null);
@@ -30,87 +32,100 @@
   let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
   let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class*} null : #t7.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : #t8.{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class?} null : #t10.{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class*} null : #t11.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class*} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class?} null : #t15.{self::Class::method}().{self::Class::field};
-  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class*} null : #t16.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::field}.{self::Class::field}.{self::Class::field};
-  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : #t20.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class?} null : #t22.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
-  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class?} null : #t23.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
-  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class*} null : #t24.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
-  c = let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class?} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class?} null : #t28.{self::Class::method}().{self::Class::field}.{self::Class::field};
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class*} null : #t29.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::method}().{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : #t32.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : #t33.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : #t37.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : #t39.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class*} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : #t43.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : #t45.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class*} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class?} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class?} null : #t49.{self::Class::field}.{self::Class::method}().{self::Class::field};
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : #t50.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class*} null : #t51.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class?} null : #t53.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
-  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : #t54.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : #t55.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class*} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : #t59.{self::Class::method}().{self::Class::method}().{self::Class::field};
-  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : #t60.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::method}().{self::Class::method}().{self::Class::method}();
+  self::throws(() → self::Class? => (let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : #t7.{self::Class::field}).{self::Class::field});
+  self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
+  self::throws(() → self::Class? => (let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::method}()).{self::Class::field});
+  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class?} null : #t11.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class*} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class?} null : #t16.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class?} null : #t20.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class*} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class?} null : #t24.{self::Class::field}.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class*} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class*} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : #t29.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  c = let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::method}().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class*} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class?} null : #t33.{self::Class::method}().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class*} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class*} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : #t39.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class?} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class*} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class?} null : #t45.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class?} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class*} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class*} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : #t50.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : #t51.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class*} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class*} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : #t55.{self::Class::field}.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  c = let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class*} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class*} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class?} null : #t60.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  c = let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::method}().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class*} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class?} null : #t64.{self::Class::method}().{self::Class::method}().{self::Class::method}();
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::field}.{self::Class::[]}(c);
-  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{void} null : #t63.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t65 = #t64.{self::Class::field} in let final self::Class? #t66 = c in let final self::Class* #t67 = new self::Class::•() in let final void #t68 = #t65.{self::Class::[]=}(#t66, #t67) in #t67;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : #t69.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
-  let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in #t71.{self::Class::[]=}(#t72, #t71.{self::Class::[]}(#t72).{self::Class::+}(0));
-  c = let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in let final self::Class? #t76 = #t74.{self::Class::[]}(#t75).{self::Class::+}(0) in let final void #t77 = #t74.{self::Class::[]=}(#t75, #t76) in #t76;
-  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t79 = #t78.{self::Class::field} in let final self::Class? #t80 = c in #t79.{self::Class::[]=}(#t80, #t79.{self::Class::[]}(#t80).{self::Class::+}(1));
-  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in let final self::Class? #t84 = #t82.{self::Class::[]}(#t83) in let final void #t85 = #t82.{self::Class::[]=}(#t83, #t84.{self::Class::+}(1)) in #t84;
-  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t87 = #t86.{self::Class::field} in let final self::Class? #t88 = c in let final self::Class? #t89 = #t87.{self::Class::[]}(#t88).{self::Class::+}(1) in let final void #t90 = #t87.{self::Class::[]=}(#t88, #t89) in #t89;
-  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t92 = #t91.{self::Class::field} in let final self::Class? #t93 = c in let final self::Class? #t94 = #t92.{self::Class::[]}(#t93).{self::Class::+}(1) in let final void #t95 = #t92.{self::Class::[]=}(#t93, #t94) in #t94;
+  let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::field}.{self::Class::[]}(c);
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : #t66.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+  c = let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t68 = #t67.{self::Class::field} in let final self::Class? #t69 = c in let final self::Class* #t70 = new self::Class::•() in let final void #t71 = #t68.{self::Class::[]=}(#t69, #t70) in #t70;
+  let final self::Class? #t72 = c in #t72.{core::Object::==}(null) ?{self::Class?} null : #t72.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in #t74.{self::Class::[]=}(#t75, #t74.{self::Class::[]}(#t75).{self::Class::+}(0));
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in let final self::Class? #t79 = #t77.{self::Class::[]}(#t78).{self::Class::+}(0) in let final void #t80 = #t77.{self::Class::[]=}(#t78, #t79) in #t79;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in #t82.{self::Class::[]=}(#t83, #t82.{self::Class::[]}(#t83).{self::Class::+}(1));
+  c = let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in let final self::Class? #t87 = #t85.{self::Class::[]}(#t86) in let final void #t88 = #t85.{self::Class::[]=}(#t86, #t87.{self::Class::+}(1)) in #t87;
+  let final self::Class? #t89 = c in #t89.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t90 = #t89.{self::Class::field} in let final self::Class? #t91 = c in let final self::Class? #t92 = #t90.{self::Class::[]}(#t91).{self::Class::+}(1) in let final void #t93 = #t90.{self::Class::[]=}(#t91, #t92) in #t92;
+  c = let final self::Class? #t94 = c in #t94.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t95 = #t94.{self::Class::field} in let final self::Class? #t96 = c in let final self::Class? #t97 = #t95.{self::Class::[]}(#t96).{self::Class::+}(1) in let final void #t98 = #t95.{self::Class::[]=}(#t96, #t97) in #t97;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : #t96.{self::Class::field}.{self::Class::+}(0);
-  let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : #t97.{self::Class::field} = #t97.{self::Class::field}.{self::Class::+}(0);
-  c = let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t99 = #t98.{self::Class::field}.{self::Class::+}(0) in let final void #t100 = #t98.{self::Class::field} = #t99 in #t99;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = #t101.{self::Class::field} in #t102.{self::Class::field} = #t102.{self::Class::field}.{self::Class::+}(0);
-  c = let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t104 = #t103.{self::Class::field} in #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : #t105.{self::Class::field} = #t105.{self::Class::field}.{self::Class::+}(1);
-  c = let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t107 = #t106.{self::Class::field} in let final void #t108 = #t106.{self::Class::field} = #t107.{self::Class::+}(1) in #t107;
-  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t110 = #t109.{self::Class::field}.{self::Class::+}(1) in let final void #t111 = #t109.{self::Class::field} = #t110 in #t110;
-  c = let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t113 = #t112.{self::Class::field}.{self::Class::+}(1) in let final void #t114 = #t112.{self::Class::field} = #t113 in #t113;
+  self::throws(() → self::Class? => (let final self::Class? #t99 = c in #t99.{core::Object::==}(null) ?{self::Class?} null : #t99.{self::Class::field}).{self::Class::+}(0));
+  self::throws(() → self::Class? => (let final self::Class? #t100 = c in #t100.{core::Object::==}(null) ?{self::Class?} null : #t100.{self::Class::field}).{self::Class::unary-}());
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : #t101.{self::Class::field} = #t101.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = #t102.{self::Class::field}.{self::Class::+}(0) in let final void #t104 = #t102.{self::Class::field} = #t103 in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field} in #t106.{self::Class::field} = #t106.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = #t107.{self::Class::field} in #t108.{self::Class::field} = #t108.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(1);
+  c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in let final void #t112 = #t110.{self::Class::field} = #t111.{self::Class::+}(1) in #t111;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field}.{self::Class::+}(1) in let final void #t115 = #t113.{self::Class::field} = #t114 in #t114;
+  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t115 = c in #t115.{core::Object::==}(null) ?{self::Class?} null : #t115.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t115.{self::Class::field} = c : null;
-  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field} in #t117.{core::Object::==}(null) ?{self::Class?} #t116.{self::Class::field} = c : #t117;
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t119 = #t118.{self::Class::field} in let final self::Class? #t120 = c in #t119.{self::Class::[]}(#t120).{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::[]=}(#t120, c) : null;
+  let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : #t119.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::field} = c : null;
+  c = let final self::Class? #t120 = c in #t120.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t121 = #t120.{self::Class::field} in #t121.{core::Object::==}(null) ?{self::Class?} #t120.{self::Class::field} = c : #t121;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t123 = #t122.{self::Class::field} in let final self::Class? #t124 = c in #t123.{self::Class::[]}(#t124).{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::[]=}(#t124, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
index 45eb1bf..e1af1bb 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
@@ -16,6 +16,8 @@
   }
   operator +(core::int value) → self::Class?
     return this.{self::Class::field};
+  operator unary-() → self::Class?
+    return this.{self::Class::field};
 }
 static method main() → dynamic {
   self::propertyAccess(null);
@@ -30,87 +32,100 @@
   let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
   let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class*} null : #t7.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : #t8.{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class?} null : #t10.{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class*} null : #t11.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class*} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class?} null : #t15.{self::Class::method}().{self::Class::field};
-  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class*} null : #t16.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::field}.{self::Class::field}.{self::Class::field};
-  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : #t20.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class?} null : #t22.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
-  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class?} null : #t23.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
-  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class*} null : #t24.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
-  c = let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class?} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class?} null : #t28.{self::Class::method}().{self::Class::field}.{self::Class::field};
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class*} null : #t29.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::method}().{self::Class::field}.{self::Class::method}();
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : #t32.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : #t33.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : #t37.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : #t39.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class*} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : #t43.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
-  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
-  let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : #t45.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class*} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  c = let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class?} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
-  let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class?} null : #t49.{self::Class::field}.{self::Class::method}().{self::Class::field};
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : #t50.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class*} null : #t51.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class?} null : #t53.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
-  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : #t54.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : #t55.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class*} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
-  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : #t59.{self::Class::method}().{self::Class::method}().{self::Class::field};
-  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : #t60.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::method}().{self::Class::method}().{self::Class::method}();
+  self::throws(() → self::Class? => (let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : #t7.{self::Class::field}).{self::Class::field});
+  self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
+  self::throws(() → self::Class? => (let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::method}()).{self::Class::field});
+  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class?} null : #t11.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class*} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class?} null : #t16.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class?} null : #t20.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class*} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class?} null : #t24.{self::Class::field}.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class*} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class*} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : #t29.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  c = let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::method}().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class*} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class?} null : #t33.{self::Class::method}().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class*} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class*} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : #t39.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class?} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class*} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class?} null : #t45.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class?} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class*} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class*} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : #t50.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : #t51.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class*} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class*} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : #t55.{self::Class::field}.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  c = let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class*} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class*} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class?} null : #t60.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  c = let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::method}().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class*} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class?} null : #t64.{self::Class::method}().{self::Class::method}().{self::Class::method}();
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::field}.{self::Class::[]}(c);
-  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{void} null : #t63.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t65 = #t64.{self::Class::field} in let final self::Class? #t66 = c in let final self::Class* #t67 = new self::Class::•() in let final void #t68 = #t65.{self::Class::[]=}(#t66, #t67) in #t67;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : #t69.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
-  let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in #t71.{self::Class::[]=}(#t72, #t71.{self::Class::[]}(#t72).{self::Class::+}(0));
-  c = let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in let final self::Class? #t76 = #t74.{self::Class::[]}(#t75).{self::Class::+}(0) in let final void #t77 = #t74.{self::Class::[]=}(#t75, #t76) in #t76;
-  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t79 = #t78.{self::Class::field} in let final self::Class? #t80 = c in #t79.{self::Class::[]=}(#t80, #t79.{self::Class::[]}(#t80).{self::Class::+}(1));
-  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in let final self::Class? #t84 = #t82.{self::Class::[]}(#t83) in let final void #t85 = #t82.{self::Class::[]=}(#t83, #t84.{self::Class::+}(1)) in #t84;
-  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t87 = #t86.{self::Class::field} in let final self::Class? #t88 = c in let final self::Class? #t89 = #t87.{self::Class::[]}(#t88).{self::Class::+}(1) in let final void #t90 = #t87.{self::Class::[]=}(#t88, #t89) in #t89;
-  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t92 = #t91.{self::Class::field} in let final self::Class? #t93 = c in let final self::Class? #t94 = #t92.{self::Class::[]}(#t93).{self::Class::+}(1) in let final void #t95 = #t92.{self::Class::[]=}(#t93, #t94) in #t94;
+  let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::field}.{self::Class::[]}(c);
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : #t66.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+  c = let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t68 = #t67.{self::Class::field} in let final self::Class? #t69 = c in let final self::Class* #t70 = new self::Class::•() in let final void #t71 = #t68.{self::Class::[]=}(#t69, #t70) in #t70;
+  let final self::Class? #t72 = c in #t72.{core::Object::==}(null) ?{self::Class?} null : #t72.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in #t74.{self::Class::[]=}(#t75, #t74.{self::Class::[]}(#t75).{self::Class::+}(0));
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in let final self::Class? #t79 = #t77.{self::Class::[]}(#t78).{self::Class::+}(0) in let final void #t80 = #t77.{self::Class::[]=}(#t78, #t79) in #t79;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in #t82.{self::Class::[]=}(#t83, #t82.{self::Class::[]}(#t83).{self::Class::+}(1));
+  c = let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in let final self::Class? #t87 = #t85.{self::Class::[]}(#t86) in let final void #t88 = #t85.{self::Class::[]=}(#t86, #t87.{self::Class::+}(1)) in #t87;
+  let final self::Class? #t89 = c in #t89.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t90 = #t89.{self::Class::field} in let final self::Class? #t91 = c in let final self::Class? #t92 = #t90.{self::Class::[]}(#t91).{self::Class::+}(1) in let final void #t93 = #t90.{self::Class::[]=}(#t91, #t92) in #t92;
+  c = let final self::Class? #t94 = c in #t94.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t95 = #t94.{self::Class::field} in let final self::Class? #t96 = c in let final self::Class? #t97 = #t95.{self::Class::[]}(#t96).{self::Class::+}(1) in let final void #t98 = #t95.{self::Class::[]=}(#t96, #t97) in #t97;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : #t96.{self::Class::field}.{self::Class::+}(0);
-  let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : #t97.{self::Class::field} = #t97.{self::Class::field}.{self::Class::+}(0);
-  c = let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t99 = #t98.{self::Class::field}.{self::Class::+}(0) in let final void #t100 = #t98.{self::Class::field} = #t99 in #t99;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = #t101.{self::Class::field} in #t102.{self::Class::field} = #t102.{self::Class::field}.{self::Class::+}(0);
-  c = let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t104 = #t103.{self::Class::field} in #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : #t105.{self::Class::field} = #t105.{self::Class::field}.{self::Class::+}(1);
-  c = let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t107 = #t106.{self::Class::field} in let final void #t108 = #t106.{self::Class::field} = #t107.{self::Class::+}(1) in #t107;
-  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t110 = #t109.{self::Class::field}.{self::Class::+}(1) in let final void #t111 = #t109.{self::Class::field} = #t110 in #t110;
-  c = let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t113 = #t112.{self::Class::field}.{self::Class::+}(1) in let final void #t114 = #t112.{self::Class::field} = #t113 in #t113;
+  self::throws(() → self::Class? => (let final self::Class? #t99 = c in #t99.{core::Object::==}(null) ?{self::Class?} null : #t99.{self::Class::field}).{self::Class::+}(0));
+  self::throws(() → self::Class? => (let final self::Class? #t100 = c in #t100.{core::Object::==}(null) ?{self::Class?} null : #t100.{self::Class::field}).{self::Class::unary-}());
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : #t101.{self::Class::field} = #t101.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = #t102.{self::Class::field}.{self::Class::+}(0) in let final void #t104 = #t102.{self::Class::field} = #t103 in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field} in #t106.{self::Class::field} = #t106.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = #t107.{self::Class::field} in #t108.{self::Class::field} = #t108.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(1);
+  c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in let final void #t112 = #t110.{self::Class::field} = #t111.{self::Class::+}(1) in #t111;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field}.{self::Class::+}(1) in let final void #t115 = #t113.{self::Class::field} = #t114 in #t114;
+  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t115 = c in #t115.{core::Object::==}(null) ?{self::Class?} null : #t115.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t115.{self::Class::field} = c : null;
-  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field} in #t117.{core::Object::==}(null) ?{self::Class?} #t116.{self::Class::field} = c : #t117;
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t119 = #t118.{self::Class::field} in let final self::Class? #t120 = c in #t119.{self::Class::[]}(#t120).{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::[]=}(#t120, c) : null;
+  let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : #t119.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::field} = c : null;
+  c = let final self::Class? #t120 = c in #t120.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t121 = #t120.{self::Class::field} in #t121.{core::Object::==}(null) ?{self::Class?} #t120.{self::Class::field} = c : #t121;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t123 = #t122.{self::Class::field} in let final self::Class? #t124 = c in #t123.{self::Class::[]}(#t124).{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::[]=}(#t124, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect
deleted file mode 100644
index 20c93f0..0000000
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect
+++ /dev/null
@@ -1,93 +0,0 @@
-pkg/front_end/testcases/nnbd/null_shorting.dart:27:5: Context: Write to c@558
-  c = c?.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:32:5: Context: Write to c@558
-  c = c?.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:35:5: Context: Write to c@558
-  c = c?.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:37:5: Context: Write to c@558
-  c = c?.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:39:5: Context: Write to c@558
-  c = c?.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:46:5: Context: Write to c@558
-  c = c?.field.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:49:5: Context: Write to c@558
-  c = c?.field = new Class().field.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:51:5: Context: Write to c@558
-  c = c?.field = new Class().field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:53:5: Context: Write to c@558
-  c = c?.field = new Class().field.method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:59:5: Context: Write to c@558
-  c = c?.field.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:61:5: Context: Write to c@558
-  c = c?.field.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:63:5: Context: Write to c@558
-  c = c?.field.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:65:5: Context: Write to c@558
-  c = c?.field = new Class().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:67:5: Context: Write to c@558
-  c = c?.field = new Class().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:69:5: Context: Write to c@558
-  c = c?.field = new Class().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:71:5: Context: Write to c@558
-  c = c?.method().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:73:5: Context: Write to c@558
-  c = c?.method().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:75:5: Context: Write to c@558
-  c = c?.method().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:79:5: Context: Write to c@558
-  c = c?.field.method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:82:5: Context: Write to c@558
-  c = c?.field = new Class().method().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:84:5: Context: Write to c@558
-  c = c?.field = new Class().method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:86:5: Context: Write to c@558
-  c = c?.field = new Class().method().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:99:5: Context: Write to c@558
-  c = c?.field[c] = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:102:5: Context: Write to c@558
-  c = c?.field[c] += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:106:5: Context: Write to c@558
-  c = c?.field[c]++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:108:5: Context: Write to c@558
-  c = ++c?.field[c];
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:115:5: Context: Write to c@558
-  c = c?.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:117:5: Context: Write to c@558
-  c = c?.field.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:121:5: Context: Write to c@558
-  c = c?.field++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:123:5: Context: Write to c@558
-  c = ++c?.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting.dart:128:5: Context: Write to c@558
-  c = c?.field ??= c;
-    ^
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
index 78ec83e..68821f8 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
@@ -20,6 +20,8 @@
   }
 
   Class? operator +(int value) => field;
+
+  Class? operator -() => field;
 }
 
 main() {
@@ -37,6 +39,9 @@
 
   Extension(c)?.field.field;
   Extension(c)?.field.field = new Class();
+  throws(() => (Extension(c)?.field).field);
+  throws(() => (Extension(c)?.field = new Class()).field);
+  throws(() => (Extension(c)?.method()).field);
   c = Extension(c)?.field.field = new Class();
   Extension(c)?.field.method();
   Extension(c)?.field = new Class().field;
@@ -117,8 +122,8 @@
 }
 
 void operatorAccess(Class? c) {
-  // TODO(johnniwinther): + should _not_ be null-shortened.
-  Extension(c)?.field + 0;
+  throws(() => Extension(c)?.field + 0);
+  throws(() => -Extension(c)?.field);
   Extension(c)?.field += 0;
   c = Extension(c)?.field += 0;
   Extension(c)?.field.field += 0;
@@ -136,3 +141,12 @@
   c = Extension(c)?.field ??= c;
   Extension(c)?.field[c] ??= c;
 }
+
+void throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Expected exception.';
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
index b39c0d9..8a55652 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
@@ -14,6 +14,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -30,6 +31,8 @@
   ;
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   ;
+static method Extension|unary-(final self::Class #this) → self::Class?
+  ;
 static method main() → dynamic
   ;
 static method propertyAccess(self::Class? c) → void
@@ -40,3 +43,5 @@
   ;
 static method ifNull(self::Class? c) → void
   ;
+static method throws(() → void f) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
index d579764..a988b01 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
@@ -15,6 +15,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -33,6 +34,8 @@
 }
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   return self::Extension|get#field(#this);
+static method Extension|unary-(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
 static method main() → dynamic {
   self::propertyAccess(null);
   self::indexAccess(null);
@@ -46,87 +49,100 @@
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
   let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
   let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
-  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
-  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
-  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
-  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
-  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
-  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
-  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
-  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
-  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
-  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
-  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
-  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
-  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
-  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
-  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
-  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
-  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
-  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
-  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
-  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
-  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
-  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
-  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
-  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
-  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
-  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
-  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+  c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+  c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+  let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+  let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
+  c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
+  let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
+  let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+  c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
+  let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
+  let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+  c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
+  let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
+  let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+  let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
-  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
-  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
-  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
-  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
-  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
-  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
-  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
-  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
-  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
+  let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
+  c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
+  let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
+  let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
+  c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
+  let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
+  c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
+  let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
-  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
-  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
-  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
-  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
-  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
-  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final self::Class? #t190 = let final self::Class? #t191 = self::Extension|+(#t189, 1) in let final void #t192 = self::Extension|set#field(#t188, #t191) in #t191 in #t189;
-  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 1) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
-  c = let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t197 = self::Extension|+(self::Extension|get#field(#t196), 1) in let final void #t198 = self::Extension|set#field(#t196, #t197) in #t197;
+  self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
+  self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
+  let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
+  c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
+  c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final self::Class? #t196 = let final self::Class? #t197 = self::Extension|+(#t195, 1) in let final void #t198 = self::Extension|set#field(#t194, #t197) in #t197 in #t195;
+  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t200 = self::Extension|+(self::Extension|get#field(#t199), 1) in let final void #t201 = self::Extension|set#field(#t199, #t200) in #t200;
+  c = let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t199).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t199, c) : null;
-  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|get#field(#t200) in #t201.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t202 = c in let final void #t203 = self::Extension|set#field(#t200, #t202) in #t202 : #t201;
-  let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in let final self::Class? #t206 = c in self::Extension|[](#t205, #t206).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t205, #t206, c) : null;
+  let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t205).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t205, c) : null;
+  c = let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t207 = self::Extension|get#field(#t206) in #t207.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t208 = c in let final void #t209 = self::Extension|set#field(#t206, #t208) in #t208 : #t207;
+  let final self::Class? #t210 = c in #t210.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t211 = self::Extension|get#field(#t210) in let final self::Class? #t212 = c in self::Extension|[](#t211, #t212).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t211, #t212, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
index d579764..a988b01 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
@@ -15,6 +15,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -33,6 +34,8 @@
 }
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   return self::Extension|get#field(#this);
+static method Extension|unary-(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
 static method main() → dynamic {
   self::propertyAccess(null);
   self::indexAccess(null);
@@ -46,87 +49,100 @@
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
   let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
   let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
-  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
-  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
-  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
-  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
-  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
-  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
-  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
-  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
-  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
-  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
-  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
-  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
-  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
-  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
-  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
-  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
-  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
-  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
-  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
-  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
-  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
-  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
-  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
-  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
-  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
-  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
-  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+  c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+  c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+  let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+  let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
+  c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
+  let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
+  let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+  c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
+  let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
+  let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+  c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
+  let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
+  let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+  let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
-  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
-  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
-  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
-  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
-  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
-  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
-  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
-  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
-  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
+  let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
+  c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
+  let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
+  let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
+  c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
+  let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
+  c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
+  let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
-  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
-  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
-  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
-  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
-  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
-  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final self::Class? #t190 = let final self::Class? #t191 = self::Extension|+(#t189, 1) in let final void #t192 = self::Extension|set#field(#t188, #t191) in #t191 in #t189;
-  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 1) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
-  c = let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t197 = self::Extension|+(self::Extension|get#field(#t196), 1) in let final void #t198 = self::Extension|set#field(#t196, #t197) in #t197;
+  self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
+  self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
+  let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
+  c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
+  c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final self::Class? #t196 = let final self::Class? #t197 = self::Extension|+(#t195, 1) in let final void #t198 = self::Extension|set#field(#t194, #t197) in #t197 in #t195;
+  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t200 = self::Extension|+(self::Extension|get#field(#t199), 1) in let final void #t201 = self::Extension|set#field(#t199, #t200) in #t200;
+  c = let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t199).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t199, c) : null;
-  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|get#field(#t200) in #t201.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t202 = c in let final void #t203 = self::Extension|set#field(#t200, #t202) in #t202 : #t201;
-  let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in let final self::Class? #t206 = c in self::Extension|[](#t205, #t206).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t205, #t206, c) : null;
+  let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t205).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t205, c) : null;
+  c = let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t207 = self::Extension|get#field(#t206) in #t207.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t208 = c in let final void #t209 = self::Extension|set#field(#t206, #t208) in #t208 : #t207;
+  let final self::Class? #t210 = c in #t210.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t211 = self::Extension|get#field(#t210) in let final self::Class? #t212 = c in self::Extension|[](#t211, #t212).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t211, #t212, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect
deleted file mode 100644
index c773aae..0000000
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect
+++ /dev/null
@@ -1,93 +0,0 @@
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:35:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:40:5: Context: Write to c@681
-  c = Extension(c)?.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:43:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:45:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:47:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:54:5: Context: Write to c@681
-  c = Extension(c)?.field.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:57:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:59:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:61:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field.method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:67:5: Context: Write to c@681
-  c = Extension(c)?.field.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:69:5: Context: Write to c@681
-  c = Extension(c)?.field.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:71:5: Context: Write to c@681
-  c = Extension(c)?.field.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:73:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:75:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:77:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:79:5: Context: Write to c@681
-  c = Extension(c)?.method().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:81:5: Context: Write to c@681
-  c = Extension(c)?.method().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:83:5: Context: Write to c@681
-  c = Extension(c)?.method().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:87:5: Context: Write to c@681
-  c = Extension(c)?.field.method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:90:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().method().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:92:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:94:5: Context: Write to c@681
-  c = Extension(c)?.field = new Class().method().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:107:5: Context: Write to c@681
-  c = Extension(c)?.field[c] = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:110:5: Context: Write to c@681
-  c = Extension(c)?.field[c] += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:114:5: Context: Write to c@681
-  c = Extension(c)?.field[c]++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:116:5: Context: Write to c@681
-  c = ++Extension(c)?.field[c];
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:123:5: Context: Write to c@681
-  c = Extension(c)?.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:125:5: Context: Write to c@681
-  c = Extension(c)?.field.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:129:5: Context: Write to c@681
-  c = Extension(c)?.field++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:131:5: Context: Write to c@681
-  c = ++Extension(c)?.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:136:5: Context: Write to c@681
-  c = Extension(c)?.field ??= c;
-    ^
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
index ee725c7..25f6e4e 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
@@ -20,6 +20,8 @@
   }
 
   Class? operator +(int value) => field;
+
+  Class? operator -() => field;
 }
 
 main() {
@@ -37,6 +39,9 @@
 
   c?.field.field;
   c?.field.field = new Class();
+  throws(() => (c?.field).field);
+  throws(() => (c?.field = new Class()).field);
+  throws(() => (c?.method()).field);
   c = c?.field.field = new Class();
   c?.field.method();
   c?.field = new Class().field;
@@ -117,8 +122,8 @@
 }
 
 void operatorAccess(Class? c) {
-  // TODO(johnniwinther): + should _not_ be null-shortened.
-  c?.field + 0;
+  throws(() => c?.field + 0);
+  throws(() => -c?.field);
   c?.field += 0;
   c = c?.field += 0;
   c?.field.field += 0;
@@ -136,3 +141,12 @@
   c = c?.field ??= c;
   c?.field[c] ??= c;
 }
+
+void throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Expected exception.';
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
index b39c0d9..8a55652 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
@@ -14,6 +14,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -30,6 +31,8 @@
   ;
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   ;
+static method Extension|unary-(final self::Class #this) → self::Class?
+  ;
 static method main() → dynamic
   ;
 static method propertyAccess(self::Class? c) → void
@@ -40,3 +43,5 @@
   ;
 static method ifNull(self::Class? c) → void
   ;
+static method throws(() → void f) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
index 8bb6efe..ac7b6fb 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
@@ -15,6 +15,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -33,6 +34,8 @@
 }
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   return self::Extension|get#field(#this);
+static method Extension|unary-(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
 static method main() → dynamic {
   self::propertyAccess(null);
   self::indexAccess(null);
@@ -46,87 +49,100 @@
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
   let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
   let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
-  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
-  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
-  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
-  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
-  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
-  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
-  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
-  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
-  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
-  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
-  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
-  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
-  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
-  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
-  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
-  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
-  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
-  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
-  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
-  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
-  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
-  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
-  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
-  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
-  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
-  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
-  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+  c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+  c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+  let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+  let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
+  c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
+  let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
+  let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+  c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
+  let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
+  let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+  c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
+  let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
+  let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+  let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
-  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
-  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
-  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
-  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
-  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
-  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
-  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
-  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
-  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
+  let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
+  c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
+  let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
+  let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
+  c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
+  let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
+  c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
+  let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
-  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
-  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
-  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
-  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
-  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
-  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final void #t190 = self::Extension|set#field(#t188, self::Extension|+(#t189, 1)) in #t189;
-  let final self::Class? #t191 = c in #t191.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t192 = self::Extension|+(self::Extension|get#field(#t191), 1) in let final void #t193 = self::Extension|set#field(#t191, #t192) in #t192;
-  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|+(self::Extension|get#field(#t194), 1) in let final void #t196 = self::Extension|set#field(#t194, #t195) in #t195;
+  self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
+  self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
+  let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
+  c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
+  c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final void #t196 = self::Extension|set#field(#t194, self::Extension|+(#t195, 1)) in #t195;
+  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|+(self::Extension|get#field(#t197), 1) in let final void #t199 = self::Extension|set#field(#t197, #t198) in #t198;
+  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t197).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t197, c) : null;
-  c = let final self::Class? #t198 = c in #t198.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t199 = self::Extension|get#field(#t198) in #t199.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t200 = c in let final void #t201 = self::Extension|set#field(#t198, #t200) in #t200 : #t199;
-  let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|get#field(#t202) in let final self::Class? #t204 = c in self::Extension|[](#t203, #t204).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t203, #t204, c) : null;
+  let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t203).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t203, c) : null;
+  c = let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in #t205.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t206 = c in let final void #t207 = self::Extension|set#field(#t204, #t206) in #t206 : #t205;
+  let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t209 = self::Extension|get#field(#t208) in let final self::Class? #t210 = c in self::Extension|[](#t209, #t210).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t209, #t210, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
index 8bb6efe..ac7b6fb 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
@@ -15,6 +15,7 @@
   operator [] = self::Extension|[];
   operator []= = self::Extension|[]=;
   operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
   set field = self::Extension|set#field;
 }
 static method Extension|get#field(final self::Class #this) → self::Class?
@@ -33,6 +34,8 @@
 }
 static method Extension|+(final self::Class #this, core::int value) → self::Class?
   return self::Extension|get#field(#this);
+static method Extension|unary-(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
 static method main() → dynamic {
   self::propertyAccess(null);
   self::indexAccess(null);
@@ -46,87 +49,100 @@
   let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
   let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
   let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
-  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
-  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
-  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
-  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
-  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
-  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
-  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
-  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
-  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
-  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
-  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
-  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
-  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
-  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
-  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
-  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
-  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
-  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
-  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
-  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
-  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
-  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
-  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
-  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
-  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
-  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
-  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
-  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
-  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
-  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
-  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
-  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
-  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
-  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
-  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
-  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
-  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
-  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
-  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
-  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
-  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
-  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
-  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
-  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
-  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
-  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
-  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
-  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
-  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+  self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
+  let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+  let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+  c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
+  let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+  c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+  let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+  let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
+  c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
+  let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
+  let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+  c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
+  let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
+  let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+  c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
+  let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
+  let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+  let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
 }
 static method indexAccess(self::Class? c) → void {
-  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
-  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
-  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
-  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
-  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
-  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
-  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
-  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
-  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
-  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
+  let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
+  c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
+  let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
+  let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
+  c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
+  let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
+  c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
+  let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+  c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
 }
 static method operatorAccess(self::Class? c) → void {
-  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
-  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
-  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
-  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
-  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
-  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
-  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final void #t190 = self::Extension|set#field(#t188, self::Extension|+(#t189, 1)) in #t189;
-  let final self::Class? #t191 = c in #t191.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t192 = self::Extension|+(self::Extension|get#field(#t191), 1) in let final void #t193 = self::Extension|set#field(#t191, #t192) in #t192;
-  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|+(self::Extension|get#field(#t194), 1) in let final void #t196 = self::Extension|set#field(#t194, #t195) in #t195;
+  self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
+  self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
+  let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
+  c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
+  c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final void #t196 = self::Extension|set#field(#t194, self::Extension|+(#t195, 1)) in #t195;
+  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|+(self::Extension|get#field(#t197), 1) in let final void #t199 = self::Extension|set#field(#t197, #t198) in #t198;
+  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
 }
 static method ifNull(self::Class? c) → void {
-  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t197).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t197, c) : null;
-  c = let final self::Class? #t198 = c in #t198.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t199 = self::Extension|get#field(#t198) in #t199.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t200 = c in let final void #t201 = self::Extension|set#field(#t198, #t200) in #t200 : #t199;
-  let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|get#field(#t202) in let final self::Class? #t204 = c in self::Extension|[](#t203, #t204).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t203, #t204, c) : null;
+  let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t203).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t203, c) : null;
+  c = let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in #t205.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t206 = c in let final void #t207 = self::Extension|set#field(#t204, #t206) in #t206 : #t205;
+  let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t209 = self::Extension|get#field(#t208) in let final self::Class? #t210 = c in self::Extension|[](#t209, #t210).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t209, #t210, c) : null;
+}
+static method throws(() → void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception.";
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect
deleted file mode 100644
index e88f73d..0000000
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect
+++ /dev/null
@@ -1,93 +0,0 @@
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:35:5: Context: Write to c@681
-  c = c?.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:40:5: Context: Write to c@681
-  c = c?.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:43:5: Context: Write to c@681
-  c = c?.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:45:5: Context: Write to c@681
-  c = c?.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:47:5: Context: Write to c@681
-  c = c?.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:54:5: Context: Write to c@681
-  c = c?.field.field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:57:5: Context: Write to c@681
-  c = c?.field = new Class().field.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:59:5: Context: Write to c@681
-  c = c?.field = new Class().field.field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:61:5: Context: Write to c@681
-  c = c?.field = new Class().field.method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:67:5: Context: Write to c@681
-  c = c?.field.field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:69:5: Context: Write to c@681
-  c = c?.field.field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:71:5: Context: Write to c@681
-  c = c?.field.field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:73:5: Context: Write to c@681
-  c = c?.field = new Class().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:75:5: Context: Write to c@681
-  c = c?.field = new Class().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:77:5: Context: Write to c@681
-  c = c?.field = new Class().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:79:5: Context: Write to c@681
-  c = c?.method().field = new Class().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:81:5: Context: Write to c@681
-  c = c?.method().field = new Class().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:83:5: Context: Write to c@681
-  c = c?.method().field = new Class().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:87:5: Context: Write to c@681
-  c = c?.field.method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:90:5: Context: Write to c@681
-  c = c?.field = new Class().method().field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:92:5: Context: Write to c@681
-  c = c?.field = new Class().method().field = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:94:5: Context: Write to c@681
-  c = c?.field = new Class().method().method();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:107:5: Context: Write to c@681
-  c = c?.field[c] = new Class();
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:110:5: Context: Write to c@681
-  c = c?.field[c] += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:114:5: Context: Write to c@681
-  c = c?.field[c]++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:116:5: Context: Write to c@681
-  c = ++c?.field[c];
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:123:5: Context: Write to c@681
-  c = c?.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:125:5: Context: Write to c@681
-  c = c?.field.field += 0;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:129:5: Context: Write to c@681
-  c = c?.field++;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:131:5: Context: Write to c@681
-  c = ++c?.field;
-    ^
-pkg/front_end/testcases/nnbd/null_shorting_extension.dart:136:5: Context: Write to c@681
-  c = c?.field ??= c;
-    ^
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart b/pkg/front_end/testcases/nnbd/opt_out.dart
new file mode 100644
index 0000000..8816bd9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'opt_out_lib.dart';
+
+main() {}
+
+noErrors() {
+  String? s = null;
+}
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect
new file mode 100644
index 0000000..0661ed3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///opt_out_lib.dart";
+
+static method main() → dynamic
+  ;
+static method noErrors() → dynamic
+  ;
+
+library;
+import self as self2;
+
+static method errors() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect
new file mode 100644
index 0000000..4d98003
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///opt_out_lib.dart";
+
+static method main() → dynamic {}
+static method noErrors() → dynamic {
+  core::String? s = null;
+}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/opt_out_lib.dart:8:9: Error: This requires the 'non-nullable' experiment to be enabled.
+// Try enabling this experiment by adding it to the command line when compiling and running.
+//   String? s = null;
+//         ^
+//
+import self as self2;
+import "dart:core" as core;
+
+static method errors() → dynamic {
+  core::String? s = null;
+}
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..4d98003
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///opt_out_lib.dart";
+
+static method main() → dynamic {}
+static method noErrors() → dynamic {
+  core::String? s = null;
+}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/opt_out_lib.dart:8:9: Error: This requires the 'non-nullable' experiment to be enabled.
+// Try enabling this experiment by adding it to the command line when compiling and running.
+//   String? s = null;
+//         ^
+//
+import self as self2;
+import "dart:core" as core;
+
+static method errors() → dynamic {
+  core::String? s = null;
+}
diff --git a/pkg/front_end/testcases/nnbd/opt_out_lib.dart b/pkg/front_end/testcases/nnbd/opt_out_lib.dart
new file mode 100644
index 0000000..789d84a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/opt_out_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+errors() {
+  String? s = null;
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect
deleted file mode 100644
index 8dc5a4c..0000000
--- a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart:34:14: Context: Write to value@1053
-  if ((value = b.foo()) != "baz") {
-             ^
-pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart:37:14: Context: Write to value@1053
-  if ((value = b.hest()) != 42) {
-             ^
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index e90a514..33482fb 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -43,6 +43,8 @@
 inference_new/infer_field_override_accessors: TypeCheckError
 inference_new/infer_field_override_getter_overrides_setter: TypeCheckError
 
+nnbd/inheritance_from_opt_out: TypeCheckError
+
 rasta/native_is_illegal: Pass # Issue 29763
 
 runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect
deleted file mode 100644
index 2beae6f..0000000
--- a/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/rasta/for_loop.dart:7:29: Context: Write to i@292
-  for (int i = 0; i < 100; i++) {
-                            ^^
-pkg/front_end/testcases/rasta/for_loop.dart:8:12: Context: Write to i@292
-    print(i++);
-           ^^
-pkg/front_end/testcases/rasta/for_loop.dart:10:53: Context: Write to i@292
-  for (int i = 0; i < 100; c < 42 ? throw "fisk" : i++) {
-                                                    ^^
-pkg/front_end/testcases/rasta/for_loop.dart:11:12: Context: Write to i@292
-    print(i++);
-           ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect
deleted file mode 100644
index 4904aab..0000000
--- a/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/rasta/issue_000004.dart:10:7: Context: Write to f@273
-    f *= n;
-      ^^
-pkg/front_end/testcases/rasta/issue_000004.dart:18:7: Context: Write to f@359
-    f *= n;
-      ^^
-pkg/front_end/testcases/rasta/issue_000004.dart:27:7: Context: Write to f@459
-    f *= global;
-      ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect
deleted file mode 100644
index f2b5d7c..0000000
--- a/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/rasta/issue_000069.dart:7:11: Context: Write to i@237
-  while (i++ < 5) var x = i;
-          ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect
deleted file mode 100644
index 27f599e..0000000
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg/front_end/testcases/rasta/issue_000070.dart:11:21: Context: Possible promotion of n@306
-    Expect.isTrue(n is N);
-                    ^^
-pkg/front_end/testcases/rasta/issue_000070.dart:12:21: Context: Possible promotion of s@311
-    Expect.isTrue(s is S);
-                    ^^
-pkg/front_end/testcases/rasta/issue_000070.dart:18:21: Context: Possible promotion of s@311
-    Expect.isTrue(s is S);
-                    ^^
diff --git a/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect
deleted file mode 100644
index a1bf30c..0000000
--- a/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/rasta/super_operator.dart:18:34: Context: Write to i@401
-  operator []=(i, val) => super[i++] += val;
-                                 ^^
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect
deleted file mode 100644
index 4aebb51..0000000
--- a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:33:21: Context: Write to result@1329
-    case 1:  result = 1;
-                    ^
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:35:21: Context: Write to result@1329
-    case 2:  result = 2; /// static warning - case fall-through, see "Switch"
-                    ^
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:36:21: Context: Write to result@1329
-    case 3:  result = 3; /// static warning - case fall-through, see "Switch"
-                    ^
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:37:21: Context: Write to result@1329
-    default: result = 4;
-                    ^
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:47:20: Context: Write to result@1636
-    case 2: result = 1; /// static warning - case fall-through, see "Switch"
-                   ^
-pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:49:20: Context: Write to result@1636
-    case 4: result = 2;
-                   ^
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect
deleted file mode 100644
index 9514d8e..0000000
--- a/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/regress/issue_31184.dart:6:28: Context: Write to i@243
-  for (int i = 0, i > 10; i++) {}
-                           ^^
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect
deleted file mode 100644
index 64406e2..0000000
--- a/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect
+++ /dev/null
@@ -1,15 +0,0 @@
-pkg/front_end/testcases/regress/issue_33452.dart:11:5: Context: Write to x@296
-  x = new ExistingClass();
-    ^
-pkg/front_end/testcases/regress/issue_33452.dart:12:5: Context: Write to x@296
-  x = new ExistingClass<String>();
-    ^
-pkg/front_end/testcases/regress/issue_33452.dart:13:5: Context: Write to x@296
-  x = new ExistingClass<String>.nonExistingConstructor();
-    ^
-pkg/front_end/testcases/regress/issue_33452.dart:14:5: Context: Write to x@296
-  x = new ExistingClass<String, String>.nonExistingConstructor();
-    ^
-pkg/front_end/testcases/regress/issue_33452.dart:15:5: Context: Write to x@296
-  x = new NonExistingClass();
-    ^
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect
deleted file mode 100644
index 929bc26..0000000
--- a/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-pkg/front_end/testcases/regress/issue_33672.dart:7:34: Context: Write to a@260
-  yield: for (int a = 0; a < 10; ++a) {
-                                 ^^
-pkg/front_end/testcases/regress/issue_33672.dart:8:29: Context: Write to b@295
-    for (int b = 0; b < 10; ++b) {
-                            ^^
-pkg/front_end/testcases/regress/issue_33672.dart:9:7: Context: Write to count@231
-      ++count;
-      ^^
-pkg/front_end/testcases/regress/issue_33672.dart:12:5: Context: Write to count@231
-    ++count;
-    ^^
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect
deleted file mode 100644
index 77d54c8..0000000
--- a/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart:11:25: Context: Write to i@310
-    for (int i = 0; o; i++) {}
-                        ^^
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect
deleted file mode 100644
index 0a2841f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart:22:50: Context: Write to b@535
-  b /*@ checkReturn=B<num*, (num*) ->* void>* */ += 1;
-                                                 ^^
-pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart:23:58: Context: Write to b@535
-  var x = b /*@ checkReturn=B<num*, (num*) ->* void>* */ += 2;
-                                                         ^^
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect
deleted file mode 100644
index 52a0161..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:51:5: Context: Write to d@1119
-  d = new D(new C(numToNum));
-    ^
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index a78d1d1..626187039 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -112,6 +112,7 @@
 instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError # Expected
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError # Expected
 nnbd/nullable_param: RuntimeError
+nnbd/inheritance_from_opt_out: TypeCheckError
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
 rasta/bad_continue: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 681bed8..c70f507 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,7 +6,6 @@
 # the round trip for Kernel textual serialization where the initial binary
 # Kernel files are produced by compiling Dart code via Fasta.
 
-all_variances: TextSerializationFailure
 expression/eval: TextSerializationFailure # Was: Pass
 expression/main: TextSerializationFailure # Was: Pass
 extensions/annotations: TextSerializationFailure
@@ -16,6 +15,8 @@
 extensions/conflict_with_object: TextSerializationFailure
 extensions/conflicts: TextSerializationFailure
 extensions/default_values: TextSerializationFailure
+extensions/deferred_explicit_access: TextSerializationFailure
+extensions/deferred_import_hidden: TextSerializationFailure
 extensions/direct_instance_access: TextSerializationFailure
 extensions/direct_static_access: TextSerializationFailure
 extensions/dynamic_invoke: TextSerializationFailure
@@ -35,6 +36,7 @@
 extensions/if_null: TextSerializationFailure
 extensions/implicit_extension_inference: TextSerializationFailure
 extensions/implicit_this: TextSerializationFailure
+extensions/import_via_prefix: TextSerializationFailure
 extensions/index: TextSerializationFailure
 extensions/instance_access: TextSerializationFailure
 extensions/instance_access_of_static: TextSerializationFailure
@@ -69,6 +71,7 @@
 general/abstract_members: TypeCheckError
 general/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
 general/accessors: TextSerializationFailure # Was: RuntimeError
+general/all_variances: TextSerializationFailure
 general/ambiguous_exports: TextSerializationFailure # Was: RuntimeError # Expected, this file exports two main methods.
 general/annotation_eof: TextSerializationFailure # Was: Pass
 general/annotation_on_enum_values: TextSerializationFailure # Was: Pass
@@ -235,6 +238,7 @@
 general/nested_implicit_const_with_env_var: TextSerializationFailure # Was: Pass
 general/nested_property_set: TextSerializationFailure
 general/nested_variable_set: TextSerializationFailure
+general/nested_variance: TextSerializationFailure
 general/no_such_method_private_setter: TextSerializationFailure # Was: Pass
 general/no_such_method_private_setter_lib: TextSerializationFailure # Was: Pass
 general/non_covariant_checks: TextSerializationFailure
@@ -885,10 +889,12 @@
 instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
-nested_variance_test: TextSerializationFailure
 new_const_insertion/simple: TextSerializationFailure # Was: Pass
 nnbd/function_types: TextSerializationFailure
+nnbd/inheritance_from_opt_out: TypeCheckError
 nnbd/intersection_types: TextSerializationFailure
+nnbd/issue_39286: TextSerializationFailure
+nnbd/issue_39286_2: TextSerializationFailure
 nnbd/late: TextSerializationFailure
 nnbd/null_check: TextSerializationFailure
 nnbd/null_shorting: TextSerializationFailure
@@ -896,6 +902,7 @@
 nnbd/null_shorting_extension: TextSerializationFailure
 nnbd/nullable_null: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
+nnbd/opt_out: TextSerializationFailure
 nnbd/required: TextSerializationFailure
 nnbd/simple_never: TextSerializationFailure
 nnbd/substitution_in_inference: TextSerializationFailure
@@ -1166,3 +1173,4 @@
 unified_collections/mixed_entries: TextSerializationFailure
 variance/class_type_parameter_modifier: TextSerializationFailure
 variance/mixin_type_parameter_modifier: TextSerializationFailure
+variance/generic_covariance_sound_variance: TextSerializationFailure
diff --git a/pkg/front_end/testcases/type_promotion_look_ahead.status b/pkg/front_end/testcases/type_promotion_look_ahead.status
deleted file mode 100644
index bee4fdc..0000000
--- a/pkg/front_end/testcases/type_promotion_look_ahead.status
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE.md file.
-
-# Status file for the ../test/fasta/type_promotion_look_ahead_test.dart test suite.
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect
deleted file mode 100644
index f87b142..0000000
--- a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:21:64: Context: Write to i@665
-var map8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]: 1};
-                                                               ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:22:54: Context: Write to i@665
-var map9 = {if (b) for (var i = 0; i < list.length; i++) list[i]: 1 else 0: 1};
-                                                     ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:24:54: Context: Write to i@665
-  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]: 1}
-                                                     ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:27:44: Context: Write to i@665
-  if (b) for (var i = 0; i < list.length; i++) ...{list[i]: 1} else 0: 1
-                                           ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:66: Context: Write to i@665
-var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
-                                                                 ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:56: Context: Write to i@665
-var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
-                                                       ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:44:54: Context: Write to i@665
-  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]}
-                                                     ^^
-pkg/front_end/testcases/unified_collections/mixed_entries.dart:47:44: Context: Write to i@665
-  if (b) for (var i = 0; i < list.length; i++) ...{list[i]} else 0: 1
-                                           ^^
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart
new file mode 100644
index 0000000..9400df5
--- /dev/null
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+typedef ContraFunction<T> = void Function(T);
+typedef InvFunction<T> = T Function(T);
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
+class A<in T, out U, V> {
+  final void Function(T) field = null;
+  void method(T t, void Function(U) u, V v) {}
+  void method2(T x, [T y]) {}
+  void set x(T t) {}
+  Map<U, Contravariant<V>> get mapContra => new Map<U, Contravariant<V>>();
+  Map<U, ContraFunction<V>> get mapContraFn => new Map<U, ContraFunction<V>>();
+  Map<U, Invariant<V>> get mapInv => new Map<U, Invariant<V>>();
+  Map<U, InvFunction<V>> get mapInvFn => new Map<U, InvFunction<V>>();
+}
+
+class B<inout T> {
+  T x;
+  T method(T x) => null;
+  void set y(T x) {}
+}
+
+class C<in T> {
+  final void Function(T) field = null;
+  void method(T x, [T y]) {}
+  void set x(T t) {}
+}
+
+abstract class D<T> {
+  int method(T x);
+}
+
+class E<inout T> {
+  final void Function(T) f;
+  E(this.f);
+  int method(T x) {
+    f(x);
+  }
+}
+
+class F<inout T> extends E<T> implements D<T> {
+  F(void Function(T) f) : super(f);
+}
+
+main() {
+  A<int, num, String> a = new A();
+  expect(null, a.field);
+  a.method(3, (num) {}, "test");
+  a.method2(3);
+  a.x = 3;
+  Map<num, Contravariant<String>> mapContra = a.mapContra;
+  Map<num, ContraFunction<String>> mapContraFn = a.mapContraFn;
+  Map<num, Invariant<String>> mapInv = a.mapInv;
+  Map<num, InvFunction<String>> mapInvFn = a.mapInvFn;
+
+  B<int> b = new B();
+  b.x = 3;
+  expect(3, b.x);
+  expect(null, b.method(3));
+  b.y = 3;
+
+  C<int> c = new C();
+  expect(null, c.field);
+  c.method(3, 2);
+  c.x = 3;
+
+  D<Object> d = new F<String>((String s) {});
+  d.method("test");
+}
+
+expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Mismatch: expected=$expected, actual=$actual';
+  }
+}
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
new file mode 100644
index 0000000..6260243
--- /dev/null
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
@@ -0,0 +1,73 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef ContraFunction<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef InvFunction<invariant T extends core::Object* = dynamic> = (T*) →* T*;
+class Contravariant<contravariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Contravariant<self::Contravariant::T*>*
+    ;
+}
+class Invariant<invariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Invariant<self::Invariant::T*>*
+    ;
+}
+class A<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  final field (self::A::T*) →* void field;
+  synthetic constructor •() → self::A<self::A::T*, self::A::U*, self::A::V*>*
+    ;
+  method method(self::A::T* t, (self::A::U*) →* void u, generic-covariant-impl self::A::V* v) → void
+    ;
+  method method2(self::A::T* x, [self::A::T* y]) → void
+    ;
+  set x(self::A::T* t) → void
+    ;
+  get mapContra() → core::Map<self::A::U*, self::Contravariant<self::A::V*>*>*
+    ;
+  get mapContraFn() → core::Map<self::A::U*, (self::A::V*) →* void>*
+    ;
+  get mapInv() → core::Map<self::A::U*, self::Invariant<self::A::V*>*>*
+    ;
+  get mapInvFn() → core::Map<self::A::U*, (self::A::V*) →* self::A::V*>*
+    ;
+}
+class B<invariant T extends core::Object* = dynamic> extends core::Object {
+  field self::B::T* x;
+  synthetic constructor •() → self::B<self::B::T*>*
+    ;
+  method method(self::B::T* x) → self::B::T*
+    ;
+  set y(self::B::T* x) → void
+    ;
+}
+class C<contravariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::C::T*) →* void field;
+  synthetic constructor •() → self::C<self::C::T*>*
+    ;
+  method method(self::C::T* x, [self::C::T* y]) → void
+    ;
+  set x(self::C::T* t) → void
+    ;
+}
+abstract class D<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::T*>*
+    ;
+  abstract method method(generic-covariant-impl self::D::T* x) → core::int*;
+}
+class E<invariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::E::T*) →* void f;
+  constructor •((self::E::T*) →* void f) → self::E<self::E::T*>*
+    ;
+  method method(self::E::T* x) → core::int*
+    ;
+}
+class F<invariant T extends core::Object* = dynamic> extends self::E<self::F::T*> implements self::D<self::F::T*> {
+  constructor •((self::F::T*) →* void f) → self::F<self::F::T*>*
+    ;
+  forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
+    return super.{self::E::method}(x);
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect
new file mode 100644
index 0000000..0c751d4
--- /dev/null
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect
@@ -0,0 +1,103 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef ContraFunction<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef InvFunction<invariant T extends core::Object* = dynamic> = (T*) →* T*;
+class Contravariant<contravariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Contravariant<self::Contravariant::T*>*
+    : super core::Object::•()
+    ;
+}
+class Invariant<invariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Invariant<self::Invariant::T*>*
+    : super core::Object::•()
+    ;
+}
+class A<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  final field (self::A::T*) →* void field = null;
+  synthetic constructor •() → self::A<self::A::T*, self::A::U*, self::A::V*>*
+    : super core::Object::•()
+    ;
+  method method(self::A::T* t, (self::A::U*) →* void u, generic-covariant-impl self::A::V* v) → void {}
+  method method2(self::A::T* x, [self::A::T* y = #C1]) → void {}
+  set x(self::A::T* t) → void {}
+  get mapContra() → core::Map<self::A::U*, self::Contravariant<self::A::V*>*>*
+    return core::Map::•<self::A::U*, self::Contravariant<self::A::V*>*>();
+  get mapContraFn() → core::Map<self::A::U*, (self::A::V*) →* void>*
+    return core::Map::•<self::A::U*, (self::A::V*) →* void>();
+  get mapInv() → core::Map<self::A::U*, self::Invariant<self::A::V*>*>*
+    return core::Map::•<self::A::U*, self::Invariant<self::A::V*>*>();
+  get mapInvFn() → core::Map<self::A::U*, (self::A::V*) →* self::A::V*>*
+    return core::Map::•<self::A::U*, (self::A::V*) →* self::A::V*>();
+}
+class B<invariant T extends core::Object* = dynamic> extends core::Object {
+  field self::B::T* x = null;
+  synthetic constructor •() → self::B<self::B::T*>*
+    : super core::Object::•()
+    ;
+  method method(self::B::T* x) → self::B::T*
+    return null;
+  set y(self::B::T* x) → void {}
+}
+class C<contravariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::C::T*) →* void field = null;
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  method method(self::C::T* x, [self::C::T* y = #C1]) → void {}
+  set x(self::C::T* t) → void {}
+}
+abstract class D<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::T*>*
+    : super core::Object::•()
+    ;
+  abstract method method(generic-covariant-impl self::D::T* x) → core::int*;
+}
+class E<invariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::E::T*) →* void f;
+  constructor •((self::E::T*) →* void f) → self::E<self::E::T*>*
+    : self::E::f = f, super core::Object::•()
+    ;
+  method method(self::E::T* x) → core::int* {
+    this.{self::E::f}(x);
+  }
+}
+class F<invariant T extends core::Object* = dynamic> extends self::E<self::F::T*> implements self::D<self::F::T*> {
+  constructor •((self::F::T*) →* void f) → self::F<self::F::T*>*
+    : super self::E::•(f)
+    ;
+  forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
+    return super.{self::E::method}(x);
+}
+static method main() → dynamic {
+  self::A<core::int*, core::num*, core::String*>* a = new self::A::•<core::int*, core::num*, core::String*>();
+  self::expect(null, a.{self::A::field});
+  a.{self::A::method}(3, (core::num* num) → core::Null? {}, "test");
+  a.{self::A::method2}(3);
+  a.{self::A::x} = 3;
+  core::Map<core::num*, self::Contravariant<core::String*>*>* mapContra = a.{self::A::mapContra} as{TypeError} core::Map<core::num*, self::Contravariant<core::String*>*>*;
+  core::Map<core::num*, (core::String*) →* void>* mapContraFn = a.{self::A::mapContraFn} as{TypeError} core::Map<core::num*, (core::String*) →* void>*;
+  core::Map<core::num*, self::Invariant<core::String*>*>* mapInv = a.{self::A::mapInv} as{TypeError} core::Map<core::num*, self::Invariant<core::String*>*>*;
+  core::Map<core::num*, (core::String*) →* core::String*>* mapInvFn = a.{self::A::mapInvFn} as{TypeError} core::Map<core::num*, (core::String*) →* core::String*>*;
+  self::B<core::int*>* b = new self::B::•<core::int*>();
+  b.{self::B::x} = 3;
+  self::expect(3, b.{self::B::x});
+  self::expect(null, b.{self::B::method}(3));
+  b.{self::B::y} = 3;
+  self::C<core::int*>* c = new self::C::•<core::int*>();
+  self::expect(null, c.{self::C::field});
+  c.{self::C::method}(3, 2);
+  c.{self::C::x} = 3;
+  self::D<core::Object*>* d = new self::F::•<core::String*>((core::String* s) → core::Null? {});
+  d.{self::D::method}("test");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
new file mode 100644
index 0000000..0c751d4
--- /dev/null
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
@@ -0,0 +1,103 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef ContraFunction<contravariant T extends core::Object* = dynamic> = (T*) →* void;
+typedef InvFunction<invariant T extends core::Object* = dynamic> = (T*) →* T*;
+class Contravariant<contravariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Contravariant<self::Contravariant::T*>*
+    : super core::Object::•()
+    ;
+}
+class Invariant<invariant T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Invariant<self::Invariant::T*>*
+    : super core::Object::•()
+    ;
+}
+class A<contravariant T extends core::Object* = dynamic, U extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  final field (self::A::T*) →* void field = null;
+  synthetic constructor •() → self::A<self::A::T*, self::A::U*, self::A::V*>*
+    : super core::Object::•()
+    ;
+  method method(self::A::T* t, (self::A::U*) →* void u, generic-covariant-impl self::A::V* v) → void {}
+  method method2(self::A::T* x, [self::A::T* y = #C1]) → void {}
+  set x(self::A::T* t) → void {}
+  get mapContra() → core::Map<self::A::U*, self::Contravariant<self::A::V*>*>*
+    return core::Map::•<self::A::U*, self::Contravariant<self::A::V*>*>();
+  get mapContraFn() → core::Map<self::A::U*, (self::A::V*) →* void>*
+    return core::Map::•<self::A::U*, (self::A::V*) →* void>();
+  get mapInv() → core::Map<self::A::U*, self::Invariant<self::A::V*>*>*
+    return core::Map::•<self::A::U*, self::Invariant<self::A::V*>*>();
+  get mapInvFn() → core::Map<self::A::U*, (self::A::V*) →* self::A::V*>*
+    return core::Map::•<self::A::U*, (self::A::V*) →* self::A::V*>();
+}
+class B<invariant T extends core::Object* = dynamic> extends core::Object {
+  field self::B::T* x = null;
+  synthetic constructor •() → self::B<self::B::T*>*
+    : super core::Object::•()
+    ;
+  method method(self::B::T* x) → self::B::T*
+    return null;
+  set y(self::B::T* x) → void {}
+}
+class C<contravariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::C::T*) →* void field = null;
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  method method(self::C::T* x, [self::C::T* y = #C1]) → void {}
+  set x(self::C::T* t) → void {}
+}
+abstract class D<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::T*>*
+    : super core::Object::•()
+    ;
+  abstract method method(generic-covariant-impl self::D::T* x) → core::int*;
+}
+class E<invariant T extends core::Object* = dynamic> extends core::Object {
+  final field (self::E::T*) →* void f;
+  constructor •((self::E::T*) →* void f) → self::E<self::E::T*>*
+    : self::E::f = f, super core::Object::•()
+    ;
+  method method(self::E::T* x) → core::int* {
+    this.{self::E::f}(x);
+  }
+}
+class F<invariant T extends core::Object* = dynamic> extends self::E<self::F::T*> implements self::D<self::F::T*> {
+  constructor •((self::F::T*) →* void f) → self::F<self::F::T*>*
+    : super self::E::•(f)
+    ;
+  forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
+    return super.{self::E::method}(x);
+}
+static method main() → dynamic {
+  self::A<core::int*, core::num*, core::String*>* a = new self::A::•<core::int*, core::num*, core::String*>();
+  self::expect(null, a.{self::A::field});
+  a.{self::A::method}(3, (core::num* num) → core::Null? {}, "test");
+  a.{self::A::method2}(3);
+  a.{self::A::x} = 3;
+  core::Map<core::num*, self::Contravariant<core::String*>*>* mapContra = a.{self::A::mapContra} as{TypeError} core::Map<core::num*, self::Contravariant<core::String*>*>*;
+  core::Map<core::num*, (core::String*) →* void>* mapContraFn = a.{self::A::mapContraFn} as{TypeError} core::Map<core::num*, (core::String*) →* void>*;
+  core::Map<core::num*, self::Invariant<core::String*>*>* mapInv = a.{self::A::mapInv} as{TypeError} core::Map<core::num*, self::Invariant<core::String*>*>*;
+  core::Map<core::num*, (core::String*) →* core::String*>* mapInvFn = a.{self::A::mapInvFn} as{TypeError} core::Map<core::num*, (core::String*) →* core::String*>*;
+  self::B<core::int*>* b = new self::B::•<core::int*>();
+  b.{self::B::x} = 3;
+  self::expect(3, b.{self::B::x});
+  self::expect(null, b.{self::B::method}(3));
+  b.{self::B::y} = 3;
+  self::C<core::int*>* c = new self::C::•<core::int*>();
+  self::expect(null, c.{self::C::field});
+  c.{self::C::method}(3, 2);
+  c.{self::C::x} = 3;
+  self::D<core::Object*>* d = new self::F::•<core::String*>((core::String* s) → core::Null? {});
+  d.{self::D::method}("test");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 73550ac..e2cbcce 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -374,23 +374,6 @@
       "command-lines": [
         "-cdart2js -rd8 --use-sdk --minified language language_2 dart2js_extra dart2js_native corelib corelib_2"
       ]
-    },
-    {
-      "name": "type_promotion_look_ahead",
-      "kind": "Chain",
-      "source": "test/fasta/type_promotion_look_ahead_suite.dart",
-      "path": "testcases/",
-      "status": "testcases/type_promotion_look_ahead.status",
-      "pattern": [
-        "\\.dart$"
-      ],
-      "exclude": [
-        "/testcases/.*_part[0-9]*\\.dart$",
-        "/testcases/.*_lib[0-9]*\\.dart$",
-        "/testcases/dartino/",
-        "/testcases/shaker/",
-        "/testcases/expression/"
-      ]
     }
   ],
   "analyze": {
diff --git a/pkg/front_end/tool/_fasta/dump_partial.dart b/pkg/front_end/tool/_fasta/dump_partial.dart
index 875e62b..af8db5a 100644
--- a/pkg/front_end/tool/_fasta/dump_partial.dart
+++ b/pkg/front_end/tool/_fasta/dump_partial.dart
@@ -70,6 +70,7 @@
   // partial.dill file.
   loadComponentFromBytes(partialDill, context);
   var result = context.libraries
+      // ignore: DEPRECATED_MEMBER_USE
       .where((l) => !l.isExternal)
       .map((l) => l.importUri)
       .toSet();
@@ -78,5 +79,6 @@
 }
 
 void _updateIsExternal(Component component, bool toValue) {
+  // ignore: DEPRECATED_MEMBER_USE
   component.libraries.forEach((lib) => lib.isExternal = toValue);
 }
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index b4c1cde..15e2e6e 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -344,6 +344,7 @@
   }
 
   await writeComponentToFile(component, fullOutput,
+      // ignore: DEPRECATED_MEMBER_USE
       filter: (lib) => !lib.isExternal);
 
   c.options.ticker.logMs("Wrote component to ${fullOutput.toFilePath()}");
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index a047f73..2037866 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -219,10 +219,6 @@
 class _PartialAstBuilder extends AstBuilder {
   _PartialAstBuilder(Uri uri)
       : super(null, null, true, FeatureSet.fromEnableFlags([]), uri);
-
-  // Note: this method converts the body to kernel, so we skip that here.
-  @override
-  finishFunction(formals, asyncModifier, body) {}
 }
 
 // Invoke the fasta kernel generator for the program starting in [entryUri]
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 852fb49..176909e 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -53,8 +53,6 @@
   ..addFlag('aot',
       help: 'Run compiler in AOT mode (enables whole-program transformations)',
       defaultsTo: false)
-// TODO(alexmarkov): Cleanup uses in Flutter and remove these obsolete flags.
-  ..addFlag('strong', help: 'Obsolete', defaultsTo: true)
   ..addFlag('tfa',
       help:
           'Enable global type flow analysis and related transformations in AOT mode.',
@@ -133,7 +131,7 @@
   ..addFlag('track-widget-creation',
       help: 'Run a kernel transformer to track creation locations for widgets.',
       defaultsTo: false)
-  ..addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: null)
+  ..addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false)
   ..addMultiOption('bytecode-options',
       help: 'Specify options for bytecode generation:',
       valueHelp: 'opt1,opt2,...',
@@ -360,7 +358,27 @@
       return false;
     }
 
-    compilerOptions.bytecode = options['gen-bytecode'] ?? options['aot'];
+    if (options['aot']) {
+      if (!options['link-platform']) {
+        print('Error: --no-link-platform option cannot be used with --aot');
+        return false;
+      }
+      if (options['split-output-by-packages']) {
+        print(
+            'Error: --split-output-by-packages option cannot be used with --aot');
+        return false;
+      }
+      if (options['incremental']) {
+        print('Error: --incremental option cannot be used with --aot');
+        return false;
+      }
+      if (options['import-dill'] != null) {
+        print('Error: --import-dill option cannot be used with --aot');
+        return false;
+      }
+    }
+
+    compilerOptions.bytecode = options['gen-bytecode'];
     final BytecodeOptions bytecodeOptions = BytecodeOptions(
       enableAsserts: options['enable-asserts'],
       emitSourceFiles: options['embed-source-text'],
@@ -581,7 +599,10 @@
         final IOSink sink = file.openWrite();
         final BinaryPrinter printer = filterExternal
             ? LimitedBinaryPrinter(
-                sink, (lib) => !lib.isExternal, true /* excludeUriToSource */)
+                sink,
+                // ignore: DEPRECATED_MEMBER_USE
+                (lib) => !lib.isExternal,
+                true /* excludeUriToSource */)
             : printerFactory.newBinaryPrinter(sink);
 
         sortComponent(component);
@@ -594,7 +615,10 @@
       final IOSink sink = File(filename).openWrite();
       final BinaryPrinter printer = filterExternal
           ? LimitedBinaryPrinter(
-              sink, (lib) => !lib.isExternal, true /* excludeUriToSource */)
+              sink,
+              // ignore: DEPRECATED_MEMBER_USE
+              (lib) => !lib.isExternal,
+              true /* excludeUriToSource */)
           : printerFactory.newBinaryPrinter(sink);
 
       sortComponent(component);
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 63e5163..2ed86d3 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -57,6 +57,7 @@
     final manifest = <String, Map<String, List<int>>>{};
     final Set<Uri> visited = <Uri>{};
     for (Library library in _originalComponent.libraries) {
+      // ignore: DEPRECATED_MEMBER_USE
       if (library.isExternal || library.importUri.scheme == 'dart') {
         continue;
       }
diff --git a/pkg/frontend_server/lib/src/strong_components.dart b/pkg/frontend_server/lib/src/strong_components.dart
index 80cb7fa5..bf2cf8d6 100644
--- a/pkg/frontend_server/lib/src/strong_components.dart
+++ b/pkg/frontend_server/lib/src/strong_components.dart
@@ -157,6 +157,7 @@
   Iterable<Library> neighborsOf(Library vertex) {
     return <Library>[
       for (LibraryDependency dependency in vertex.dependencies)
+        // ignore: DEPRECATED_MEMBER_USE
         if (!dependency.targetLibrary.isExternal &&
             dependency.targetLibrary.importUri.scheme != 'dart')
           dependency.targetLibrary
diff --git a/pkg/frontend_server/test/frontend_server_flutter.dart b/pkg/frontend_server/test/frontend_server_flutter.dart
index ee88962..ad507fa 100644
--- a/pkg/frontend_server/test/frontend_server_flutter.dart
+++ b/pkg/frontend_server/test/frontend_server_flutter.dart
@@ -101,7 +101,6 @@
     '--sdk-root',
     flutterPlatformDirectory.path,
     '--incremental',
-    '--strong',
     '--target=flutter',
     '--packages',
     dotPackage.path,
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index b88dda9..26d94bd 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -862,6 +862,7 @@
         '--platform=${platformKernel.path}',
         '--output-dill=${dillFile.path}',
         '--unsafe-package-serialization',
+        '--no-incremental-serialization',
       ];
 
       final StreamController<List<int>> inputStreamController =
@@ -906,12 +907,13 @@
             Component component = loadComponentFromBinary(dillFile.path);
 
             // Contains (at least) the 2 files we want.
-            component.libraries
+            expect(
+                component.libraries
                     .where((l) =>
                         l.importUri.toString() == "package:pkgB/a.dart" ||
-                        l.fileUri.toString().contains(fileB.path))
-                    .length ==
-                2;
+                        l.fileUri == fileB.uri)
+                    .length,
+                2);
 
             // Verifiable (together with the platform file).
             component =
@@ -1015,12 +1017,13 @@
             Component component = loadComponentFromBinary(dillFile.path);
 
             // Contains (at least) the 2 files we want.
-            component.libraries
+            expect(
+                component.libraries
                     .where((l) =>
                         l.importUri.toString() == "package:pkgB/a.dart" ||
-                        l.fileUri.toString().contains(fileB.path))
-                    .length ==
-                2;
+                        l.fileUri == fileB.uri)
+                    .length,
+                2);
 
             // Verifiable (together with the platform file).
             component =
@@ -1032,6 +1035,120 @@
       inputStreamController.close();
     });
 
+    test('incremental-serialization with reject', () async {
+      // Basically a reproduction of
+      // https://github.com/flutter/flutter/issues/44384.
+      var file = new File('${tempDir.path}/pkgA/.packages')
+        ..createSync(recursive: true);
+      file.writeAsStringSync("pkgA:.");
+      file = new File('${tempDir.path}/pkgA/a.dart')
+        ..createSync(recursive: true);
+      file.writeAsStringSync("pkgA() {}");
+
+      var dillFile = new File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--incremental-serialization',
+      ];
+
+      final StreamController<List<int>> inputStreamController =
+          new StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          new StreamController<List<int>>();
+      final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = new StreamController<Result>();
+      final outputParser = new OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      Future<int> result =
+          starter(args, input: inputStreamController.stream, output: ioSink);
+      inputStreamController.add('compile ${file.path}\n'.codeUnits);
+      int count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            new CompilationResult.parse(compiledResult.status);
+        switch (count) {
+          case 0:
+            expect(dillFile.existsSync(), equals(true));
+            expect(result.filename, dillFile.path);
+            expect(result.errorsCount, 0);
+
+            // Loadable.
+            Component component = loadComponentFromBinary(dillFile.path);
+
+            // Contain the file we want.
+            var libs = component.libraries
+                .where((l) => l.importUri.toString() == "package:pkgA/a.dart");
+            expect(libs.length, 1);
+
+            // Has 1 procedure.
+            expect(libs.first.procedures.length, 1);
+
+            file.writeAsStringSync("pkgA() {} pkgA_2() {}");
+
+            count += 1;
+            inputStreamController.add('reject\n'.codeUnits);
+            inputStreamController.add('reset\n'.codeUnits);
+            inputStreamController.add('recompile ${file.path} abc\n'
+                    '${file.path}\n'
+                    'abc\n'
+                .codeUnits);
+            break;
+          case 1:
+            expect(dillFile.existsSync(), equals(true));
+            expect(result.filename, dillFile.path);
+            expect(result.errorsCount, 0);
+
+            // Loadable.
+            Component component = loadComponentFromBinary(dillFile.path);
+
+            // Contain the file we want.
+            var libs = component.libraries
+                .where((l) => l.importUri.toString() == "package:pkgA/a.dart");
+            expect(libs.length, 1);
+
+            // Has 2 procedure.
+            expect(libs.first.procedures.length, 2);
+
+            file.writeAsStringSync("pkgA() {} pkgA_2() {} pkgA_3() {}");
+
+            count += 1;
+            inputStreamController.add('accept\n'.codeUnits);
+            inputStreamController.add('reset\n'.codeUnits);
+            inputStreamController.add('recompile ${file.path} abc\n'
+                    '${file.path}\n'
+                    'abc\n'
+                .codeUnits);
+            break;
+          case 2:
+            expect(result.filename, dillFile.path);
+            expect(result.errorsCount, 0);
+            inputStreamController.add('quit\n'.codeUnits);
+
+            // Loadable.
+            Component component = loadComponentFromBinary(dillFile.path);
+
+            // Contain the file we want.
+            var libs = component.libraries
+                .where((l) => l.importUri.toString() == "package:pkgA/a.dart");
+            expect(libs.length, 1);
+
+            // Has 3 procedures.
+            expect(libs.first.procedures.length, 3);
+        }
+      });
+      expect(await result, 0);
+      inputStreamController.close();
+    });
+
     test('compile and recompile report non-zero error count', () async {
       var file = new File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("main() { foo(); bar(); }\n");
diff --git a/pkg/js/CHANGELOG.md b/pkg/js/CHANGELOG.md
index 800418a..821443e 100644
--- a/pkg/js/CHANGELOG.md
+++ b/pkg/js/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.3
+
+* Added promiseToFuture function.
+
 ## 0.6.2
 
 * Improved documentation.
diff --git a/pkg/js/pubspec.yaml b/pkg/js/pubspec.yaml
index a7a4e0a..d02009c 100644
--- a/pkg/js/pubspec.yaml
+++ b/pkg/js/pubspec.yaml
@@ -1,5 +1,5 @@
 name: js
-version: 0.6.2
+version: 0.6.3
 author: Dart Team <misc@dartlang.org>
 description: Access JavaScript from Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/js
diff --git a/pkg/kernel/bin/split.dart b/pkg/kernel/bin/split.dart
index fd7532c..d3abed4 100755
--- a/pkg/kernel/bin/split.dart
+++ b/pkg/kernel/bin/split.dart
@@ -28,26 +28,24 @@
   Component binary = CommandLineHelper.tryLoadDill(args[0]);
 
   int part = 1;
-  binary.libraries.forEach((lib) => lib.isExternal = true);
   for (int i = 0; i < binary.libraries.length; ++i) {
     Library lib = binary.libraries[i];
     if (lib.name?.startsWith("dart.") == true ||
         lib.name == "builtin" ||
         lib.name == "nativewrappers") continue;
-    lib.isExternal = false;
     String path = args[0] + ".part${part++}.dill";
-    await writeComponentToFile(binary, path);
+    await writeComponentToFile(binary, path, lib);
     print("Wrote $path");
-    lib.isExternal = true;
   }
 }
 
-Future<Null> writeComponentToFile(Component component, String path) async {
+Future<Null> writeComponentToFile(
+    Component component, String path, Library wantedLibrary) async {
   File output = new File(path);
   IOSink sink = output.openWrite();
   try {
     BinaryPrinter printer =
-        new LimitedBinaryPrinter(sink, (lib) => !lib.isExternal, false);
+        new LimitedBinaryPrinter(sink, (lib) => lib == wantedLibrary, false);
     printer.writeComponentFile(component);
   } finally {
     await sink.close();
diff --git a/pkg/kernel/doc/nnbd_api.md b/pkg/kernel/doc/nnbd_api.md
index 3b5757e..a0b3781 100644
--- a/pkg/kernel/doc/nnbd_api.md
+++ b/pkg/kernel/doc/nnbd_api.md
@@ -8,6 +8,9 @@
 
 ## CHANGELOG
 
+2019.11.06:
+- Described required nullability parameter.
+
 2019.10.18:
 - Added information about `NeverType`.
 
@@ -16,8 +19,6 @@
 
 2019.10.15:
 - Added information about implementing the subtype relation.
-
-2019.10.15:
 - Added description of `DartType.withNullability`.
 
 2019.09.26:
@@ -290,7 +291,7 @@
 #### Nullability attribute on types
 
 - `DartType.nullability` is added to `DartType` and the implementations are added to the subclasses (fields for InterfaceType, FunctionType, TypedefType, and TypeParameterType, concrete getter for `TypeParameterType`).
-- Nullability parameter is added to constructors of InterfaceType, FunctionType, TypedefType, and TypeParameterType.
+- The required nullability parameter is added to constructors of InterfaceType, FunctionType, TypedefType, and TypeParameterType.  All of the call sites were modified so that `Nullability.legacy` is passed for the parameter.
 - `TypeParameterType.typeParameterTypeNullability` is added.  For details see section **Nullability of Intersection Types** of this document.
 - `TypeParameterType.computeNullabilityFromBound` is added.
 - `DartType.withNullability` method is added to `DartType` and is implemented in its subclasses.  The method takes a single parameter, the desired nullability, and returns the type that is the receiver with the given nullability.  If the receiver already has the nullability that is passed in as the parameter, the receiver object itself is returned, and a copy isn't created.  If the types that are represented by a particular `DartType` subclass always have a certain nullability, like `dynamic` or `void`, invocations of `withNullability` on them always return the receiver.
@@ -344,7 +345,7 @@
 
 #### Avoiding explicit legacy
 
-As described in section **Changes in caching of raw types**, all previously existing invocations of `Class.rawType` and of the related getters of `TypeEnvironment` were replaced with invocations of nullability-aware members of `CoreTypes`.  To keep the observable behavior of the client code, legacy types were used wherever before a raw type was used.  For example, `intClass.rawType` was replaced with `coreTypes.intLegacyRawType` and `cls.rawType` was replaced with `coreTypes.legacyRawType(cls)`.  All of those call sites should be updated as a part of the NNBD feature implementation because they are the source of legacy types regardless of the opted-in status of the library they are generated for.  Section **Library status and library-specific nullability treatment** describes the changes in the CFE public interface that are supposed to help with the process.
+As described in section **Nullability attribute on types**, all previously existing invocations of the constructors of `InterfaceType`, `TypedefType`, `TypeParameterType`, and `FunctionType` were given additional argument that specifies the nullability of the created type; `Nullability.legacy` was used in the cases that weren't migrated to the NNBD semantics yet.  Additionally, as described in section **Changes in caching of raw types**, all previously existing invocations of `Class.rawType` and of the related getters of `TypeEnvironment` were replaced with invocations of nullability-aware members of `CoreTypes`.  To keep the observable behavior of the client code, legacy types were used wherever before a raw type was used.  For example, `intClass.rawType` was replaced with `coreTypes.intLegacyRawType` and `cls.rawType` was replaced with `coreTypes.legacyRawType(cls)`.  All of those call sites should be updated as a part of the NNBD feature implementation because they are the source of legacy types regardless of the opted-in status of the library they are generated for.  Section **Library status and library-specific nullability treatment** describes the changes in the CFE public interface that are supposed to help with the process.
 
 The easiest way to avoid using explicitly legacy types is to do the following:
 
@@ -356,13 +357,13 @@
 - Replace `coreTypes.intLegacyRawType` with `coreTypes.intRawType(library.nonNullable)`.  Similarly for other built-in types.
 - Replace `coreTypes.legacyRawType(cls)` with `coreTypes.rawType(cls, library.nonNullable)`.
 - Replace `coreTypes.rawType(cls, Nullability.legacy)` with `coreTypes.rawType(cls, library.nonNullable)`.
-- Replace `new InterfaceType(cls, typeArgs)` with `new InterfaceType(cls, typeArgs, library.nonNullable)`.
-- Replace `new InterfaceType(cls)` with `new InterfaceType(cls, const <DartType>[], library.nonNullable)`.
-- Replace `new InterfaceType.byReference(clsRef, typeArgs)` with `new InterfaceType.byReference(clsRef, typeArgs, library.nonNullable)`.
-- Replace `new FunctionType(positional, retType, <NAMED>)` with `new FunctionType(positional, retType, nullability: library.nonNullable, <NAMED>)` where `<NAMED>` are the named arguments passed in.
-- Replace `new TypedefType(tdef, typeArgs)` with `new TypedefType(tdef, typeArgs, library.nonNullable)`.
-- Replace `new TypedefType(tdef)` with `new TypedefType(tdef, const <DartType>[], library.nonNullable)`.
-- Replace `new TypedefType.byReference(tdefRef, typeArgs)` with `new TypedefType.byReference(tdefRef, typeArgs, library.nonNullable)`.
+- Replace `new InterfaceType(cls, Nullability.legacy, typeArgs)` with `new InterfaceType(cls, library.nonNullable, typeArgs)`.
+- Replace `new InterfaceType(cls, Nullability.legacy)` with `new InterfaceType(cls, library.nonNullable)`.
+- Replace `new InterfaceType.byReference(clsRef, Nullability.legacy, typeArgs)` with `new InterfaceType.byReference(clsRef, library.nonNullable, typeArgs)`.
+- Replace `new FunctionType(positional, retType, Nullability.legacy, <NAMED>)` with `new FunctionType(positional, retType, library.nonNullable, <NAMED>)` where `<NAMED>` are the named arguments passed in.
+- Replace `new TypedefType(tdef, Nullability.legacy, typeArgs)` with `new TypedefType(tdef, library.nonNullable, typeArgs)`.
+- Replace `new TypedefType(tdef, Nullability.legacy)` with `new TypedefType(tdef, library.nonNullable)`.
+- Replace `new TypedefType.byReference(tdefRef, Nullability.legacy, typeArgs)` with `new TypedefType.byReference(tdefRef, library.nonNullable, typeArgs)`.
 
 The code updated this way will generate nullable and non-nullable types as desired for the opted-in libraries and will generate legacy types for the opted-out libraries.  It should also be easy to deprecate the weak-NNBD mode for such code: `Library.nonNullable` and `Library.nullable` will start returning the corresponding nullability constants.
 
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 0b5196d..8f97938 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -349,7 +349,10 @@
   ///
   /// If the library is non-external, then its classes are at [ClassLevel.Body]
   /// and all members are loaded.
+  @Deprecated("Library.isExternal is going away.")
   bool get isExternal => (flags & ExternalFlag) != 0;
+
+  @Deprecated("Library.isExternal is going away.")
   void set isExternal(bool value) {
     flags = value ? (flags | ExternalFlag) : (flags & ~ExternalFlag);
   }
@@ -416,6 +419,7 @@
         this.procedures = procedures ?? <Procedure>[],
         this.fields = fields ?? <Field>[],
         super(reference) {
+    // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
     this.isExternal = isExternal;
     setParents(this.dependencies, this);
     setParents(this.parts, this);
@@ -727,7 +731,8 @@
   Library get enclosingLibrary => parent;
 
   TypedefType get thisType {
-    return new TypedefType(this, _getAsTypeArguments(typeParameters));
+    return new TypedefType(
+        this, Nullability.legacy, _getAsTypeArguments(typeParameters));
   }
 
   R accept<R>(TreeVisitor<R> v) {
@@ -1215,13 +1220,6 @@
   R accept<R>(TreeVisitor<R> v) => v.visitClass(this);
   R acceptReference<R>(Visitor<R> v) => v.visitClassReference(this);
 
-  /// If true, the class is part of an external library, that is, it is defined
-  /// in another build unit.  Only a subset of its members are present.
-  ///
-  /// These classes should be loaded at either [ClassLevel.Type] or
-  /// [ClassLevel.Hierarchy] level.
-  bool get isInExternalLibrary => enclosingLibrary.isExternal;
-
   Supertype get asRawSupertype {
     return new Supertype(this,
         new List<DartType>.filled(typeParameters.length, const DynamicType()));
@@ -1233,13 +1231,13 @@
 
   InterfaceType _thisType;
   InterfaceType get thisType {
-    return _thisType ??=
-        new InterfaceType(this, _getAsTypeArguments(typeParameters));
+    return _thisType ??= new InterfaceType(
+        this, Nullability.legacy, _getAsTypeArguments(typeParameters));
   }
 
   InterfaceType _bottomType;
   InterfaceType get bottomType {
-    return _bottomType ??= new InterfaceType(this,
+    return _bottomType ??= new InterfaceType(this, Nullability.legacy,
         new List<DartType>.filled(typeParameters.length, const BottomType()));
   }
 
@@ -1453,11 +1451,6 @@
   R accept<R>(MemberVisitor<R> v);
   acceptReference(MemberReferenceVisitor v);
 
-  /// If true, the member is part of an external library, that is, it is defined
-  /// in another build unit.  Such members have no body or initializer present
-  /// in the IR.
-  bool get isInExternalLibrary => enclosingLibrary.isExternal;
-
   /// Returns true if this is an abstract procedure.
   bool get isAbstract => false;
 
@@ -2484,6 +2477,7 @@
     return new FunctionType(
         positionalParameters.map(_getTypeOfVariable).toList(growable: false),
         returnType,
+        Nullability.legacy,
         namedParameters: named,
         typeParameters: typeParametersCopy,
         requiredParameterCount: requiredParameterCount);
@@ -3140,7 +3134,7 @@
             .map((p) => new NamedExpression(p.name, new VariableGet(p)))
             .toList(),
         types: function.typeParameters
-            .map((p) => new TypeParameterType(p))
+            .map((p) => new TypeParameterType(p, Nullability.legacy))
             .toList());
   }
 
@@ -3417,7 +3411,7 @@
     return arguments.types.isEmpty
         ? types.coreTypes.legacyRawType(target.enclosingClass)
         : new InterfaceType(
-            target.enclosingClass, arguments.types, Nullability.legacy);
+            target.enclosingClass, Nullability.legacy, arguments.types);
   }
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitConstructorInvocation(this);
@@ -3443,9 +3437,9 @@
     // empty.
     return arguments.types.isEmpty
         ? new InterfaceType(
-            enclosingClass, const <DartType>[], Nullability.legacy)
+            enclosingClass, Nullability.legacy, const <DartType>[])
         : new InterfaceType(
-            enclosingClass, arguments.types, Nullability.legacy);
+            enclosingClass, Nullability.legacy, arguments.types);
   }
 }
 
@@ -3751,14 +3745,18 @@
   final List<Expression> unusedArguments;
 
   InstanceCreation(this.classReference, this.typeArguments, this.fieldValues,
-      this.asserts, this.unusedArguments);
+      this.asserts, this.unusedArguments) {
+    setParents(fieldValues.values.toList(), this);
+    setParents(asserts, this);
+    setParents(unusedArguments, this);
+  }
 
   Class get classNode => classReference.asClass;
 
   DartType getStaticType(TypeEnvironment types) {
     return typeArguments.isEmpty
         ? types.coreTypes.legacyRawType(classNode)
-        : new InterfaceType(classNode, typeArguments);
+        : new InterfaceType(classNode, Nullability.legacy, typeArguments);
   }
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceCreation(this);
@@ -4520,7 +4518,15 @@
 class AssertStatement extends Statement {
   Expression condition;
   Expression message; // May be null.
+
+  /// Character offset in the source where the assertion condition begins.
+  ///
+  /// Note: This is not the offset into the UTF8 encoded `List<int>` source.
   int conditionStartOffset;
+
+  /// Character offset in the source where the assertion condition ends.
+  ///
+  /// Note: This is not the offset into the UTF8 encoded `List<int>` source.
   int conditionEndOffset;
 
   AssertStatement(this.condition,
@@ -5556,14 +5562,13 @@
 
   /// The [typeArguments] list must not be modified after this call. If the
   /// list is omitted, 'dynamic' type arguments are filled in.
-  InterfaceType(Class classNode,
-      [List<DartType> typeArguments,
-      Nullability nullability = Nullability.legacy])
-      : this.byReference(getClassReference(classNode),
-            typeArguments ?? _defaultTypeArguments(classNode), nullability);
+  InterfaceType(Class classNode, Nullability nullability,
+      [List<DartType> typeArguments])
+      : this.byReference(getClassReference(classNode), nullability,
+            typeArguments ?? _defaultTypeArguments(classNode));
 
-  InterfaceType.byReference(this.className, this.typeArguments,
-      [this.nullability = Nullability.legacy]);
+  InterfaceType.byReference(
+      this.className, this.nullability, this.typeArguments);
 
   Class get classNode => className.asClass;
 
@@ -5614,7 +5619,7 @@
   InterfaceType withNullability(Nullability nullability) {
     return nullability == this.nullability
         ? this
-        : new InterfaceType.byReference(className, typeArguments, nullability);
+        : new InterfaceType.byReference(className, nullability, typeArguments);
   }
 }
 
@@ -5632,10 +5637,10 @@
   final DartType returnType;
   int _hashCode;
 
-  FunctionType(List<DartType> positionalParameters, this.returnType,
+  FunctionType(
+      List<DartType> positionalParameters, this.returnType, this.nullability,
       {this.namedParameters: const <NamedType>[],
       this.typeParameters: const <TypeParameter>[],
-      this.nullability: Nullability.legacy,
       int requiredParameterCount,
       this.typedefType})
       : this.positionalParameters = positionalParameters,
@@ -5698,7 +5703,8 @@
   /// type.
   FunctionType get withoutTypeParameters {
     if (typeParameters.isEmpty) return this;
-    return new FunctionType(positionalParameters, returnType,
+    return new FunctionType(
+        positionalParameters, returnType, Nullability.legacy,
         requiredParameterCount: requiredParameterCount,
         namedParameters: namedParameters,
         typedefType: null);
@@ -5752,10 +5758,10 @@
 
   FunctionType withNullability(Nullability nullability) {
     if (nullability == this.nullability) return this;
-    FunctionType result = FunctionType(positionalParameters, returnType,
+    FunctionType result = FunctionType(
+        positionalParameters, returnType, nullability,
         namedParameters: namedParameters,
         typeParameters: typeParameters,
-        nullability: nullability,
         requiredParameterCount: requiredParameterCount,
         typedefType: typedefType?.withNullability(nullability));
     if (typeParameters.isEmpty) return result;
@@ -5771,14 +5777,13 @@
   final Reference typedefReference;
   final List<DartType> typeArguments;
 
-  TypedefType(Typedef typedefNode,
-      [List<DartType> typeArguments,
-      Nullability nullability = Nullability.legacy])
-      : this.byReference(typedefNode.reference,
-            typeArguments ?? const <DartType>[], nullability);
+  TypedefType(Typedef typedefNode, Nullability nullability,
+      [List<DartType> typeArguments])
+      : this.byReference(typedefNode.reference, nullability,
+            typeArguments ?? const <DartType>[]);
 
-  TypedefType.byReference(this.typedefReference, this.typeArguments,
-      [this.nullability = Nullability.legacy]);
+  TypedefType.byReference(
+      this.typedefReference, this.nullability, this.typeArguments);
 
   Typedef get typedefNode => typedefReference.asTypedef;
 
@@ -5832,7 +5837,7 @@
     return nullability == this.nullability
         ? this
         : new TypedefType.byReference(
-            typedefReference, typeArguments, nullability);
+            typedefReference, nullability, typeArguments);
   }
 }
 
@@ -5904,9 +5909,8 @@
   /// is therefore the same as the bound of [parameter].
   DartType promotedBound;
 
-  TypeParameterType(this.parameter,
-      [this.promotedBound,
-      this.typeParameterTypeNullability = Nullability.legacy]);
+  TypeParameterType(this.parameter, this.typeParameterTypeNullability,
+      [this.promotedBound]);
 
   R accept<R>(DartTypeVisitor<R> v) => v.visitTypeParameterType(this);
   R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) =>
@@ -5917,13 +5921,15 @@
   bool operator ==(Object other) {
     return other is TypeParameterType &&
         parameter == other.parameter &&
-        nullability == other.nullability;
+        nullability == other.nullability &&
+        promotedBound == other.promotedBound;
   }
 
   int get hashCode {
     int hash = _temporaryHashCodeTable[parameter] ?? parameter.hashCode;
     int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
     hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
+    hash = 0x3fffffff & (hash * 31 + (hash ^ promotedBound.hashCode));
     return hash;
   }
 
@@ -5965,7 +5971,7 @@
     return typeParameterTypeNullability == this.typeParameterTypeNullability
         ? this
         : new TypeParameterType(
-            parameter, promotedBound, typeParameterTypeNullability);
+            parameter, typeParameterTypeNullability, promotedBound);
   }
 
   /// Gets the nullability of a type-parameter type based on the bound.
@@ -6297,7 +6303,7 @@
   }
 
   InterfaceType get asInterfaceType {
-    return new InterfaceType(classNode, typeArguments);
+    return new InterfaceType(classNode, Nullability.legacy, typeArguments);
   }
 
   bool operator ==(Object other) {
@@ -6631,7 +6637,7 @@
   }
 
   DartType getType(TypeEnvironment types) =>
-      new InterfaceType(classNode, typeArguments);
+      new InterfaceType(classNode, Nullability.legacy, typeArguments);
 }
 
 class PartialInstantiationConstant extends Constant {
@@ -7029,8 +7035,8 @@
 
 List<DartType> _getAsTypeArguments(List<TypeParameter> typeParameters) {
   if (typeParameters.isEmpty) return const <DartType>[];
-  return new List<DartType>.generate(
-      typeParameters.length, (i) => new TypeParameterType(typeParameters[i]),
+  return new List<DartType>.generate(typeParameters.length,
+      (i) => new TypeParameterType(typeParameters[i], Nullability.legacy),
       growable: false);
 }
 
@@ -7053,6 +7059,7 @@
 class Source {
   final List<int> lineStarts;
 
+  /// A UTF8 encoding of the original source file.
   final List<int> source;
 
   final Uri importUri;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 11695a2..2178093 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -2101,6 +2101,11 @@
 
   Supertype readSupertype() {
     InterfaceType type = readDartType();
+    assert(
+        type.nullability == _currentLibrary.nonNullable,
+        "In serialized form supertypes should have Nullability.legacy if they "
+        "are in a library that is opted out of the NNBD feature.  If they are "
+        "in an opted-in library, they should have Nullability.nonNullable.");
     return new Supertype.byReference(type.className, type.typeArguments);
   }
 
@@ -2156,7 +2161,7 @@
       case Tag.TypedefType:
         int nullabilityIndex = readByte();
         return new TypedefType.byReference(readTypedefReference(),
-            readDartTypeList(), Nullability.values[nullabilityIndex]);
+            Nullability.values[nullabilityIndex], readDartTypeList());
       case Tag.BottomType:
         return const BottomType();
       case Tag.InvalidType:
@@ -2171,11 +2176,11 @@
       case Tag.InterfaceType:
         int nullabilityIndex = readByte();
         return new InterfaceType.byReference(readClassReference(),
-            readDartTypeList(), Nullability.values[nullabilityIndex]);
+            Nullability.values[nullabilityIndex], readDartTypeList());
       case Tag.SimpleInterfaceType:
         int nullabilityIndex = readByte();
         return new InterfaceType.byReference(readClassReference(),
-            const <DartType>[], Nullability.values[nullabilityIndex]);
+            Nullability.values[nullabilityIndex], const <DartType>[]);
       case Tag.FunctionType:
         int typeParameterStackHeight = typeParameterStack.length;
         int nullabilityIndex = readByte();
@@ -2188,24 +2193,24 @@
         assert(positional.length + named.length == totalParameterCount);
         var returnType = readDartType();
         typeParameterStack.length = typeParameterStackHeight;
-        return new FunctionType(positional, returnType,
+        return new FunctionType(
+            positional, returnType, Nullability.values[nullabilityIndex],
             typeParameters: typeParameters,
             requiredParameterCount: requiredParameterCount,
             namedParameters: named,
-            typedefType: typedefType,
-            nullability: Nullability.values[nullabilityIndex]);
+            typedefType: typedefType);
       case Tag.SimpleFunctionType:
         int nullabilityIndex = readByte();
         var positional = readDartTypeList();
         var returnType = readDartType();
-        return new FunctionType(positional, returnType,
-            nullability: Nullability.values[nullabilityIndex]);
+        return new FunctionType(
+            positional, returnType, Nullability.values[nullabilityIndex]);
       case Tag.TypeParameterType:
         int declaredNullabilityIndex = readByte();
         int index = readUInt();
         var bound = readDartTypeOption();
-        return new TypeParameterType(typeParameterStack[index], bound,
-            Nullability.values[declaredNullabilityIndex]);
+        return new TypeParameterType(typeParameterStack[index],
+            Nullability.values[declaredNullabilityIndex], bound);
       default:
         throw fail('unexpected dart type tag: $tag');
     }
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index da2fd24..141f142 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -54,6 +54,8 @@
   Set<CanonicalName> _knownCanonicalNameNonRootTops = new Set<CanonicalName>();
   Set<CanonicalName> _reindexedCanonicalNames = new Set<CanonicalName>();
 
+  Library _currentLibrary;
+
   /// Create a printer that writes to the given [sink].
   ///
   /// The BinaryPrinter will use its own buffer, so the [sink] does not need
@@ -930,6 +932,9 @@
 
   @override
   void visitLibrary(Library node) {
+    _currentLibrary = node;
+
+    // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
     insideExternalLibrary = node.isExternal;
     libraryOffsets.add(getBufferOffset());
     writeByte(node.flags);
@@ -991,6 +996,8 @@
       writeUInt32(offset);
     }
     writeUInt32(procedureOffsets.length - 1);
+
+    _currentLibrary = null;
   }
 
   void writeLibraryDependencies(Library library) {
@@ -2067,11 +2074,11 @@
     // requires the nullability byte.
     if (node.typeArguments.isEmpty) {
       writeByte(Tag.SimpleInterfaceType);
-      writeByte(Nullability.nonNullable.index);
+      writeByte(_currentLibrary.nonNullable.index);
       writeNonNullReference(node.className);
     } else {
       writeByte(Tag.InterfaceType);
-      writeByte(Nullability.nonNullable.index);
+      writeByte(_currentLibrary.nonNullable.index);
       writeNonNullReference(node.className);
       writeNodeList(node.typeArguments);
     }
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 1f846ce..dc958c9 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -521,7 +521,8 @@
       if (newNode == null) {
         newNode = new TypeParameter(node.name);
         typeParams[node] = newNode;
-        typeSubstitution[node] = new TypeParameterType(newNode);
+        typeSubstitution[node] =
+            new TypeParameterType(newNode, Nullability.legacy);
       }
     }
   }
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index d18d3aa..7524a6d 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -465,19 +465,19 @@
 
   InterfaceType get objectLegacyRawType {
     return _objectLegacyRawType ??= _legacyRawTypes[objectClass] ??=
-        new InterfaceType(objectClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(objectClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get objectNullableRawType {
     return _objectNullableRawType ??= _nullableRawTypes[objectClass] ??=
         new InterfaceType(
-            objectClass, const <DartType>[], Nullability.nullable);
+            objectClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get objectNonNullableRawType {
     return _objectNonNullableRawType ??= _nonNullableRawTypes[objectClass] ??=
         new InterfaceType(
-            objectClass, const <DartType>[], Nullability.nonNullable);
+            objectClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType objectRawType(Nullability nullability) {
@@ -498,23 +498,23 @@
   /// Null is always nullable, so there's only one raw type for that class.
   InterfaceType get nullType {
     return _nullType ??= _nullableRawTypes[nullClass] ??=
-        new InterfaceType(nullClass, const <DartType>[], Nullability.nullable);
+        new InterfaceType(nullClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get boolLegacyRawType {
     return _boolLegacyRawType ??= _legacyRawTypes[boolClass] ??=
-        new InterfaceType(boolClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(boolClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get boolNullableRawType {
     return _boolNullableRawType ??= _nullableRawTypes[boolClass] ??=
-        new InterfaceType(boolClass, const <DartType>[], Nullability.nullable);
+        new InterfaceType(boolClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get boolNonNullableRawType {
     return _boolNonNullableRawType ??= _nonNullableRawTypes[boolClass] ??=
         new InterfaceType(
-            boolClass, const <DartType>[], Nullability.nonNullable);
+            boolClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType boolRawType(Nullability nullability) {
@@ -534,18 +534,18 @@
 
   InterfaceType get intLegacyRawType {
     return _intLegacyRawType ??= _legacyRawTypes[intClass] ??=
-        new InterfaceType(intClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(intClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get intNullableRawType {
     return _intNullableRawType ??= _nullableRawTypes[intClass] ??=
-        new InterfaceType(intClass, const <DartType>[], Nullability.nullable);
+        new InterfaceType(intClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get intNonNullableRawType {
     return _intNonNullableRawType ??= _nonNullableRawTypes[intClass] ??=
         new InterfaceType(
-            intClass, const <DartType>[], Nullability.nonNullable);
+            intClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType intRawType(Nullability nullability) {
@@ -565,18 +565,18 @@
 
   InterfaceType get numLegacyRawType {
     return _numLegacyRawType ??= _legacyRawTypes[numClass] ??=
-        new InterfaceType(numClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(numClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get numNullableRawType {
     return _numNullableRawType ??= _nullableRawTypes[numClass] ??=
-        new InterfaceType(numClass, const <DartType>[], Nullability.nullable);
+        new InterfaceType(numClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get numNonNullableRawType {
     return _numNonNullableRawType ??= _nonNullableRawTypes[numClass] ??=
         new InterfaceType(
-            numClass, const <DartType>[], Nullability.nonNullable);
+            numClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType numRawType(Nullability nullability) {
@@ -596,19 +596,19 @@
 
   InterfaceType get doubleLegacyRawType {
     return _doubleLegacyRawType ??= _legacyRawTypes[doubleClass] ??=
-        new InterfaceType(doubleClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(doubleClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get doubleNullableRawType {
     return _doubleNullableRawType ??= _nullableRawTypes[doubleClass] ??=
         new InterfaceType(
-            doubleClass, const <DartType>[], Nullability.nullable);
+            doubleClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get doubleNonNullableRawType {
     return _doubleNonNullableRawType ??= _nonNullableRawTypes[doubleClass] ??=
         new InterfaceType(
-            doubleClass, const <DartType>[], Nullability.nonNullable);
+            doubleClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType doubleRawType(Nullability nullability) {
@@ -628,19 +628,19 @@
 
   InterfaceType get stringLegacyRawType {
     return _stringLegacyRawType ??= _legacyRawTypes[stringClass] ??=
-        new InterfaceType(stringClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(stringClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get stringNullableRawType {
     return _stringNullableRawType ??= _nullableRawTypes[stringClass] ??=
         new InterfaceType(
-            stringClass, const <DartType>[], Nullability.nullable);
+            stringClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get stringNonNullableRawType {
     return _stringNonNullableRawType ??= _nonNullableRawTypes[stringClass] ??=
         new InterfaceType(
-            stringClass, const <DartType>[], Nullability.nonNullable);
+            stringClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType stringRawType(Nullability nullability) {
@@ -660,20 +660,20 @@
 
   InterfaceType get listLegacyRawType {
     return _listLegacyRawType ??= _legacyRawTypes[listClass] ??=
-        new InterfaceType(listClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(listClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get listNullableRawType {
     return _listNullableRawType ??= _nullableRawTypes[listClass] ??=
-        new InterfaceType(listClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(listClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get listNonNullableRawType {
     return _listNonNullableRawType ??= _nonNullableRawTypes[listClass] ??=
-        new InterfaceType(listClass, const <DartType>[const DynamicType()],
-            Nullability.nonNullable);
+        new InterfaceType(listClass, Nullability.nonNullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType listRawType(Nullability nullability) {
@@ -693,20 +693,20 @@
 
   InterfaceType get setLegacyRawType {
     return _setLegacyRawType ??= _legacyRawTypes[setClass] ??=
-        new InterfaceType(setClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(setClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get setNullableRawType {
     return _setNullableRawType ??= _nullableRawTypes[setClass] ??=
-        new InterfaceType(setClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(setClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get setNonNullableRawType {
     return _setNonNullableRawType ??= _nonNullableRawTypes[setClass] ??=
-        new InterfaceType(setClass, const <DartType>[const DynamicType()],
-            Nullability.nonNullable);
+        new InterfaceType(setClass, Nullability.nonNullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType setRawType(Nullability nullability) {
@@ -726,26 +726,20 @@
 
   InterfaceType get mapLegacyRawType {
     return _mapLegacyRawType ??= _legacyRawTypes[mapClass] ??=
-        new InterfaceType(
-            mapClass,
-            const <DartType>[const DynamicType(), const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(mapClass, Nullability.legacy,
+            const <DartType>[const DynamicType(), const DynamicType()]);
   }
 
   InterfaceType get mapNullableRawType {
     return _mapNullableRawType ??= _nullableRawTypes[mapClass] ??=
-        new InterfaceType(
-            mapClass,
-            const <DartType>[const DynamicType(), const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(mapClass, Nullability.nullable,
+            const <DartType>[const DynamicType(), const DynamicType()]);
   }
 
   InterfaceType get mapNonNullableRawType {
     return _mapNonNullableRawType ??= _nonNullableRawTypes[mapClass] ??=
-        new InterfaceType(
-            mapClass,
-            const <DartType>[const DynamicType(), const DynamicType()],
-            Nullability.nonNullable);
+        new InterfaceType(mapClass, Nullability.nonNullable,
+            const <DartType>[const DynamicType(), const DynamicType()]);
   }
 
   InterfaceType mapRawType(Nullability nullability) {
@@ -765,20 +759,20 @@
 
   InterfaceType get iterableLegacyRawType {
     return _iterableLegacyRawType ??= _legacyRawTypes[iterableClass] ??=
-        new InterfaceType(iterableClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(iterableClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get iterableNullableRawType {
     return _iterableNullableRawType ??= _nullableRawTypes[iterableClass] ??=
-        new InterfaceType(iterableClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(iterableClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get iterableNonNullableRawType {
     return _iterableNonNullableRawType ??=
         _nonNullableRawTypes[iterableClass] ??= new InterfaceType(iterableClass,
-            const <DartType>[const DynamicType()], Nullability.nonNullable);
+            Nullability.nonNullable, const <DartType>[const DynamicType()]);
   }
 
   InterfaceType iterableRawType(Nullability nullability) {
@@ -798,20 +792,20 @@
 
   InterfaceType get iteratorLegacyRawType {
     return _iteratorLegacyRawType ??= _legacyRawTypes[iteratorClass] ??=
-        new InterfaceType(iteratorClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(iteratorClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get iteratorNullableRawType {
     return _iteratorNullableRawType ??= _nullableRawTypes[iteratorClass] ??=
-        new InterfaceType(iteratorClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(iteratorClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get iteratorNonNullableRawType {
     return _iteratorNonNullableRawType ??=
         _nonNullableRawTypes[iteratorClass] ??= new InterfaceType(iteratorClass,
-            const <DartType>[const DynamicType()], Nullability.nonNullable);
+            Nullability.nonNullable, const <DartType>[const DynamicType()]);
   }
 
   InterfaceType iteratorRawType(Nullability nullability) {
@@ -831,19 +825,19 @@
 
   InterfaceType get symbolLegacyRawType {
     return _symbolLegacyRawType ??= _legacyRawTypes[symbolClass] ??=
-        new InterfaceType(symbolClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(symbolClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get symbolNullableRawType {
     return _symbolNullableRawType ??= _nullableRawTypes[symbolClass] ??=
         new InterfaceType(
-            symbolClass, const <DartType>[], Nullability.nullable);
+            symbolClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get symbolNonNullableRawType {
     return _symbolNonNullableRawType ??= _nonNullableRawTypes[symbolClass] ??=
         new InterfaceType(
-            symbolClass, const <DartType>[], Nullability.nonNullable);
+            symbolClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType symbolRawType(Nullability nullability) {
@@ -863,18 +857,18 @@
 
   InterfaceType get typeLegacyRawType {
     return _typeLegacyRawType ??= _legacyRawTypes[typeClass] ??=
-        new InterfaceType(typeClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(typeClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get typeNullableRawType {
     return _typeNullableRawType ??= _nullableRawTypes[typeClass] ??=
-        new InterfaceType(typeClass, const <DartType>[], Nullability.nullable);
+        new InterfaceType(typeClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get typeNonNullableRawType {
     return _typeNonNullableRawType ??= _nonNullableRawTypes[typeClass] ??=
         new InterfaceType(
-            typeClass, const <DartType>[], Nullability.nonNullable);
+            typeClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType typeRawType(Nullability nullability) {
@@ -895,19 +889,19 @@
   InterfaceType get functionLegacyRawType {
     return _functionLegacyRawType ??= _legacyRawTypes[functionClass] ??=
         new InterfaceType(
-            functionClass, const <DartType>[], Nullability.legacy);
+            functionClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get functionNullableRawType {
     return _functionNullableRawType ??= _nullableRawTypes[functionClass] ??=
         new InterfaceType(
-            functionClass, const <DartType>[], Nullability.nullable);
+            functionClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get functionNonNullableRawType {
     return _functionNonNullableRawType ??=
         _nonNullableRawTypes[functionClass] ??= new InterfaceType(
-            functionClass, const <DartType>[], Nullability.nonNullable);
+            functionClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType functionRawType(Nullability nullability) {
@@ -928,19 +922,19 @@
   InterfaceType get invocationLegacyRawType {
     return _invocationLegacyRawType ??= _legacyRawTypes[invocationClass] ??=
         new InterfaceType(
-            invocationClass, const <DartType>[], Nullability.legacy);
+            invocationClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get invocationNullableRawType {
     return _invocationNullableRawType ??= _nullableRawTypes[invocationClass] ??=
         new InterfaceType(
-            invocationClass, const <DartType>[], Nullability.nullable);
+            invocationClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get invocationNonNullableRawType {
     return _invocationNonNullableRawType ??=
         _nonNullableRawTypes[invocationClass] ??= new InterfaceType(
-            invocationClass, const <DartType>[], Nullability.nonNullable);
+            invocationClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType invocationRawType(Nullability nullability) {
@@ -961,19 +955,19 @@
   InterfaceType get invocationMirrorLegacyRawType {
     return _invocationMirrorLegacyRawType ??=
         _legacyRawTypes[invocationMirrorClass] ??= new InterfaceType(
-            invocationMirrorClass, const <DartType>[], Nullability.legacy);
+            invocationMirrorClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get invocationMirrorNullableRawType {
     return _invocationMirrorNullableRawType ??=
         _nullableRawTypes[invocationMirrorClass] ??= new InterfaceType(
-            invocationMirrorClass, const <DartType>[], Nullability.nullable);
+            invocationMirrorClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get invocationMirrorNonNullableRawType {
     return _invocationMirrorNonNullableRawType ??=
         _nonNullableRawTypes[invocationMirrorClass] ??= new InterfaceType(
-            invocationMirrorClass, const <DartType>[], Nullability.nonNullable);
+            invocationMirrorClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType invocationMirrorRawType(Nullability nullability) {
@@ -993,20 +987,20 @@
 
   InterfaceType get futureLegacyRawType {
     return _futureLegacyRawType ??= _legacyRawTypes[futureClass] ??=
-        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(futureClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get futureNullableRawType {
     return _futureNullableRawType ??= _nullableRawTypes[futureClass] ??=
-        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(futureClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get futureNonNullableRawType {
     return _futureNonNullableRawType ??= _nonNullableRawTypes[futureClass] ??=
-        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
-            Nullability.nonNullable);
+        new InterfaceType(futureClass, Nullability.nonNullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType futureRawType(Nullability nullability) {
@@ -1027,19 +1021,19 @@
   InterfaceType get stackTraceLegacyRawType {
     return _stackTraceLegacyRawType ??= _legacyRawTypes[stackTraceClass] ??=
         new InterfaceType(
-            stackTraceClass, const <DartType>[], Nullability.legacy);
+            stackTraceClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get stackTraceNullableRawType {
     return _stackTraceNullableRawType ??= _nullableRawTypes[stackTraceClass] ??=
         new InterfaceType(
-            stackTraceClass, const <DartType>[], Nullability.nullable);
+            stackTraceClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get stackTraceNonNullableRawType {
     return _stackTraceNonNullableRawType ??=
         _nonNullableRawTypes[stackTraceClass] ??= new InterfaceType(
-            stackTraceClass, const <DartType>[], Nullability.nonNullable);
+            stackTraceClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType stackTraceRawType(Nullability nullability) {
@@ -1059,20 +1053,20 @@
 
   InterfaceType get streamLegacyRawType {
     return _streamLegacyRawType ??= _legacyRawTypes[streamClass] ??=
-        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(streamClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get streamNullableRawType {
     return _streamNullableRawType ??= _nullableRawTypes[streamClass] ??=
-        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(streamClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get streamNonNullableRawType {
     return _streamNonNullableRawType ??= _nonNullableRawTypes[streamClass] ??=
-        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
-            Nullability.nonNullable);
+        new InterfaceType(streamClass, Nullability.nonNullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType streamRawType(Nullability nullability) {
@@ -1094,24 +1088,24 @@
     return _asyncAwaitCompleterLegacyRawType ??=
         _legacyRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
             asyncAwaitCompleterClass,
-            const <DartType>[const DynamicType()],
-            Nullability.legacy);
+            Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get asyncAwaitCompleterNullableRawType {
     return _asyncAwaitCompleterNullableRawType ??=
         _nullableRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
             asyncAwaitCompleterClass,
-            const <DartType>[const DynamicType()],
-            Nullability.nullable);
+            Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get asyncAwaitCompleterNonNullableRawType {
     return _asyncAwaitCompleterNonNullableRawType ??=
         _nonNullableRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
             asyncAwaitCompleterClass,
-            const <DartType>[const DynamicType()],
-            Nullability.nonNullable);
+            Nullability.nonNullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType asyncAwaitCompleterRawType(Nullability nullability) {
@@ -1131,20 +1125,20 @@
 
   InterfaceType get futureOrLegacyRawType {
     return _futureOrLegacyRawType ??= _legacyRawTypes[futureOrClass] ??=
-        new InterfaceType(futureOrClass, const <DartType>[const DynamicType()],
-            Nullability.legacy);
+        new InterfaceType(futureOrClass, Nullability.legacy,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get futureOrNullableRawType {
     return _futureOrNullableRawType ??= _nullableRawTypes[futureOrClass] ??=
-        new InterfaceType(futureOrClass, const <DartType>[const DynamicType()],
-            Nullability.nullable);
+        new InterfaceType(futureOrClass, Nullability.nullable,
+            const <DartType>[const DynamicType()]);
   }
 
   InterfaceType get futureOrNonNullableRawType {
     return _futureOrNonNullableRawType ??=
         _nonNullableRawTypes[futureOrClass] ??= new InterfaceType(futureOrClass,
-            const <DartType>[const DynamicType()], Nullability.nonNullable);
+            Nullability.nonNullable, const <DartType>[const DynamicType()]);
   }
 
   InterfaceType futureOrRawType(Nullability nullability) {
@@ -1164,19 +1158,19 @@
 
   InterfaceType get pragmaLegacyRawType {
     return _pragmaLegacyRawType ??= _legacyRawTypes[pragmaClass] ??=
-        new InterfaceType(pragmaClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(pragmaClass, Nullability.legacy, const <DartType>[]);
   }
 
   InterfaceType get pragmaNullableRawType {
     return _pragmaNullableRawType ??= _nullableRawTypes[pragmaClass] ??=
         new InterfaceType(
-            pragmaClass, const <DartType>[], Nullability.nullable);
+            pragmaClass, Nullability.nullable, const <DartType>[]);
   }
 
   InterfaceType get pragmaNonNullableRawType {
     return _pragmaNonNullableRawType ??= _nonNullableRawTypes[pragmaClass] ??=
         new InterfaceType(
-            pragmaClass, const <DartType>[], Nullability.nonNullable);
+            pragmaClass, Nullability.nonNullable, const <DartType>[]);
   }
 
   InterfaceType pragmaRawType(Nullability nullability) {
@@ -1198,27 +1192,27 @@
     // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
     return _legacyRawTypes[klass] ??= new InterfaceType(
         klass,
+        Nullability.legacy,
         new List<DartType>.filled(
-            klass.typeParameters.length, const DynamicType()),
-        Nullability.legacy);
+            klass.typeParameters.length, const DynamicType()));
   }
 
   InterfaceType nullableRawType(Class klass) {
     // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
     return _nullableRawTypes[klass] ??= new InterfaceType(
         klass,
+        Nullability.nullable,
         new List<DartType>.filled(
-            klass.typeParameters.length, const DynamicType()),
-        Nullability.nullable);
+            klass.typeParameters.length, const DynamicType()));
   }
 
   InterfaceType nonNullableRawType(Class klass) {
     // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
     return _nonNullableRawTypes[klass] ??= new InterfaceType(
         klass,
+        Nullability.nonNullable,
         new List<DartType>.filled(
-            klass.typeParameters.length, const DynamicType()),
-        Nullability.nonNullable);
+            klass.typeParameters.length, const DynamicType()));
   }
 
   InterfaceType rawType(Class klass, Nullability nullability) {
diff --git a/pkg/kernel/lib/library_index.dart b/pkg/kernel/lib/library_index.dart
index abebaa4..ce66691 100644
--- a/pkg/kernel/lib/library_index.dart
+++ b/pkg/kernel/lib/library_index.dart
@@ -156,6 +156,7 @@
     // is external.  If a class or member was not found in an external library,
     // it might be that it exists in the actual library, but its interface was
     // not included in this build unit.
+    // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
     return library.isExternal
         ? "external library '${library.importUri}'"
         : "library '${library.importUri}'";
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index 27985e7..4f78734 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -148,7 +148,8 @@
       for (int i = 0; i < ownFunction.typeParameters.length; ++i) {
         var subParameter = ownFunction.typeParameters[i];
         var superParameter = superFunction.typeParameters[i];
-        typeParameterMap[subParameter] = new TypeParameterType(superParameter);
+        typeParameterMap[subParameter] =
+            new TypeParameterType(superParameter, Nullability.legacy);
       }
 
       ownSubstitution = Substitution.combine(
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 2710985..0096017 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -13,6 +13,7 @@
         InvalidType,
         NamedType,
         NeverType,
+        Nullability,
         TypeParameter,
         TypeParameterType,
         Typedef,
@@ -124,10 +125,8 @@
         return type;
       }
     }
-    return new InterfaceType.byReference(
-        type.className,
-        calculateBounds(type.classNode.typeParameters, objectClass),
-        type.nullability);
+    return new InterfaceType.byReference(type.className, type.nullability,
+        calculateBounds(type.classNode.typeParameters, objectClass));
   }
   if (type is TypedefType) {
     if (type.typeArguments.isEmpty) return type;
@@ -136,10 +135,8 @@
         return type;
       }
     }
-    return new TypedefType.byReference(
-        type.typedefReference,
-        calculateBounds(type.typedefNode.typeParameters, objectClass),
-        type.nullability);
+    return new TypedefType.byReference(type.typedefReference, type.nullability,
+        calculateBounds(type.typedefNode.typeParameters, objectClass));
   }
   return type;
 }
@@ -231,8 +228,8 @@
     // definition in that case.  For details, see [link]
     // (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/super-bounded-types.md).
     FunctionType functionType = type;
-    FunctionType cloned = new FunctionType(
-        functionType.positionalParameters, functionType.returnType,
+    FunctionType cloned = new FunctionType(functionType.positionalParameters,
+        functionType.returnType, Nullability.legacy,
         namedParameters: functionType.namedParameters,
         typeParameters: functionType.typeParameters,
         requiredParameterCount: functionType.requiredParameterCount,
@@ -426,7 +423,8 @@
           typeEnvironment, type.typeArguments[i],
           isCovariant: isCovariant);
     }
-    return new InterfaceType(type.classNode, replacedTypeArguments);
+    return new InterfaceType(
+        type.classNode, Nullability.legacy, replacedTypeArguments);
   } else if (type is TypedefType && type.typedefNode.typeParameters != null) {
     List<DartType> replacedTypeArguments =
         new List<DartType>(type.typeArguments.length);
@@ -435,7 +433,8 @@
           typeEnvironment, type.typeArguments[i],
           isCovariant: isCovariant);
     }
-    return new TypedefType(type.typedefNode, replacedTypeArguments);
+    return new TypedefType(
+        type.typedefNode, Nullability.legacy, replacedTypeArguments);
   } else if (type is FunctionType) {
     var replacedReturnType = convertSuperBoundedToRegularBounded(
         typeEnvironment, type.returnType,
@@ -456,7 +455,8 @@
               typeEnvironment, type.namedParameters[i].type,
               isCovariant: !isCovariant));
     }
-    return new FunctionType(replacedPositionalParameters, replacedReturnType,
+    return new FunctionType(
+        replacedPositionalParameters, replacedReturnType, Nullability.legacy,
         namedParameters: replacedNamedParameters,
         typeParameters: type.typeParameters,
         requiredParameterCount: type.requiredParameterCount,
diff --git a/pkg/kernel/lib/src/future_or.dart b/pkg/kernel/lib/src/future_or.dart
new file mode 100644
index 0000000..fd2d9d0
--- /dev/null
+++ b/pkg/kernel/lib/src/future_or.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// TODO(dmitryas):  Delete the file when a special representation for FutureOr
+// is landed.
+
+import '../ast.dart';
+
+Nullability uniteNullabilities(Nullability a, Nullability b) {
+  if (a == Nullability.nullable || b == Nullability.nullable) {
+    return Nullability.nullable;
+  }
+  if (a == Nullability.legacy || b == Nullability.legacy) {
+    return Nullability.legacy;
+  }
+  if (a == Nullability.undetermined || b == Nullability.undetermined) {
+    return Nullability.undetermined;
+  }
+  return Nullability.nonNullable;
+}
+
+Nullability intersectNullabilities(Nullability a, Nullability b) {
+  if (a == Nullability.nonNullable || b == Nullability.nonNullable) {
+    return Nullability.nonNullable;
+  }
+  if (a == Nullability.undetermined || b == Nullability.undetermined) {
+    return Nullability.undetermined;
+  }
+  if (a == Nullability.legacy || b == Nullability.legacy) {
+    return Nullability.legacy;
+  }
+  return Nullability.nonNullable;
+}
+
+Nullability computeNullabilityOfFutureOr(
+    InterfaceType futureOr, Class futureOrClass) {
+  assert(futureOr.classNode == futureOrClass);
+
+  // Performance note: the algorithm is linear.
+  DartType argument = futureOr.typeArguments.single;
+  if (argument is InterfaceType && argument.classNode == futureOrClass) {
+    return uniteNullabilities(
+        computeNullabilityOfFutureOr(argument, futureOrClass),
+        futureOr.nullability);
+  }
+  if (argument is TypeParameterType && argument.promotedBound != null) {
+    DartType promotedBound = argument.promotedBound;
+    if (promotedBound is InterfaceType &&
+        promotedBound.className == futureOrClass) {
+      return uniteNullabilities(
+          intersectNullabilities(argument.typeParameterTypeNullability,
+              computeNullabilityOfFutureOr(promotedBound, futureOrClass)),
+          futureOr.nullability);
+    }
+  }
+  Nullability argumentNullability =
+      argument is InvalidType ? Nullability.undetermined : argument.nullability;
+  return uniteNullabilities(argumentNullability, futureOr.nullability);
+}
+
+Nullability computeNullability(DartType type, Class futureOrClass) {
+  if (type is InterfaceType && type.classNode == futureOrClass) {
+    return computeNullabilityOfFutureOr(type, futureOrClass);
+  }
+  return type.nullability;
+}
diff --git a/pkg/kernel/lib/testing/mock_sdk_component.dart b/pkg/kernel/lib/testing/mock_sdk_component.dart
index 17be30b..f37b01c 100644
--- a/pkg/kernel/lib/testing/mock_sdk_component.dart
+++ b/pkg/kernel/lib/testing/mock_sdk_component.dart
@@ -17,7 +17,7 @@
   }
 
   var objectClass = addClass(coreLib, new Class(name: 'Object'));
-  var objectType = new InterfaceType(objectClass);
+  var objectType = new InterfaceType(objectClass, Nullability.legacy);
 
   TypeParameter typeParam(String name, [DartType bound]) {
     return new TypeParameter(name, bound ?? objectType);
@@ -47,7 +47,8 @@
         class_('List', typeParameters: [
           T
         ], implementedTypes: [
-          new Supertype(iterable, [new TypeParameterType(T)])
+          new Supertype(
+              iterable, [new TypeParameterType(T, Nullability.legacy)])
         ]));
   }
   addClass(
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 750cc48..88e1512 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -509,6 +509,7 @@
     }
     writeComponentProblems(component);
     for (var library in component.libraries) {
+      // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
       if (library.isExternal) {
         if (!showExternal) {
           continue;
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index f13dc82..6aa0943 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -932,8 +932,8 @@
     Tuple2<List<TypeParameter>,
             Tuple4<List<DartType>, List<DartType>, List<NamedType>, DartType>>
         tuple) {
-  return new FunctionType(
-      tuple.second.first + tuple.second.second, tuple.second.fourth,
+  return new FunctionType(tuple.second.first + tuple.second.second,
+      tuple.second.fourth, Nullability.legacy,
       requiredParameterCount: tuple.second.first.length,
       typeParameters: tuple.first,
       namedParameters: tuple.second.third);
@@ -962,7 +962,7 @@
 }
 
 TypeParameterType wrapTypeParameterType(Tuple2<TypeParameter, DartType> tuple) {
-  return new TypeParameterType(tuple.first, tuple.second);
+  return new TypeParameterType(tuple.first, Nullability.legacy, tuple.second);
 }
 
 Case<DartType> dartTypeSerializer =
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index d6bf44f..d77ba82 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -186,7 +186,8 @@
 
   SyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
       : iteratorVariable = new VariableDeclaration(':iterator')
-          ..type = new InterfaceType(helper.syncIteratorClass, [
+          ..type =
+              new InterfaceType(helper.syncIteratorClass, Nullability.legacy, [
             ContinuationRewriterBase.elementTypeFrom(
                 helper.iterableClass, enclosingFunction.returnType)
           ]),
@@ -749,8 +750,8 @@
               helper.streamIteratorConstructor,
               new Arguments(<Expression>[new VariableGet(streamVariable)],
                   types: [valueVariable.type])),
-          type: new InterfaceType(
-              helper.streamIteratorClass, [valueVariable.type]));
+          type: new InterfaceType(helper.streamIteratorClass,
+              Nullability.legacy, [valueVariable.type]));
 
       // await :for-iterator.moveNext()
       var condition = new AwaitExpression(new MethodInvocation(
@@ -914,8 +915,8 @@
 
     // _AsyncStarStreamController<T> :controller;
     controllerVariable = new VariableDeclaration(":controller",
-        type: new InterfaceType(
-            helper.asyncStarStreamControllerClass, [elementType]));
+        type: new InterfaceType(helper.asyncStarStreamControllerClass,
+            Nullability.legacy, [elementType]));
     statements.add(controllerVariable);
 
     // dynamic :controller_stream;
@@ -1036,12 +1037,12 @@
     if (valueType == const DynamicType()) {
       valueType = elementTypeFromReturnType(helper.futureOrClass);
     }
-    final DartType returnType =
-        new InterfaceType(helper.futureOrClass, <DartType>[valueType]);
+    final DartType returnType = new InterfaceType(
+        helper.futureOrClass, Nullability.legacy, <DartType>[valueType]);
     var completerTypeArguments = <DartType>[valueType];
 
-    final completerType = new InterfaceType(
-        helper.asyncAwaitCompleterClass, completerTypeArguments);
+    final completerType = new InterfaceType(helper.asyncAwaitCompleterClass,
+        Nullability.legacy, completerTypeArguments);
     // final Completer<T> :async_completer = new _AsyncAwaitCompleter<T>();
     completerVariable = new VariableDeclaration(":async_completer",
         initializer: new ConstructorInvocation(
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 2aa31c6..cbeb3d1 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -55,6 +55,7 @@
     // the mixin and constructors from the base class.
     var processedClasses = new Set<Class>();
     for (var library in libraries) {
+      // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
       if (library.isExternal) continue;
 
       for (var class_ in library.classes) {
@@ -71,6 +72,7 @@
     }
     // Resolve all super call expressions and super initializers.
     for (var library in libraries) {
+      // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
       if (library.isExternal) continue;
 
       for (var class_ in library.classes) {
diff --git a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
index 13bde9a..c2289a5 100644
--- a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
+++ b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
@@ -345,7 +345,7 @@
       _hasCreationLocationClass.enclosingLibrary,
     );
     final Field locationField = new Field(fieldName,
-        type: new InterfaceType(_locationClass),
+        type: new InterfaceType(_locationClass, Nullability.legacy),
         isFinal: true,
         reference: clazz.reference.canonicalName
             ?.getChildFromFieldWithName(fieldName)
@@ -433,6 +433,7 @@
       ..addAll(libraries);
 
     for (Library library in libraries) {
+      // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
       if (library.isExternal) {
         continue;
       }
@@ -453,6 +454,7 @@
             tracker: this);
 
     for (Library library in libraries) {
+      // ignore: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
       if (library.isExternal) {
         continue;
       }
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index f1d903e..e7b810b 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -114,7 +114,8 @@
       growable: true);
   var map = <TypeParameter, DartType>{};
   for (int i = 0; i < typeParameters.length; ++i) {
-    map[typeParameters[i]] = new TypeParameterType(freshParameters[i]);
+    map[typeParameters[i]] =
+        new TypeParameterType(freshParameters[i], Nullability.legacy);
   }
   CloneVisitor cloner;
   for (int i = 0; i < typeParameters.length; ++i) {
@@ -125,6 +126,8 @@
     freshTypeParameter.defaultType = typeParameter.defaultType != null
         ? substitute(typeParameter.defaultType, map)
         : null;
+    freshTypeParameter.variance =
+        typeParameter.isLegacyCovariant ? null : typeParameter.variance;
     if (typeParameter.annotations.isNotEmpty) {
       // Annotations can't refer to type parameters, so the cloner shouldn't
       // perform the substitution.
@@ -148,12 +151,12 @@
   FunctionType applyToFunctionType(FunctionType type) => new FunctionType(
       type.positionalParameters.map(substitute).toList(),
       substitute(type.returnType),
+      type.nullability,
       namedParameters: type.namedParameters.map(substituteNamed).toList(),
       typeParameters: freshTypeParameters,
       requiredParameterCount: type.requiredParameterCount,
       typedefType:
-          type.typedefType == null ? null : substitute(type.typedefType),
-      nullability: type.nullability);
+          type.typedefType == null ? null : substitute(type.typedefType));
 
   DartType substitute(DartType type) => substitution.substituteType(type);
 
@@ -290,7 +293,7 @@
   const _NullSubstitution();
 
   DartType getSubstitute(TypeParameter parameter, bool upperBound) {
-    return new TypeParameterType(parameter);
+    return new TypeParameterType(parameter, Nullability.legacy);
   }
 
   @override
@@ -385,7 +388,7 @@
 
   TypeParameter freshTypeParameter(TypeParameter node) {
     var fresh = new TypeParameter(node.name);
-    substitution[node] = new TypeParameterType(fresh);
+    substitution[node] = new TypeParameterType(fresh, Nullability.legacy);
     fresh.bound = visit(node.bound);
     if (node.defaultType != null) {
       fresh.defaultType = visit(node.defaultType);
@@ -492,7 +495,7 @@
     int before = useCounter;
     var typeArguments = node.typeArguments.map(visit).toList();
     if (useCounter == before) return node;
-    return new InterfaceType(node.classNode, typeArguments, node.nullability);
+    return new InterfaceType(node.classNode, node.nullability, typeArguments);
   }
 
   DartType visitTypedefType(TypedefType node) {
@@ -500,7 +503,7 @@
     int before = useCounter;
     var typeArguments = node.typeArguments.map(visit).toList();
     if (useCounter == before) return node;
-    return new TypedefType(node.typedefNode, typeArguments, node.nullability);
+    return new TypedefType(node.typedefNode, node.nullability, typeArguments);
   }
 
   List<TypeParameter> freshTypeParameters(List<TypeParameter> parameters) {
@@ -545,12 +548,11 @@
     DartType typedefType =
         node.typedefType == null ? null : inner.visit(node.typedefType);
     if (this.useCounter == before) return node;
-    return new FunctionType(positionalParameters, returnType,
+    return new FunctionType(positionalParameters, returnType, node.nullability,
         namedParameters: namedParameters,
         typeParameters: typeParameters,
         requiredParameterCount: node.requiredParameterCount,
-        typedefType: typedefType,
-        nullability: node.nullability);
+        typedefType: typedefType);
   }
 
   void bumpCountersUntil(_TypeSubstitutor target) {
@@ -717,7 +719,8 @@
       var rightInstance = <TypeParameter, DartType>{};
       for (int i = 0; i < type1.typeParameters.length; ++i) {
         var instantiator = new TypeParameter(type1.typeParameters[i].name);
-        var instantiatorType = new TypeParameterType(instantiator);
+        var instantiatorType =
+            new TypeParameterType(instantiator, Nullability.legacy);
         leftInstance[type1.typeParameters[i]] = instantiatorType;
         rightInstance[type2.typeParameters[i]] = instantiatorType;
         _universallyQuantifiedVariables.add(instantiator);
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 6024d89..53eec114 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -426,7 +426,8 @@
     Class class_ = target.enclosingClass;
     handleCall(arguments, target.function.thisFunctionType,
         typeParameters: class_.typeParameters);
-    return new InterfaceType(target.enclosingClass, arguments.types);
+    return new InterfaceType(
+        target.enclosingClass, Nullability.legacy, arguments.types);
   }
 
   @override
@@ -729,7 +730,8 @@
       DartType valueType = visitExpression(value);
       checkAssignable(node, fieldType, valueType);
     });
-    return new InterfaceType(node.classNode, node.typeArguments);
+    return new InterfaceType(
+        node.classNode, Nullability.legacy, node.typeArguments);
   }
 
   @override
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index de454c1..028df5e 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -8,6 +8,7 @@
 import 'core_types.dart';
 import 'type_algebra.dart';
 
+import 'src/future_or.dart';
 import 'src/hierarchy_based_type_environment.dart'
     show HierarchyBasedTypeEnvironment;
 
@@ -44,29 +45,34 @@
   InterfaceType get functionLegacyRawType => coreTypes.functionLegacyRawType;
 
   InterfaceType literalListType(DartType elementType) {
-    return new InterfaceType(coreTypes.listClass, <DartType>[elementType]);
+    return new InterfaceType(
+        coreTypes.listClass, Nullability.legacy, <DartType>[elementType]);
   }
 
   InterfaceType literalSetType(DartType elementType) {
-    return new InterfaceType(coreTypes.setClass, <DartType>[elementType]);
+    return new InterfaceType(
+        coreTypes.setClass, Nullability.legacy, <DartType>[elementType]);
   }
 
   InterfaceType literalMapType(DartType key, DartType value) {
-    return new InterfaceType(coreTypes.mapClass, <DartType>[key, value]);
+    return new InterfaceType(
+        coreTypes.mapClass, Nullability.legacy, <DartType>[key, value]);
   }
 
   InterfaceType iterableType(DartType type) {
-    return new InterfaceType(coreTypes.iterableClass, <DartType>[type]);
+    return new InterfaceType(
+        coreTypes.iterableClass, Nullability.legacy, <DartType>[type]);
   }
 
   InterfaceType streamType(DartType type) {
-    return new InterfaceType(coreTypes.streamClass, <DartType>[type]);
+    return new InterfaceType(
+        coreTypes.streamClass, Nullability.legacy, <DartType>[type]);
   }
 
   InterfaceType futureType(DartType type,
       [Nullability nullability = Nullability.legacy]) {
     return new InterfaceType(
-        coreTypes.futureClass, <DartType>[type], nullability);
+        coreTypes.futureClass, nullability, <DartType>[type]);
   }
 
   /// Removes a level of `Future<>` types wrapping a type.
@@ -155,20 +161,13 @@
   }
 }
 
-/// Result of a nullability-aware subtype check.
-///
-/// It is assumed that if a subtype check succeeds for two types in full-NNBD
-/// mode, it also succeeds for those two types if the nullability markers on the
-/// types and all of their sub-terms are ignored (that is, in the pre-NNBD
-/// mode).  By contraposition, if a subtype check fails for two types when the
-/// nullability markers are ignored, it should also fail for those types in
-/// full-NNBD mode.
+/// Tri-state logical result of a nullability-aware subtype check.
 class IsSubtypeOf {
   /// Internal value constructed via [IsSubtypeOf.never].
   ///
   /// The integer values of [_valueNever], [_valueOnlyIfIgnoringNullabilities],
-  /// and [_valueAlways] are important for the implementations of [_joinValues],
-  /// [_all], and [join].  They should be kept in sync.
+  /// and [_valueAlways] are important for the implementations of [_andValues],
+  /// [_all], and [and].  They should be kept in sync.
   static const int _valueNever = 0;
 
   /// Internal value constructed via [IsSubtypeOf.onlyIfIgnoringNullabilities].
@@ -184,13 +183,23 @@
     const IsSubtypeOf.always()
   ];
 
-  /// Joins results of subtype checks on parts into the overall result.
+  /// Combines results of subtype checks on parts into the overall result.
   ///
-  /// Both [value1] and [value2] should be chosen from
+  /// It's an implementation detail for [and].  See the comment on [and] for
+  /// more details and examples.  Both [value1] and [value2] should be chosen
+  /// from [_valueNever], [_valueOnlyIfIgnoringNullabilities], and
+  /// [_valueAlways].  The method produces the result which is one of
+  /// [_valueNever], [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
+  static int _andValues(int value1, int value2) => value1 & value2;
+
+  /// Combines results of the checks on alternatives into the overall result.
+  ///
+  /// It's an implementation detail for [or].  See the comment on [or] for more
+  /// details and examples.  Both [value1] and [value2] should be chosen from
   /// [_valueNever], [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
   /// The method produces the result which is one of [_valueNever],
   /// [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
-  static int _joinValues(int value1, int value2) => value1 & value2;
+  static int _orValues(int value1, int value2) => value1 | value2;
 
   /// The only state of an [IsSubtypeOf] object.
   final int _value;
@@ -202,8 +211,12 @@
 
   /// Subtype check succeeds only if the nullability markers are ignored.
   ///
-  /// This implies that if the nullability markers aren't ignored, the subtype
-  /// check fails.
+  /// It is assumed that if a subtype check succeeds for two types in full-NNBD
+  /// mode, it also succeeds for those two types if the nullability markers on
+  /// the types and all of their sub-terms are ignored (that is, in the pre-NNBD
+  /// mode).  By contraposition, if a subtype check fails for two types when the
+  /// nullability markers are ignored, it should also fail for those types in
+  /// full-NNBD mode.
   const IsSubtypeOf.onlyIfIgnoringNullabilities()
       : this._internal(_valueOnlyIfIgnoringNullabilities);
 
@@ -211,6 +224,15 @@
   const IsSubtypeOf.never() : this._internal(_valueNever);
 
   /// Checks if two types are in relation based solely on their nullabilities.
+  ///
+  /// This is useful on its own if the types are known to be the same modulo the
+  /// nullability attribute, but mostly it's useful to combine the result from
+  /// [IsSubtypeOf.basedSolelyOnNullabilities] via [and] with the partial
+  /// results obtained from other type parts. For example, the overall result
+  /// for `List<int>? <: List<num>*` can be computed as `Ra.join(Rn)` where `Ra`
+  /// is the result of a subtype check on the arguments `int` and `num`, and
+  /// `Rn` is the result of [IsSubtypeOf.basedSolelyOnNullabilities] on the
+  /// types `List<int>?` and `List<num>*`.
   factory IsSubtypeOf.basedSolelyOnNullabilities(
       DartType subtype, DartType supertype) {
     if (subtype.isPotentiallyNullable && supertype.isPotentiallyNonNullable) {
@@ -221,26 +243,56 @@
 
   /// Combines results for the type parts into the overall result for the type.
   ///
-  /// For example, the result of `A<B1, C1>? <: A<B2, C2>*` can be computed as
-  /// `Rb.join(Rc).join(Rn)` where `Rb` is the result of `B1 <: B2`, `Rc` is the
-  /// result of `C1 <: C2`, and `Rn` is
-  /// `new IsSubtypeOf.basedSolelyOnNullabilities(A<B1, C1>?, A<B2, C2>*)`.
-  IsSubtypeOf join(IsSubtypeOf other) {
-    return _all[_joinValues(_value, other._value)];
+  /// For example, the result of `A<B1, C1> <: A<B2, C2>` can be computed from
+  /// the results of the checks `B1 <: B2` and `C1 <: C2`.  Using the binary
+  /// outcome of the checks, the combination of the check results on parts is
+  /// simply done via `&&`, and [and] is the analog to `&&` for the ternary
+  /// outcome.  So, in the example above the overall result is computed as
+  /// `Rb.and(Rc)` where `Rb` is the result of `B1 <: B2`, `Rc` is the result
+  /// of `C1 <: C2`.
+  IsSubtypeOf and(IsSubtypeOf other) {
+    return _all[_andValues(_value, other._value)];
   }
 
-  /// Shorts the computation of [join] if `this` is [IsSubtypeOf.never].
+  /// Shorts the computation of [and] if `this` is [IsSubtypeOf.never].
   ///
-  /// Use this instead of [join] for optimization in case the argument to [join]
-  /// is, for example, a potentially expensive subtype check.  Unlike [join],
-  /// [joinWithSubtypeCheckFor] will immediately return if [this] was
-  /// constructed as [IsSubtypeOf.never] because the right-hand side will not
-  /// change the result anyway.
-  IsSubtypeOf joinWithSubtypeCheckFor(
+  /// Use this instead of [and] for optimization in case the argument to [and]
+  /// is, for example, a potentially expensive subtype check.  Unlike [and],
+  /// [andSubtypeCheckFor] will immediately return if `this` was constructed as
+  /// [IsSubtypeOf.never] because the right-hand side will not change the
+  /// overall result anyway.
+  IsSubtypeOf andSubtypeCheckFor(
       DartType subtype, DartType supertype, SubtypeTester tester) {
     if (_value == _valueNever) return this;
     return this
-        .join(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
+        .and(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
+  }
+
+  /// Combines results of the checks on alternatives into the overall result.
+  ///
+  /// For example, the result of `T <: FutureOr<S>` can be computed from the
+  /// results of the checks `T <: S` and `T <: Future<S>`.  Using the binary
+  /// outcome of the checks, the combination of the check results on parts is
+  /// simply done via logical "or", and [or] is the analog to "or" for the
+  /// ternary outcome.  So, in the example above the overall result is computed
+  /// as `Rs.or(Rf)` where `Rs` is the result of `T <: S`, `Rf` is the result of
+  /// `T <: Future<S>`.
+  IsSubtypeOf or(IsSubtypeOf other) {
+    return _all[_orValues(_value, other._value)];
+  }
+
+  /// Shorts the computation of [or] if `this` is [IsSubtypeOf.always].
+  ///
+  /// Use this instead of [or] for optimization in case the argument to [or] is,
+  /// for example, a potentially expensive subtype check.  Unlike [or],
+  /// [orSubtypeCheckFor] will immediately return if `this` was constructed
+  /// as [IsSubtypeOf.always] because the right-hand side will not change the
+  /// overall result anyway.
+  IsSubtypeOf orSubtypeCheckFor(
+      DartType subtype, DartType supertype, SubtypeTester tester) {
+    if (_value == _valueAlways) return this;
+    return this
+        .or(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
   }
 
   bool isSubtypeWhenIgnoringNullabilities() {
@@ -250,6 +302,18 @@
   bool isSubtypeWhenUsingNullabilities() {
     return _value == _valueAlways;
   }
+
+  String toString() {
+    switch (_value) {
+      case _valueAlways:
+        return "IsSubtypeOf.always";
+      case _valueNever:
+        return "IsSubtypeOf.never";
+      case _valueOnlyIfIgnoringNullabilities:
+        return "IsSubtypeOf.onlyIfIgnoringNullabilities";
+    }
+    return "IsSubtypeOf.<unknown value '${_value}'>";
+  }
 }
 
 enum SubtypeCheckMode {
@@ -334,8 +398,10 @@
         return const IsSubtypeOf.always();
       }
 
-      if (supertype.nullability == Nullability.nullable ||
-          supertype.nullability == Nullability.legacy) {
+      Nullability supertypeNullability =
+          computeNullability(supertype, futureOrClass);
+      if (supertypeNullability == Nullability.nullable ||
+          supertypeNullability == Nullability.legacy) {
         return const IsSubtypeOf.always();
       }
       // See rule 4 of the subtype rules from the Dart Language Specification.
@@ -359,9 +425,9 @@
       // given t1 is Future<A> | A, then:
       // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
       return performNullabilityAwareSubtypeCheck(subtypeArg, supertype)
-          .joinWithSubtypeCheckFor(
+          .andSubtypeCheckFor(
               futureType(subtypeArg, Nullability.nonNullable), supertype, this)
-          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
+          .and(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
     }
 
     if (supertype is InterfaceType && supertype.classNode == objectClass) {
@@ -373,14 +439,13 @@
         identical(supertype.classNode, futureOrClass)) {
       // given t2 is Future<A> | A, then:
       // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
-      var supertypeArg = supertype.typeArguments[0];
-      var supertypeFuture = futureType(supertypeArg, Nullability.legacy);
+      Nullability unitedNullability =
+          computeNullabilityOfFutureOr(supertype, futureOrClass);
+      DartType supertypeArg = supertype.typeArguments[0];
+      DartType supertypeFuture = futureType(supertypeArg, unitedNullability);
       return performNullabilityAwareSubtypeCheck(subtype, supertypeFuture)
-                  .isSubtypeWhenIgnoringNullabilities() ||
-              performNullabilityAwareSubtypeCheck(subtype, supertypeArg)
-                  .isSubtypeWhenIgnoringNullabilities()
-          ? const IsSubtypeOf.always()
-          : const IsSubtypeOf.never();
+          .orSubtypeCheckFor(
+              subtype, supertypeArg.withNullability(unitedNullability), this);
     }
 
     if (subtype is InterfaceType && supertype is InterfaceType) {
@@ -394,47 +459,69 @@
         DartType rightType = supertype.typeArguments[i];
         if (variance == Variance.contravariant) {
           result = result
-              .join(performNullabilityAwareSubtypeCheck(rightType, leftType));
+              .and(performNullabilityAwareSubtypeCheck(rightType, leftType));
           if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         } else if (variance == Variance.invariant) {
-          result = result.join(
+          result = result.and(
               performNullabilityAwareMutualSubtypesCheck(leftType, rightType));
           if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         } else {
           result = result
-              .join(performNullabilityAwareSubtypeCheck(leftType, rightType));
+              .and(performNullabilityAwareSubtypeCheck(leftType, rightType));
           if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         }
       }
       return result
-          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
+          .and(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
     }
     if (subtype is TypeParameterType) {
-      if (supertype is TypeParameterType &&
-          subtype.parameter == supertype.parameter) {
-        if (supertype.promotedBound != null) {
-          return performNullabilityAwareSubtypeCheck(
-              subtype.bound, supertype.bound);
+      if (supertype is TypeParameterType) {
+        IsSubtypeOf result = const IsSubtypeOf.always();
+        if (subtype.parameter == supertype.parameter) {
+          if (supertype.promotedBound != null) {
+            return performNullabilityAwareSubtypeCheck(
+                    subtype,
+                    new TypeParameterType(supertype.parameter,
+                        supertype.typeParameterTypeNullability))
+                .andSubtypeCheckFor(subtype, supertype.bound, this);
+          } else {
+            // Promoted bound should always be a subtype of the declared bound.
+            // TODO(dmitryas): Use the following assertion when type promotion
+            // is updated.
+            // assert(subtype.promotedBound == null ||
+            //     performNullabilityAwareSubtypeCheck(
+            //         subtype.bound, supertype.bound)
+            //         .isSubtypeWhenUsingNullabilities());
+            assert(subtype.promotedBound == null ||
+                performNullabilityAwareSubtypeCheck(
+                        subtype.bound, supertype.bound)
+                    .isSubtypeWhenIgnoringNullabilities());
+            result = const IsSubtypeOf.always();
+          }
         } else {
-          // Promoted bound should always be a subtype of the declared bound.
-          assert(subtype.promotedBound == null ||
-              performNullabilityAwareSubtypeCheck(
-                      subtype.bound, supertype.bound)
-                  .isSubtypeWhenIgnoringNullabilities());
-          return const IsSubtypeOf.always();
+          result =
+              performNullabilityAwareSubtypeCheck(subtype.bound, supertype);
         }
+        if (subtype.nullability == Nullability.undetermined &&
+            supertype.nullability == Nullability.undetermined) {
+          // The two nullabilities are undetermined, but are connected via
+          // additional constraint, namely that they will be equal at run time.
+          return result;
+        }
+        return result.and(
+            new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
       }
       // Termination: if there are no cyclically bound type parameters, this
       // recursive call can only occur a finite number of times, before reaching
       // a shrinking recursive call (or terminating).
       return performNullabilityAwareSubtypeCheck(subtype.bound, supertype)
-          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
+          .and(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
     }
     if (subtype is FunctionType) {
       if (supertype is InterfaceType && supertype.classNode == functionClass) {
@@ -449,8 +536,9 @@
 
   IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
       DartType type1, DartType type2) {
+    // TODO(dmitryas): Replace it with one recursive descent instead of two.
     return performNullabilityAwareSubtypeCheck(type1, type2)
-        .joinWithSubtypeCheckFor(type2, type1, this);
+        .andSubtypeCheckFor(type2, type1, this);
   }
 
   IsSubtypeOf _performNullabilityAwareFunctionSubtypeCheck(
@@ -465,12 +553,15 @@
     if (subtype.typeParameters.length != supertype.typeParameters.length) {
       return const IsSubtypeOf.never();
     }
+
+    IsSubtypeOf result = const IsSubtypeOf.always();
     if (subtype.typeParameters.isNotEmpty) {
       var substitution = <TypeParameter, DartType>{};
       for (int i = 0; i < subtype.typeParameters.length; ++i) {
         var subParameter = subtype.typeParameters[i];
         var superParameter = supertype.typeParameters[i];
-        substitution[subParameter] = new TypeParameterType(superParameter);
+        substitution[subParameter] =
+            new TypeParameterType(superParameter, Nullability.legacy);
       }
       for (int i = 0; i < subtype.typeParameters.length; ++i) {
         var subParameter = subtype.typeParameters[i];
@@ -479,28 +570,26 @@
         // Termination: if there are no cyclically bound type parameters, this
         // recursive call can only occur a finite number of times before
         // reaching a shrinking recursive call (or terminating).
-        // TODO(dmitryas): Replace it with one recursive descent instead of two.
-        if (!performNullabilityAwareSubtypeCheck(superParameter.bound, subBound)
-                .isSubtypeWhenIgnoringNullabilities() ||
-            !performNullabilityAwareSubtypeCheck(subBound, superParameter.bound)
-                .isSubtypeWhenIgnoringNullabilities()) {
+        result = result.and(performNullabilityAwareMutualSubtypesCheck(
+            superParameter.bound, subBound));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
       }
       subtype = substitute(subtype.withoutTypeParameters, substitution);
     }
-    if (!performNullabilityAwareSubtypeCheck(
-            subtype.returnType, supertype.returnType)
-        .isSubtypeWhenIgnoringNullabilities()) {
+    result = result.and(performNullabilityAwareSubtypeCheck(
+        subtype.returnType, supertype.returnType));
+    if (!result.isSubtypeWhenIgnoringNullabilities()) {
       return const IsSubtypeOf.never();
     }
     for (int i = 0; i < supertype.positionalParameters.length; ++i) {
       var supertypeParameter = supertype.positionalParameters[i];
       var subtypeParameter = subtype.positionalParameters[i];
       // Termination: Both types shrink in size.
-      if (!performNullabilityAwareSubtypeCheck(
-              supertypeParameter, subtypeParameter)
-          .isSubtypeWhenIgnoringNullabilities()) {
+      result = result.and(performNullabilityAwareSubtypeCheck(
+          supertypeParameter, subtypeParameter));
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
         return const IsSubtypeOf.never();
       }
     }
@@ -516,12 +605,13 @@
       }
       NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex];
       // Termination: Both types shrink in size.
-      if (!performNullabilityAwareSubtypeCheck(
-              supertypeParameter.type, subtypeParameter.type)
-          .isSubtypeWhenIgnoringNullabilities()) {
+      result = result.and(performNullabilityAwareSubtypeCheck(
+          supertypeParameter.type, subtypeParameter.type));
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
         return const IsSubtypeOf.never();
       }
     }
-    return const IsSubtypeOf.always();
+    return result
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
   }
 }
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 503655e..f47c3e7 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -6,8 +6,9 @@
 import 'ast.dart';
 import 'transformations/flags.dart';
 
-void verifyComponent(Component component) {
-  VerifyingVisitor.check(component);
+void verifyComponent(Component component, {bool isOutline, bool afterConst}) {
+  VerifyingVisitor.check(component,
+      isOutline: isOutline, afterConst: afterConst);
 }
 
 class VerificationError {
@@ -49,14 +50,22 @@
   Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
   final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
   final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
+  final Set<Constant> seenConstants = <Constant>{};
   bool classTypeParametersAreInScope = false;
 
   /// If true, relax certain checks for *outline* mode. For example, don't
   /// attempt to validate constructor initializers.
-  bool isOutline = false;
+  final bool isOutline;
+
+  /// If true, assume that constant evaluation has been performed (with a
+  /// target that did not opt out of any of the constant inlining) and report
+  /// a verification error for anything that should have been removed by it.
+  final bool afterConst;
 
   bool inCatchBlock = false;
 
+  bool inUnevaluatedConstant = false;
+
   Library currentLibrary;
 
   Member currentMember;
@@ -67,14 +76,32 @@
 
   TreeNode get context => currentMember ?? currentClass;
 
-  static void check(Component component) {
-    component.accept(new VerifyingVisitor());
+  static void check(Component component, {bool isOutline, bool afterConst}) {
+    component.accept(
+        new VerifyingVisitor(isOutline: isOutline, afterConst: afterConst));
   }
 
+  VerifyingVisitor({bool isOutline, bool afterConst})
+      : isOutline = isOutline ?? false,
+        afterConst = afterConst ?? !(isOutline ?? false);
+
+  @override
   defaultTreeNode(TreeNode node) {
     visitChildren(node);
   }
 
+  @override
+  defaultConstantReference(Constant constant) {
+    if (seenConstants.add(constant)) {
+      constant.accept(this);
+    }
+  }
+
+  @override
+  defaultConstant(Constant constant) {
+    constant.visitChildren(this);
+  }
+
   problem(TreeNode node, String details, {TreeNode context}) {
     context ??= this.context;
     throw new VerificationError(context, node, details);
@@ -392,11 +419,22 @@
     }
     visitChildren(node);
     declareVariable(node);
+    if (afterConst && node.isConst) {
+      Expression initializer = node.initializer;
+      if (!(initializer is InvalidExpression ||
+          initializer is ConstantExpression &&
+              initializer.constant is UnevaluatedConstant)) {
+        problem(node, "Constant VariableDeclaration");
+      }
+    }
   }
 
   visitVariableGet(VariableGet node) {
     checkVariableInScope(node.variable, node);
     visitChildren(node);
+    if (afterConst && node.variable.isConst) {
+      problem(node, "VariableGet of const variable '${node.variable}'.");
+    }
   }
 
   visitVariableSet(VariableSet node) {
@@ -424,6 +462,9 @@
     if (node.target.isInstanceMember) {
       problem(node, "StaticGet of '${node.target}' that's an instance member.");
     }
+    if (afterConst && node.target is Field && node.target.isConst) {
+      problem(node, "StaticGet of const field '${node.target}'.");
+    }
   }
 
   @override
@@ -456,6 +497,9 @@
           "Constant StaticInvocation of '${node.target}' that isn't"
           " a const external factory.");
     }
+    if (afterConst && node.isConst && !inUnevaluatedConstant) {
+      problem(node, "Constant StaticInvocation.");
+    }
   }
 
   void checkTargetedInvocation(Member target, InvocationExpression node) {
@@ -532,6 +576,9 @@
           "Constant ConstructorInvocation fo '${node.target}' that"
           " isn't const.");
     }
+    if (afterConst && node.isConst) {
+      problem(node, "Invocation of const constructor '${node.target}'.");
+    }
   }
 
   bool areArgumentsCompatible(Arguments arguments, FunctionNode function) {
@@ -554,6 +601,37 @@
   }
 
   @override
+  visitListLiteral(ListLiteral node) {
+    visitChildren(node);
+    if (afterConst && node.isConst) {
+      problem(node, "Constant list literal.");
+    }
+  }
+
+  @override
+  visitSetLiteral(SetLiteral node) {
+    visitChildren(node);
+    if (afterConst && node.isConst) {
+      problem(node, "Constant set literal.");
+    }
+  }
+
+  @override
+  visitMapLiteral(MapLiteral node) {
+    visitChildren(node);
+    if (afterConst && node.isConst) {
+      problem(node, "Constant map literal.");
+    }
+  }
+
+  @override
+  visitSymbolLiteral(SymbolLiteral node) {
+    if (afterConst) {
+      problem(node, "Symbol literal.");
+    }
+  }
+
+  @override
   visitContinueSwitchStatement(ContinueSwitchStatement node) {
     if (node.target == null) {
       problem(node, "No target.");
@@ -569,6 +647,57 @@
   }
 
   @override
+  visitInstanceConstant(InstanceConstant constant) {
+    constant.visitChildren(this);
+    if (constant.typeArguments.length !=
+        constant.classNode.typeParameters.length) {
+      problem(
+          currentParent,
+          "Constant $constant provides ${constant.typeArguments.length}"
+          " type arguments, but the class declares"
+          " ${constant.classNode.typeParameters.length} parameters.");
+    }
+    Set<Class> superClasses = <Class>{};
+    int fieldCount = 0;
+    for (Class cls = constant.classNode; cls != null; cls = cls.superclass) {
+      superClasses.add(cls);
+      for (Field f in cls.fields) {
+        if (!f.isStatic && !f.isConst) fieldCount++;
+      }
+    }
+    if (constant.fieldValues.length != fieldCount) {
+      problem(
+          currentParent,
+          "Constant $constant provides ${constant.fieldValues.length}"
+          " field values, but the class declares"
+          " $fieldCount fields.");
+    }
+    constant.fieldValues.forEach((Reference fieldRef, Constant value) {
+      Field field = fieldRef.asField;
+      if (!superClasses.contains(field.enclosingClass)) {
+        problem(
+            currentParent,
+            "Constant $constant refers to field $field,"
+            " which does not belong to the right class.");
+      }
+    });
+  }
+
+  @override
+  visitUnevaluatedConstant(UnevaluatedConstant constant) {
+    if (inUnevaluatedConstant) {
+      problem(currentParent, "UnevaluatedConstant in UnevaluatedConstant.");
+    }
+    bool savedInUnevaluatedConstant = inUnevaluatedConstant;
+    inUnevaluatedConstant = true;
+    TreeNode oldParent = currentParent;
+    currentParent = null;
+    constant.expression.accept(this);
+    currentParent = oldParent;
+    inUnevaluatedConstant = savedInUnevaluatedConstant;
+  }
+
+  @override
   defaultMemberReference(Member node) {
     if (node.transformerFlags & TransformerFlag.seenByVerifier == 0) {
       problem(
@@ -616,7 +745,7 @@
       problem(
           currentParent,
           "Type $node provides ${node.typeArguments.length}"
-          " type arguments but the class declares"
+          " type arguments, but the class declares"
           " ${node.classNode.typeParameters.length} parameters.");
     }
   }
@@ -629,7 +758,7 @@
       problem(
           currentParent,
           "The typedef type $node provides ${node.typeArguments.length}"
-          " type arguments but the typedef declares"
+          " type arguments, but the typedef declares"
           " ${node.typedefNode.typeParameters.length} parameters.");
     }
   }
diff --git a/pkg/kernel/runtime/reify/README.md b/pkg/kernel/runtime/reify/README.md
deleted file mode 100644
index d3371fb..0000000
--- a/pkg/kernel/runtime/reify/README.md
+++ /dev/null
@@ -1,14 +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.
--->
-# Runtime Support for Reified Generic Types
-
-This subdirectory contains files used at runtime by the code generated by
-[../reify_transformer.dart].
-
-The files in this directory can be imported by anyone, but files in this
-directory should be frugal about importing anything themselves. This is because
-this library is used by all programs that are tranformed and contributes to
-code size.
diff --git a/pkg/kernel/runtime/reify/declarations.dart b/pkg/kernel/runtime/reify/declarations.dart
deleted file mode 100644
index 7aeb474..0000000
--- a/pkg/kernel/runtime/reify/declarations.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library kernel.transformations.reify.runtime.declarations;
-
-import 'types.dart' show FunctionType, Interface, ReifiedType, TypeVariable;
-
-typedef String Id2String(Object id);
-
-/// Represents a class.
-///
-/// There's one instance of this class for each class in the program.
-///
-/// Note: not all classes can be represented as a compile-time constants. For
-/// example, most core classes, such as, `String`, `int`, and `double`
-/// implement `Comparable` in a way that cannot be expressed as a constant.
-class Class {
-  final id;
-
-  Interface supertype;
-
-  FunctionType callableType;
-
-  final List<TypeVariable> variables;
-
-  List<Interface> interfaces;
-
-  static Id2String debugId2String;
-
-  Class(this.id, this.supertype,
-      {this.callableType,
-      this.variables: const <TypeVariable>[],
-      this.interfaces /* set in init */});
-
-  Interface get thisType {
-    return new Interface(this, variables);
-  }
-
-  String get name => debugId2String == null ? "$id" : debugId2String(id);
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write("class $name");
-    if (variables.isNotEmpty) {
-      sb.write("<");
-      bool first = true;
-      for (TypeVariable tv in variables) {
-        if (!first) {
-          sb.write(", ");
-        }
-        sb.write(tv);
-        sb.write(" extends ");
-        sb.write(tv.bound);
-      }
-      sb.write(">");
-    }
-    if (supertype != null) {
-      sb.write(" extends $supertype");
-    }
-    if (interfaces.isNotEmpty) {
-      sb.write(" implements ");
-      sb.writeAll(interfaces, ", ");
-    }
-    return "$sb";
-  }
-}
-
-/// Allocates a (non-growable) list of [amount] class declarations with ids `0`
-/// to `amount - 1`. This function is called from the generated code that
-/// initializes the type information.
-List<Class> allocateDeclarations(List<String> names, List<int> typeParameters) {
-  List<TypeVariable> allocateVariables(int amount) {
-    if (amount == 0) return const <TypeVariable>[];
-    return new List<TypeVariable>.generate(
-        amount, (int i) => new TypeVariable(i),
-        growable: false);
-  }
-
-  return new List<Class>.generate(
-      names.length,
-      (int i) => new Class(names[i], null,
-          variables: allocateVariables(typeParameters[i])),
-      growable: false);
-}
-
-/// Initializes the supertype and interfaces of `classes[index]`.
-/// This function is called from generated code.
-void init(List<Class> classes, int index, ReifiedType supertype,
-    [List<Interface> interfaces = const <Interface>[],
-    FunctionType callableType]) {
-  Class declaration = classes[index];
-  assert(supertype == null);
-  declaration.supertype = supertype;
-  assert(interfaces == null);
-  declaration.interfaces = interfaces;
-  declaration.callableType = callableType;
-}
diff --git a/pkg/kernel/runtime/reify/interceptors.dart b/pkg/kernel/runtime/reify/interceptors.dart
deleted file mode 100644
index af4368d..0000000
--- a/pkg/kernel/runtime/reify/interceptors.dart
+++ /dev/null
@@ -1,73 +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.reify.runtime.interceptors;
-
-import 'types.dart' show ReifiedType;
-
-/// Helper method that generates a [ReifiedType] corresponding to the literal
-/// type [type].
-///
-/// Calls to this method are recognized in the transformation and replaced by
-/// code that constructs the correct type.
-ReifiedType reify(Type type) {
-  throw "This method should never be called in translated code";
-}
-
-/// Marker interface to indicate that we can extract the runtime type using
-/// a property getter.
-abstract class HasRuntimeTypeGetter {
-  ReifiedType get $type;
-}
-
-/// Interceptor to safely access the type of an object.
-///
-/// For native objects that do not have the `$type` field on them, the
-/// interceptor directly returns the type, otherwise the value of the field is
-/// returned.
-ReifiedType type(dynamic o) {
-  if (o == null) {
-    return reify(Null);
-  } else if (o is HasRuntimeTypeGetter) {
-    return o.$type;
-  } else if (o is bool) {
-    return reify(bool);
-  } else if (o is String) {
-    return reify(String);
-  } else if (o is int) {
-    return reify(int);
-  } else if (o is double) {
-    return reify(double);
-  } else if (o is Type) {
-    return reify(Type);
-  } else if (o is AbstractClassInstantiationError) {
-    return reify(AbstractClassInstantiationError);
-  } else if (o is NoSuchMethodError) {
-    return reify(NoSuchMethodError);
-  } else if (o is CyclicInitializationError) {
-    return reify(CyclicInitializationError);
-  } else if (o is UnsupportedError) {
-    return reify(UnsupportedError);
-  } else if (o is IntegerDivisionByZeroException) {
-    return reify(IntegerDivisionByZeroException);
-  } else if (o is RangeError) {
-    return reify(RangeError);
-  } else if (o is ArgumentError) {
-    return reify(ArgumentError);
-  }
-  ReifiedType type = _type[o];
-  if (type != null) {
-    return type;
-  }
-  throw 'Unable to get runtime type of ${o.runtimeType}';
-}
-
-// This constructor call is not intercepted with [attachType] since the runtime
-// library is currently never transformed.
-final Expando _type = new Expando();
-
-dynamic attachType(Object o, ReifiedType t) {
-  _type[o] = t;
-  return o;
-}
diff --git a/pkg/kernel/runtime/reify/types.dart b/pkg/kernel/runtime/reify/types.dart
deleted file mode 100644
index f119342..0000000
--- a/pkg/kernel/runtime/reify/types.dart
+++ /dev/null
@@ -1,678 +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.
-
-/// Notation:
-///
-/// * `[[T]]` is the runtime representation of type `T` (that is, `T` reified).
-library kernel.transformations.reify.runtime.types;
-
-import 'declarations.dart' show Class;
-
-export 'declarations.dart';
-
-export 'interceptors.dart';
-
-// The public interface of this library are static functions to access parts of
-// reified type objects and the constructors on the ReifiedType subclasses.
-
-bool isSubtypeOf(ReifiedType a, ReifiedType b) => a._isSubtypeOf(b);
-
-bool isMoreSpecificThan(ReifiedType a, ReifiedType b) {
-  return a._isMoreSpecificThan(b);
-}
-
-Kind getKind(ReifiedType type) => type._kind;
-
-ReifiedType asInstanceOf(Interface type, Class declaration) {
-  return type.asInstanceOf(declaration);
-}
-
-List<ReifiedType> getTypeArguments(Interface type) => type._typeArguments;
-
-bool isDynamic(ReifiedType type) => type._isDynamic;
-
-bool isFunction(ReifiedType type) => type._isFunction;
-
-bool isInterface(ReifiedType type) => type._isInterface;
-
-bool isIntersection(ReifiedType type) => type._isIntersection;
-
-bool isVariable(ReifiedType type) => type._isVariable;
-
-bool isVoid(ReifiedType type) => type._isVoid;
-
-bool isObject(ReifiedType type) => false;
-
-ReifiedType getSupertype(var type) => type._supertype;
-
-Iterable<ReifiedType> getInterfaces(Interface type) => type._interfaces;
-
-ReifiedType subst(ReifiedType type, List<ReifiedType> arguments,
-    List<ReifiedType> parameters) {
-  return type._subst(arguments, parameters);
-}
-
-// TODO(ahe): Do we need ReifiedNullType?
-
-ReifiedType _intersection(ReifiedType a, ReifiedType b) {
-  if (a == null) return b;
-  if (b == null) return a;
-  if (a == b) return a;
-  return new Intersection(a, b);
-}
-
-enum Kind {
-  Bottom,
-  Dynamic,
-  Function,
-  Interface,
-  Intersection,
-  Variable,
-  Void,
-}
-
-abstract class ReifiedType {
-  // TODO(ahe): Should this be a getter to save memory? Which is faster?
-  final Kind _kind;
-
-  const ReifiedType(this._kind);
-
-  bool get _isDynamic => _kind == Kind.Dynamic;
-
-  bool get _isFunction => _kind == Kind.Function;
-
-  bool get _isInterface => _kind == Kind.Interface;
-
-  bool get _isIntersection => _kind == Kind.Intersection;
-
-  bool get _isVariable => _kind == Kind.Variable;
-
-  bool get _isVoid => _kind == Kind.Void;
-
-  bool get _isObject => false;
-
-  /// Returns true if [this] is more specific than [type].
-  bool _isMoreSpecificThan(ReifiedType type);
-
-  /// Performs the substitution `[arguments[i]/parameters[i]]this`.
-  ///
-  /// The notation is known from this lambda calculus rule:
-  ///
-  ///     (lambda x.e0)e1 -> [e1/x]e0.
-  ///
-  /// Invariant: There must be the same number of [arguments] and [parameters].
-  ReifiedType _subst(List<ReifiedType> arguments, List<ReifiedType> parameters);
-
-  /// Returns true if [this] is a subtype of [type].
-  bool _isSubtypeOf(ReifiedType type) {
-    return _subst(const <ReifiedType>[const Bottom()],
-        const <ReifiedType>[const Dynamic()])._isMoreSpecificThan(type);
-  }
-
-  bool _isAssignableTo(ReifiedType type) {
-    if (type._isDynamic) return true;
-    return this._isSubtypeOf(type) || type._isSubtypeOf(this);
-  }
-}
-
-/// Represents the type `dynamic`.
-class Dynamic extends ReifiedType {
-  const Dynamic() : super(Kind.Dynamic);
-
-  bool _isMoreSpecificThan(ReifiedType type) => type._isDynamic;
-
-  ReifiedType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    int index = 0;
-    for (ReifiedType parameter in parameters) {
-      if (parameter._isDynamic) return arguments[index];
-      index++;
-    }
-    return this;
-  }
-
-  String toString() => "dynamic";
-}
-
-/// Represents the bottom type.
-class Bottom extends ReifiedType {
-  const Bottom() : super(Kind.Bottom);
-
-  bool _isMoreSpecificThan(ReifiedType type) => true;
-
-  ReifiedType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    return this;
-  }
-
-  String toString() => "<bottom>";
-}
-
-/// Represents the type `void`.
-class Void extends ReifiedType {
-  const Void() : super(Kind.Void);
-
-  bool _isMoreSpecificThan(ReifiedType type) {
-    // `void` isn't more specific than anything but itself.
-    return type._isVoid;
-  }
-
-  bool _isSubtypeOf(ReifiedType type) {
-    // `void` isn't the subtype of anything besides `dynamic` and itself.
-    return type._isVoid || type._isDynamic;
-  }
-
-  ReifiedType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    return this;
-  }
-
-  String toString() => "void";
-}
-
-/// Represents an interface type. That is, the type of any class.
-///
-/// For example, the type
-///
-///     String
-///
-/// Would be represented as:
-///
-///    new Interface(stringDeclaration);
-///
-/// Where `stringDeclaration` is an instance of [Class] which contains
-/// information about [String]'s supertype and implemented interfaces.
-///
-/// A parameterized type, for example:
-///
-///     Box<int>
-///
-/// Would be represented as:
-///
-///     new Interface(boxDeclaration,
-///         [new Interface(intDeclaration)]);
-///
-/// Implementation notes and considerations:
-///
-/// * It's possible that we want to split this class in two to save memory: one
-///   for non-generic classes and one for generic classes. Only the latter
-///   would need [_typeArguments]. However, this must be weighed against the
-///   additional polymorphism.
-/// * Generally, we don't canonicalize types. However, simple types like `new
-///   Interface(intDeclaration)` should be canonicalized to save
-///   memory. Precisely how this canonicalization will happen is TBD, but it
-///   may simply be by using compile-time constants.
-class Interface extends ReifiedType implements Type {
-  final Class _declaration;
-
-  final List<ReifiedType> _typeArguments;
-
-  const Interface(this._declaration,
-      [this._typeArguments = const <ReifiedType>[]])
-      : super(Kind.Interface);
-
-  bool get _isObject => _declaration.supertype == null;
-
-  Interface get _supertype {
-    return _declaration.supertype
-        ?._subst(_typeArguments, _declaration.variables);
-  }
-
-  Iterable<Interface> get _interfaces {
-    return _declaration.interfaces.map((Interface type) {
-      return type._subst(_typeArguments, _declaration.variables);
-    });
-  }
-
-  FunctionType get _callableType {
-    return _declaration.callableType
-        ?._subst(_typeArguments, _declaration.variables);
-  }
-
-  bool _isMoreSpecificThan(ReifiedType type) {
-    if (type._isDynamic) return true;
-    // Intersection types can only occur as the result of calling
-    // [asInstanceOf], they should never be passed in to this method.
-    assert(!type._isIntersection);
-    if (type._isFunction) {
-      return _callableType?._isMoreSpecificThan(type) ?? false;
-    }
-    if (!type._isInterface) return false;
-    if (this == type) return true;
-    ReifiedType supertype = asInstanceOfType(type);
-    if (supertype == null) {
-      // Special case: A callable class is a subtype of [Function], regardless
-      // if it implements [Function]. It isn't more specific than
-      // [Function]. The type representing [Function] is the supertype of
-      // `declaration.callableType`.
-      return _declaration.callableType?._supertype?._isSubtypeOf(type) ?? false;
-    }
-    if (type == supertype) return true;
-    switch (supertype._kind) {
-      case Kind.Dynamic:
-      case Kind.Variable:
-        // Shouldn't happen. See switch in [asInstanceOf].
-        throw "internal error: $supertype";
-
-      case Kind.Interface:
-        Interface s = supertype;
-        Interface t = type;
-        for (int i = 0; i < s._typeArguments.length; i++) {
-          if (!s._typeArguments[i]._isMoreSpecificThan(t._typeArguments[i])) {
-            return false;
-          }
-        }
-        return true;
-
-      case Kind.Intersection:
-        return supertype._isMoreSpecificThan(type);
-
-      default:
-        throw "Internal error: unhandled kind '${type._kind}'";
-    }
-  }
-
-  bool _isSubtypeOf(ReifiedType type) {
-    if (type._isInterface) {
-      Interface interface = type;
-      if (interface._declaration != this._declaration) {
-        // This addition to the specified rules allows us to handle cases like
-        //     class D extends A<dynamic> {}
-        //     new D() is A<A>
-        // where directly going to `isMoreSpecific` would leave `dynamic` in the
-        // result of `asInstanceOf(A)` instead of bottom.
-        ReifiedType that = asInstanceOf(interface._declaration);
-        if (that != null) {
-          return that._isSubtypeOf(type);
-        }
-      }
-    }
-    return super._isSubtypeOf(type) ||
-        (_callableType?._isSubtypeOf(type) ?? false);
-  }
-
-  /// Returns [this] translated to [type] if [type] is a supertype of
-  /// [this]. Otherwise null.
-  ///
-  /// For example, given:
-  ///
-  ///     class Box<T> {}
-  ///     class BeatBox extends Box<Beat> {}
-  ///     class Beat {}
-  ///
-  /// We have:
-  ///
-  ///     [[BeatBox]].asInstanceOf([[Box]]) -> [[Box<Beat>]].
-  ReifiedType asInstanceOf(Class other) {
-    if (_declaration == other) return this;
-    ReifiedType result = _declaration.supertype
-        ?._subst(_typeArguments, _declaration.variables)
-        ?.asInstanceOf(other);
-    for (Interface interface in _declaration.interfaces) {
-      result = _intersection(
-          result,
-          interface
-              ._subst(_typeArguments, _declaration.variables)
-              .asInstanceOf(other));
-    }
-    return result;
-  }
-
-  ReifiedType asInstanceOfType(Interface type) {
-    return asInstanceOf(type._declaration);
-  }
-
-  Interface _subst(List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    List<ReifiedType> copy;
-    int index = 0;
-    for (ReifiedType typeArgument in _typeArguments) {
-      ReifiedType substitution = typeArgument._subst(arguments, parameters);
-      if (substitution != typeArgument) {
-        if (copy == null) {
-          copy = new List<ReifiedType>.from(_typeArguments);
-        }
-        copy[index] = substitution;
-      }
-      index++;
-    }
-    return copy == null ? this : new Interface(_declaration, copy);
-  }
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write(_declaration.name);
-    if (_typeArguments.isNotEmpty) {
-      sb.write("<");
-      sb.writeAll(_typeArguments, ", ");
-      sb.write(">");
-    }
-    return "$sb";
-  }
-
-  int get hashCode {
-    int code = 23;
-    code = (71 * code + _declaration.hashCode) & 0x3fffffff;
-    for (ReifiedType typeArgument in _typeArguments) {
-      code = (71 * code + typeArgument.hashCode) & 0x3fffffff;
-    }
-    return code;
-  }
-
-  bool operator ==(other) {
-    if (other is Interface) {
-      if (_declaration != other._declaration) return false;
-      if (identical(_typeArguments, other._typeArguments)) return true;
-      assert(_typeArguments.length == other._typeArguments.length);
-      for (int i = 0; i < _typeArguments.length; i++) {
-        if (_typeArguments[i] != other._typeArguments[i]) {
-          return false;
-        }
-      }
-      return true;
-    }
-    return false;
-  }
-}
-
-/// Represents the intersection type of [typeA] and [typeB]. The intersection
-/// type represents a type that is a subtype of both [typeA] and [typeB].
-///
-/// This type is produced when a class implements the same interface twice with
-/// different type arguments. For example:
-///
-///     abstract class MyNumberList implements List<int>, List<double> {}
-///
-/// Can lead to this intersection type:
-///
-///     new Intersection([[List<int>]], [[List<double>]])
-///
-/// For example,
-///
-///     [[MyNumberList]].asInstanceOf([[List]]) ->
-///         new Intersection([[List<int>]], [[List<double>]])
-///
-/// Note: sometimes, people confuse this with union types. However the union
-/// type of `A` and `B` would be anything that is a subtype of either `A` or
-/// `B`.
-///
-/// See [Intersection types]
-/// (https://en.wikipedia.org/wiki/Type_system#Intersection_types).
-class Intersection extends ReifiedType {
-  final ReifiedType typeA;
-  final ReifiedType typeB;
-
-  const Intersection(this.typeA, this.typeB) : super(Kind.Intersection);
-
-  bool _isMoreSpecificThan(ReifiedType type) {
-    // In the above example, `MyNumberList` is a subtype of List<int> *or*
-    // List<double>.
-    return typeA._isMoreSpecificThan(type) || typeB._isMoreSpecificThan(type);
-  }
-
-  ReifiedType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    ReifiedType aSubstitution = typeA._subst(arguments, parameters);
-    ReifiedType bSubstitution = typeB._subst(arguments, parameters);
-    return (aSubstitution == typeA && bSubstitution == typeB)
-        ? this
-        : _intersection(aSubstitution, bSubstitution);
-  }
-
-  String toString() => "{ $typeA, $typeB }";
-}
-
-/// Represents a type variable aka type parameter.
-///
-/// For example, this class:
-///
-///     class Box<T> {}
-///
-/// Defines one type variable. In the type `Box<int>`, there are no type
-/// variables.  However, `int` is a type argument to the type
-/// parameter/variable `T`.
-class TypeVariable extends ReifiedType {
-  final int _id;
-
-  // TODO(ahe): Do we need to reify bounds?
-  ReifiedType bound;
-
-  TypeVariable(this._id) : super(Kind.Variable);
-
-  bool _isMoreSpecificThan(ReifiedType type) {
-    if (type == this || type._isDynamic || type._isObject) return true;
-    // The bounds of a type variable may contain a cycle, such as:
-    //
-    //     class C<T extends S, S extends T> {}
-    //
-    // We use the [tortoise and hare algorithm]
-    // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
-    // handle cycles.
-    ReifiedType tortoise = bound;
-    if (tortoise == type) return true;
-    ReifiedType hare = getBoundOrNull(bound);
-    while (tortoise != hare) {
-      tortoise = getBoundOrNull(tortoise);
-      if (tortoise == type) return true;
-      hare = getBoundOrNull(getBoundOrNull(hare));
-    }
-    // Here we know that `tortoise == hare`. Either they're both `null` or we
-    // detected a cycle.
-    if (tortoise != null) {
-      // There was a cycle of type variables in the bounds, but it didn't
-      // involve [type]. The variable [tortoise] visited all the type variables
-      // in the cycle (at least once), and each time we compared it to [type].
-      return false;
-    }
-    // There are no cycles and it's safe to recurse on [bound].
-    return bound._isMoreSpecificThan(type);
-  }
-
-  ReifiedType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    int index = 0;
-    for (ReifiedType parameter in parameters) {
-      if (this == parameter) return arguments[index];
-      index++;
-    }
-    return this;
-  }
-
-  String toString() => "#$_id";
-}
-
-/// Represents a function type.
-class FunctionType extends ReifiedType {
-  /// Normally, the [Interface] representing [Function]. But an
-  /// implementation-specific subtype of [Function] may also be used.
-  final ReifiedType _supertype;
-
-  final ReifiedType _returnType;
-
-  /// Encodes number of optional parameters and if the optional parameters are
-  /// named.
-  final int _data;
-
-  /// Encodes the argument types. Positional parameters use one element, the
-  /// type; named parameters use two, the name [String] and type. Named
-  /// parameters must be sorted by name.
-  final List _encodedParameters;
-
-  static const FunctionTypeRelation subtypeRelation =
-      const FunctionSubtypeRelation();
-
-  static const FunctionTypeRelation moreSpecificRelation =
-      const FunctionMoreSpecificRelation();
-
-  const FunctionType(
-      this._supertype, this._returnType, this._data, this._encodedParameters)
-      : super(Kind.Function);
-
-  bool get hasNamedParameters => (_data & 1) == 1;
-
-  int get optionalParameters => _data >> 1;
-
-  int get parameters {
-    return hasNamedParameters
-        ? _encodedParameters.length - optionalParameters
-        : _encodedParameters.length;
-  }
-
-  int get requiredParameters {
-    return hasNamedParameters
-        ? _encodedParameters.length - optionalParameters * 2
-        : _encodedParameters.length - optionalParameters;
-  }
-
-  bool _isSubtypeOf(ReifiedType type) => subtypeRelation.areRelated(this, type);
-
-  bool _isMoreSpecificThan(ReifiedType type) {
-    return moreSpecificRelation.areRelated(this, type);
-  }
-
-  FunctionType _subst(
-      List<ReifiedType> arguments, List<ReifiedType> parameters) {
-    List substitutedParameters;
-    int positionalParameters =
-        hasNamedParameters ? requiredParameters : this.parameters;
-    for (int i = 0; i < _encodedParameters.length; i++) {
-      if (i >= positionalParameters) {
-        // Skip the name of a named parameter.
-        i++;
-      }
-      ReifiedType type = _encodedParameters[i];
-      ReifiedType substitution = type._subst(arguments, parameters);
-      if (substitution != type) {
-        if (substitutedParameters == null) {
-          substitutedParameters = new List.from(_encodedParameters);
-        }
-        substitutedParameters[i] = substitution;
-      }
-    }
-    ReifiedType substitutedReturnType =
-        _returnType._subst(arguments, parameters);
-    if (substitutedParameters == null) {
-      if (_returnType == substitutedReturnType) return this;
-      substitutedParameters = _encodedParameters;
-    }
-    return new FunctionType(
-        _supertype, substitutedReturnType, _data, substitutedParameters);
-  }
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write("(");
-    bool first = true;
-    for (int i = 0; i < requiredParameters; i++) {
-      if (!first) {
-        sb.write(", ");
-      }
-      sb.write(_encodedParameters[i]);
-      first = false;
-    }
-    if (requiredParameters != parameters) {
-      if (!first) {
-        sb.write(", ");
-      }
-      if (hasNamedParameters) {
-        sb.write("{");
-        first = true;
-        for (int i = requiredParameters;
-            i < _encodedParameters.length;
-            i += 2) {
-          if (!first) {
-            sb.write(", ");
-          }
-          sb.write(_encodedParameters[i + 1]);
-          sb.write(" ");
-          sb.write(_encodedParameters[i]);
-          first = false;
-        }
-        sb.write("}");
-      } else {
-        sb.write("[");
-        first = true;
-        for (int i = requiredParameters; i < _encodedParameters.length; i++) {
-          if (!first) {
-            sb.write(", ");
-          }
-          sb.write(_encodedParameters[i]);
-          first = false;
-        }
-        sb.write("]");
-      }
-    }
-    sb.write(") -> ");
-    sb.write(_returnType);
-    return "$sb";
-  }
-}
-
-abstract class FunctionTypeRelation {
-  const FunctionTypeRelation();
-
-  bool areRelated(FunctionType self, ReifiedType type, {bool isMoreSpecific}) {
-    if (!type._isFunction) {
-      return arePartsRelated(self._supertype, type);
-    }
-    FunctionType other = type;
-    if (!other._returnType._isVoid) {
-      if (!arePartsRelated(self._returnType, other._returnType)) return false;
-    }
-    int positionalParameters =
-        self.hasNamedParameters ? self.requiredParameters : self.parameters;
-    int otherPositionalParameters =
-        other.hasNamedParameters ? other.requiredParameters : other.parameters;
-    if (self.requiredParameters > other.requiredParameters) return false;
-    if (positionalParameters < otherPositionalParameters) return false;
-
-    for (int i = 0; i < otherPositionalParameters; i++) {
-      if (!arePartsRelated(
-          self._encodedParameters[i], other._encodedParameters[i])) {
-        return false;
-      }
-    }
-
-    if (!other.hasNamedParameters) return true;
-
-    int j = positionalParameters;
-    for (int i = otherPositionalParameters;
-        i < other._encodedParameters.length;
-        i += 2) {
-      String name = other._encodedParameters[i];
-      for (; j < self._encodedParameters.length; j += 2) {
-        if (self._encodedParameters[j] == name) break;
-      }
-      if (j == self._encodedParameters.length) return false;
-      if (!arePartsRelated(
-          self._encodedParameters[j + 1], other._encodedParameters[i + 1])) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool arePartsRelated(ReifiedType a, ReifiedType b);
-}
-
-class FunctionSubtypeRelation extends FunctionTypeRelation {
-  const FunctionSubtypeRelation();
-
-  bool arePartsRelated(ReifiedType a, ReifiedType b) => a._isAssignableTo(b);
-}
-
-class FunctionMoreSpecificRelation extends FunctionTypeRelation {
-  const FunctionMoreSpecificRelation();
-
-  bool arePartsRelated(ReifiedType a, ReifiedType b) =>
-      a._isMoreSpecificThan(b);
-}
-
-/// If [type] is a type variable, return its bound. Otherwise `null`.
-ReifiedType getBoundOrNull(ReifiedType type) {
-  if (type == null) return null;
-  if (!type._isVariable) return null;
-  TypeVariable tv = type;
-  return tv.bound;
-}
diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart
index 9389b21..bca2e52 100644
--- a/pkg/kernel/test/binary/library_flags_test.dart
+++ b/pkg/kernel/test/binary/library_flags_test.dart
@@ -4,6 +4,8 @@
 
 import 'utils.dart';
 
+// ignore_for_file: DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
+
 /// Test that library flags (external, synthetic)
 /// are serialized and read correctly.
 main() {
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 0d53973..d6be1b2 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -309,7 +309,8 @@
         .map((name) => new TypeParameter(name, coreTypes.objectLegacyRawType))
         .toList();
     var typeParameterTypes = typeParameters
-        .map((parameter) => new TypeParameterType(parameter))
+        .map(
+            (parameter) => new TypeParameterType(parameter, Nullability.legacy))
         .toList();
     var supertype =
         extends_ != null ? extends_(typeParameterTypes) : objectSuper;
@@ -527,7 +528,7 @@
     var a = addGenericClass('A', ['T', 'U']);
 
     var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
-    var bTT = new TypeParameterType(bT);
+    var bTT = new TypeParameterType(bT, Nullability.legacy);
     var b = addClass(new Class(
         name: 'B',
         typeParameters: [bT],
@@ -555,7 +556,7 @@
     var a = addGenericClass('A', ['T', 'U']);
 
     var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
-    var bTT = new TypeParameterType(bT);
+    var bTT = new TypeParameterType(bT, Nullability.legacy);
     var b = addClass(new Class(
         name: 'B',
         typeParameters: [bT],
@@ -589,7 +590,7 @@
     var a = addGenericClass('A', ['T', 'U']);
 
     var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
-    var bTT = new TypeParameterType(bT);
+    var bTT = new TypeParameterType(bT, Nullability.legacy);
     var b = addClass(new Class(
         name: 'B',
         typeParameters: [bT],
@@ -1201,7 +1202,7 @@
     var a = addGenericClass('A', ['T', 'U']);
 
     var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
-    var bTT = new TypeParameterType(bT);
+    var bTT = new TypeParameterType(bT, Nullability.legacy);
     var b = addClass(new Class(
         name: 'B',
         typeParameters: [bT],
@@ -1212,11 +1213,11 @@
 class B<T*> extends self::A<self::B::T*, core::bool*> {}
 ''');
 
-    var b_int = new InterfaceType(b, [int]);
+    var b_int = new InterfaceType(b, Nullability.legacy, [int]);
     expect(hierarchy.getTypeAsInstanceOf(b_int, a),
-        new InterfaceType(a, [int, bool]));
+        new InterfaceType(a, Nullability.legacy, [int, bool]));
     expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass),
-        new InterfaceType(objectClass));
+        new InterfaceType(objectClass, Nullability.legacy));
   }
 
   void _assertOverridePairs(Class class_, List<String> expected) {
diff --git a/pkg/kernel/test/metadata_test.dart b/pkg/kernel/test/metadata_test.dart
index d544535..87ed4e9 100644
--- a/pkg/kernel/test/metadata_test.dart
+++ b/pkg/kernel/test/metadata_test.dart
@@ -45,7 +45,7 @@
     if (parent.typeParameters.isEmpty) {
       return const VoidType();
     }
-    return new TypeParameterType(parent.typeParameters[0]);
+    return new TypeParameterType(parent.typeParameters[0], Nullability.legacy);
   }
   return getTypeForMetadata(parent);
 }
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index 9603db8..ad2354e 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -329,10 +329,14 @@
           name: "/* T Function<T>(T Function<T>()); */",
           node: new ExpressionStatement(new TypeLiteral(new FunctionType(
               [
-                new FunctionType([], new TypeParameterType(innerParam),
+                new FunctionType(
+                    [],
+                    new TypeParameterType(innerParam, Nullability.legacy),
+                    Nullability.legacy,
                     typeParameters: [innerParam])
               ],
-              new TypeParameterType(outterParam),
+              new TypeParameterType(outterParam, Nullability.legacy),
+              Nullability.legacy,
               typeParameters: [outterParam]))),
           expectation: ""
               "(expr (type (-> (\"T^0\") ((dynamic)) ((dynamic)) "
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index e4b88ae..cb4856f 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.dart
@@ -165,11 +165,11 @@
         } else if (target is Class) {
           List<DartType> typeArguments = parseOptionalTypeArgumentList();
           Nullability nullability = parseOptionalNullability();
-          return new InterfaceType(target, typeArguments, nullability);
+          return new InterfaceType(target, nullability, typeArguments);
         } else if (target is Typedef) {
           List<DartType> typeArguments = parseOptionalTypeArgumentList();
           Nullability nullability = parseOptionalNullability();
-          return new TypedefType(target, typeArguments, nullability);
+          return new TypedefType(target, nullability, typeArguments);
         } else if (target is TypeParameter) {
           Nullability nullability = parseOptionalNullability();
           DartType promotedBound;
@@ -183,7 +183,7 @@
             default:
               break;
           }
-          return new TypeParameterType(target, promotedBound, nullability);
+          return new TypeParameterType(target, nullability, promotedBound);
         }
         return fail("Unexpected lookup result for $name: $target");
 
@@ -194,8 +194,8 @@
         consumeString('=>');
         Nullability nullability = parseOptionalNullability();
         var returnType = parseType();
-        return new FunctionType(parameters, returnType,
-            namedParameters: namedParameters, nullability: nullability);
+        return new FunctionType(parameters, returnType, nullability,
+            namedParameters: namedParameters);
 
       case Token.LeftAngle:
         var typeParameters = parseAndPushTypeParameterList();
@@ -206,10 +206,8 @@
         Nullability nullability = parseOptionalNullability();
         var returnType = parseType();
         popTypeParameters(typeParameters);
-        return new FunctionType(parameters, returnType,
-            typeParameters: typeParameters,
-            namedParameters: namedParameters,
-            nullability: nullability);
+        return new FunctionType(parameters, returnType, nullability,
+            typeParameters: typeParameters, namedParameters: namedParameters);
 
       default:
         return fail('Unexpected token: $tokenText');
@@ -303,7 +301,8 @@
       scanToken();
       typeParameter.bound = parseType();
     } else {
-      typeParameter.bound = new InterfaceType(lookupType('Object'));
+      typeParameter.bound =
+          new InterfaceType(lookupType('Object'), Nullability.legacy);
     }
     return typeParameter;
   }
@@ -329,8 +328,8 @@
     return name.length == 1
         ? typeParameters.putIfAbsent(
             name,
-            () => new TypeParameter(
-                name, new InterfaceType(lookupClass('Object'))))
+            () => new TypeParameter(name,
+                new InterfaceType(lookupClass('Object'), Nullability.legacy)))
         : lookupClass(name);
   }
 
diff --git a/pkg/kernel/test/typedef_unalias_test.dart b/pkg/kernel/test/typedef_unalias_test.dart
index f9d448b..4f70f04 100644
--- a/pkg/kernel/test/typedef_unalias_test.dart
+++ b/pkg/kernel/test/typedef_unalias_test.dart
@@ -17,18 +17,21 @@
   harnessTest('`Foo` where typedef Foo = C', (TestHarness harness) {
     var foo = new Typedef('Foo', harness.otherLegacyRawType);
     harness.enclosingLibrary.addTypedef(foo);
-    var type = new TypedefType(foo);
+    var type = new TypedefType(foo, Nullability.legacy);
     expect(type.unalias, equals(harness.otherLegacyRawType));
   });
   harnessTest('`Foo<Obj>` where typedef Foo<T> = C<T>', (TestHarness harness) {
     var param = harness.makeTypeParameter('T');
-    var foo = new Typedef('Foo',
-        new InterfaceType(harness.otherClass, [new TypeParameterType(param)]),
+    var foo = new Typedef(
+        'Foo',
+        new InterfaceType(harness.otherClass, Nullability.legacy,
+            [new TypeParameterType(param, Nullability.legacy)]),
         typeParameters: [param]);
     harness.enclosingLibrary.addTypedef(foo);
-    var input = new TypedefType(foo, [harness.objectLegacyRawType]);
-    var expected =
-        new InterfaceType(harness.otherClass, [harness.objectLegacyRawType]);
+    var input =
+        new TypedefType(foo, Nullability.legacy, [harness.objectLegacyRawType]);
+    var expected = new InterfaceType(
+        harness.otherClass, Nullability.legacy, [harness.objectLegacyRawType]);
     expect(input.unalias, equals(expected));
   });
   harnessTest('`Bar<Obj>` where typedef Bar<T> = Foo<T>, Foo<T> = C<T>',
@@ -36,32 +39,37 @@
     var fooParam = harness.makeTypeParameter('T');
     var foo = new Typedef(
         'Foo',
-        new InterfaceType(
-            harness.otherClass, [new TypeParameterType(fooParam)]),
+        new InterfaceType(harness.otherClass, Nullability.legacy,
+            [new TypeParameterType(fooParam, Nullability.legacy)]),
         typeParameters: [fooParam]);
     var barParam = harness.makeTypeParameter('T');
     var bar = new Typedef(
-        'Bar', new TypedefType(foo, [new TypeParameterType(barParam)]),
+        'Bar',
+        new TypedefType(foo, Nullability.legacy,
+            [new TypeParameterType(barParam, Nullability.legacy)]),
         typeParameters: [barParam]);
     harness.enclosingLibrary.addTypedef(foo);
     harness.enclosingLibrary.addTypedef(bar);
-    var input = new TypedefType(bar, [harness.objectLegacyRawType]);
-    var expected =
-        new InterfaceType(harness.otherClass, [harness.objectLegacyRawType]);
+    var input =
+        new TypedefType(bar, Nullability.legacy, [harness.objectLegacyRawType]);
+    var expected = new InterfaceType(
+        harness.otherClass, Nullability.legacy, [harness.objectLegacyRawType]);
     expect(input.unalias, equals(expected));
   });
   harnessTest('`Foo<Foo<C>>` where typedef Foo<T> = C<T>',
       (TestHarness harness) {
     var param = harness.makeTypeParameter('T');
-    var foo = new Typedef('Foo',
-        new InterfaceType(harness.otherClass, [new TypeParameterType(param)]),
+    var foo = new Typedef(
+        'Foo',
+        new InterfaceType(harness.otherClass, Nullability.legacy,
+            [new TypeParameterType(param, Nullability.legacy)]),
         typeParameters: [param]);
     harness.enclosingLibrary.addTypedef(foo);
-    var input = new TypedefType(foo, [
-      new TypedefType(foo, [harness.objectLegacyRawType])
+    var input = new TypedefType(foo, Nullability.legacy, [
+      new TypedefType(foo, Nullability.legacy, [harness.objectLegacyRawType])
     ]);
-    var expected = new InterfaceType(harness.otherClass, [
-      new TypedefType(foo, [harness.objectLegacyRawType])
+    var expected = new InterfaceType(harness.otherClass, Nullability.legacy, [
+      new TypedefType(foo, Nullability.legacy, [harness.objectLegacyRawType])
     ]);
     expect(input.unalias, equals(expected));
   });
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 56498c6..c69b044 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -93,15 +93,15 @@
       matches("Type parameter '$tvarRegexp' referenced out of scope,"
           " parent is: 'null'\\."), (TestHarness test) {
     var parameter = test.makeTypeParameter();
-    test.addNode(
-        ListLiteral([], typeArgument: new TypeParameterType(parameter)));
+    test.addNode(ListLiteral([],
+        typeArgument: new TypeParameterType(parameter, Nullability.legacy)));
   });
   negativeTest(
       'Class type parameter from another class',
       "Type parameter 'test_lib::OtherClass::OtherT' referenced out of scope,"
           " parent is: 'test_lib::OtherClass'.", (TestHarness test) {
-    test.addNode(
-        TypeLiteral(new TypeParameterType(test.otherClass.typeParameters[0])));
+    test.addNode(TypeLiteral(new TypeParameterType(
+        test.otherClass.typeParameters[0], Nullability.legacy)));
   });
   negativeTest(
       'Class type parameter in static method',
@@ -110,8 +110,9 @@
     test.addNode(Procedure(
         new Name('bar'),
         ProcedureKind.Method,
-        new FunctionNode(new ReturnStatement(
-            new TypeLiteral(new TypeParameterType(test.classTypeParameter)))),
+        new FunctionNode(new ReturnStatement(new TypeLiteral(
+            new TypeParameterType(
+                test.classTypeParameter, Nullability.legacy)))),
         isStatic: true));
   });
   negativeTest(
@@ -119,8 +120,8 @@
       "Type parameter 'test_lib::TestClass::T' referenced from static context,"
           " parent is: 'test_lib::TestClass'.", (TestHarness test) {
     test.addNode(Field(new Name('field'),
-        initializer:
-            new TypeLiteral(new TypeParameterType(test.classTypeParameter)),
+        initializer: new TypeLiteral(
+            new TypeParameterType(test.classTypeParameter, Nullability.legacy)),
         isStatic: true));
   });
   negativeTest(
@@ -140,29 +141,30 @@
           new Procedure(
               new Name('use'),
               ProcedureKind.Method,
-              new FunctionNode(new ReturnStatement(
-                  new TypeLiteral(new TypeParameterType(parameter)))))
+              new FunctionNode(new ReturnStatement(new TypeLiteral(
+                  new TypeParameterType(parameter, Nullability.legacy)))))
         ]));
   });
   negativeTest(
       'Interface type arity too low',
-      "Type test_lib::OtherClass* provides 0 type arguments"
+      "Type test_lib::OtherClass* provides 0 type arguments,"
           " but the class declares 1 parameters.", (TestHarness test) {
-    test.addNode(TypeLiteral(new InterfaceType(test.otherClass, [])));
+    test.addNode(TypeLiteral(
+        new InterfaceType(test.otherClass, Nullability.legacy, [])));
   });
   negativeTest(
       'Interface type arity too high',
-      "Type test_lib::OtherClass<dynamic, dynamic>* provides 2 type arguments"
+      "Type test_lib::OtherClass<dynamic, dynamic>* provides 2 type arguments,"
           " but the class declares 1 parameters.", (TestHarness test) {
-    test.addNode(TypeLiteral(new InterfaceType(
-        test.otherClass, [new DynamicType(), new DynamicType()])));
+    test.addNode(TypeLiteral(new InterfaceType(test.otherClass,
+        Nullability.legacy, [new DynamicType(), new DynamicType()])));
   });
   negativeTest(
       'Dangling interface type',
       matches("Dangling reference to 'null::#class[0-9]+',"
           " parent is: 'null'\\."), (TestHarness test) {
     var orphan = new Class();
-    test.addNode(TypeLiteral(new InterfaceType(orphan)));
+    test.addNode(TypeLiteral(new InterfaceType(orphan, Nullability.legacy)));
   });
   negativeTest('Dangling field get',
       "Dangling reference to 'null::foo', parent is: 'null'.",
@@ -274,18 +276,22 @@
   });
   positiveTest('Valid typedef Foo = `(C) => void`', (TestHarness test) {
     var typedef_ = new Typedef(
-        'Foo', new FunctionType([test.otherLegacyRawType], const VoidType()));
+        'Foo',
+        new FunctionType(
+            [test.otherLegacyRawType], const VoidType(), Nullability.legacy));
     test.addNode(typedef_);
   });
   positiveTest('Valid typedef Foo = C<dynamic>', (TestHarness test) {
     var typedef_ = new Typedef(
-        'Foo', new InterfaceType(test.otherClass, [const DynamicType()]));
+        'Foo',
+        new InterfaceType(
+            test.otherClass, Nullability.legacy, [const DynamicType()]));
     test.addNode(typedef_);
   });
   positiveTest('Valid typedefs Foo = Bar, Bar = C', (TestHarness test) {
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
-    foo.type = new TypedefType(bar);
+    foo.type = new TypedefType(bar, Nullability.legacy);
     bar.type = test.otherLegacyRawType;
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
@@ -293,16 +299,19 @@
   positiveTest('Valid typedefs Foo = C<Bar>, Bar = C', (TestHarness test) {
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
-    foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]);
+    foo.type = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypedefType(bar, Nullability.legacy)]);
     bar.type = test.otherLegacyRawType;
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
   positiveTest('Valid typedef type in field', (TestHarness test) {
     var typedef_ = new Typedef(
-        'Foo', new FunctionType([test.otherLegacyRawType], const VoidType()));
+        'Foo',
+        new FunctionType(
+            [test.otherLegacyRawType], const VoidType(), Nullability.legacy));
     var field = new Field(new Name('field'),
-        type: new TypedefType(typedef_), isStatic: true);
+        type: new TypedefType(typedef_, Nullability.legacy), isStatic: true);
     test.enclosingLibrary.addTypedef(typedef_);
     test.enclosingLibrary.addMember(field);
   });
@@ -311,7 +320,7 @@
       "The typedef 'typedef Foo = test_lib::Foo;\n'"
           " refers to itself", (TestHarness test) {
     var typedef_ = new Typedef('Foo', null);
-    typedef_.type = new TypedefType(typedef_);
+    typedef_.type = new TypedefType(typedef_, Nullability.legacy);
     test.addNode(typedef_);
   });
   negativeTest(
@@ -319,8 +328,10 @@
       "The typedef 'typedef Foo = (test_lib::Foo) →* void;\n'"
           " refers to itself", (TestHarness test) {
     var typedef_ = new Typedef('Foo', null);
-    typedef_.type =
-        new FunctionType([new TypedefType(typedef_)], const VoidType());
+    typedef_.type = new FunctionType(
+        [new TypedefType(typedef_, Nullability.legacy)],
+        const VoidType(),
+        Nullability.legacy);
     test.addNode(typedef_);
   });
   negativeTest(
@@ -328,7 +339,8 @@
       "The typedef 'typedef Foo = () →* test_lib::Foo;\n'"
           " refers to itself", (TestHarness test) {
     var typedef_ = new Typedef('Foo', null);
-    typedef_.type = new FunctionType([], new TypedefType(typedef_));
+    typedef_.type = new FunctionType(
+        [], new TypedefType(typedef_, Nullability.legacy), Nullability.legacy);
     test.addNode(typedef_);
   });
   negativeTest(
@@ -336,8 +348,8 @@
       "The typedef 'typedef Foo = test_lib::OtherClass<test_lib::Foo>*;\n'"
           " refers to itself", (TestHarness test) {
     var typedef_ = new Typedef('Foo', null);
-    typedef_.type =
-        new InterfaceType(test.otherClass, [new TypedefType(typedef_)]);
+    typedef_.type = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypedefType(typedef_, Nullability.legacy)]);
     test.addNode(typedef_);
   });
   negativeTest(
@@ -346,8 +358,8 @@
           " refers to itself", (TestHarness test) {
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
-    foo.type = new TypedefType(bar);
-    bar.type = new TypedefType(foo);
+    foo.type = new TypedefType(bar, Nullability.legacy);
+    bar.type = new TypedefType(foo, Nullability.legacy);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
@@ -357,8 +369,9 @@
           " refers to itself", (TestHarness test) {
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
-    foo.type = new TypedefType(bar);
-    bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]);
+    foo.type = new TypedefType(bar, Nullability.legacy);
+    bar.type = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypedefType(foo, Nullability.legacy)]);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
@@ -368,8 +381,10 @@
           " refers to itself", (TestHarness test) {
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
-    foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]);
-    bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]);
+    foo.type = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypedefType(bar, Nullability.legacy)]);
+    bar.type = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypedefType(foo, Nullability.legacy)]);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
@@ -378,7 +393,8 @@
     var typedef_ = new Typedef('C0', const DynamicType());
     test.enclosingLibrary.addTypedef(typedef_);
     for (int i = 1; i < 20; ++i) {
-      typedef_ = new Typedef('C$i', new TypedefType(typedef_));
+      typedef_ =
+          new Typedef('C$i', new TypedefType(typedef_, Nullability.legacy));
       test.enclosingLibrary.addTypedef(typedef_);
     }
   });
@@ -390,24 +406,29 @@
     test.enclosingLibrary.addTypedef(typedef_);
     var first = typedef_;
     for (int i = 1; i < 20; ++i) {
-      typedef_ = new Typedef('C$i', new TypedefType(typedef_));
+      typedef_ =
+          new Typedef('C$i', new TypedefType(typedef_, Nullability.legacy));
       test.enclosingLibrary.addTypedef(typedef_);
     }
-    first.type = new TypedefType(typedef_);
+    first.type = new TypedefType(typedef_, Nullability.legacy);
   });
   positiveTest('Valid typedef Foo<T extends C> = C<T>', (TestHarness test) {
     var param = new TypeParameter('T', test.otherLegacyRawType);
-    var foo = new Typedef('Foo',
-        new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
+    var foo = new Typedef(
+        'Foo',
+        new InterfaceType(test.otherClass, Nullability.legacy,
+            [new TypeParameterType(param, Nullability.legacy)]),
         typeParameters: [param]);
     test.addNode(foo);
   });
   positiveTest('Valid typedef Foo<T extends C<T>> = C<T>', (TestHarness test) {
     var param = new TypeParameter('T', test.otherLegacyRawType);
-    param.bound =
-        new InterfaceType(test.otherClass, [new TypeParameterType(param)]);
-    var foo = new Typedef('Foo',
-        new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
+    param.bound = new InterfaceType(test.otherClass, Nullability.legacy,
+        [new TypeParameterType(param, Nullability.legacy)]);
+    var foo = new Typedef(
+        'Foo',
+        new InterfaceType(test.otherClass, Nullability.legacy,
+            [new TypeParameterType(param, Nullability.legacy)]),
         typeParameters: [param]);
     test.addNode(foo);
   });
@@ -417,9 +438,12 @@
     var foo =
         new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]);
     var barParam = new TypeParameter('T', null);
-    barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]);
-    var bar = new Typedef('Bar',
-        new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]),
+    barParam.bound = new TypedefType(foo, Nullability.legacy,
+        [new TypeParameterType(barParam, Nullability.legacy)]);
+    var bar = new Typedef(
+        'Bar',
+        new InterfaceType(test.otherClass, Nullability.legacy,
+            [new TypeParameterType(barParam, Nullability.legacy)]),
         typeParameters: [barParam]);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
@@ -432,11 +456,15 @@
     var foo =
         new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]);
     var barParam = new TypeParameter('T', null);
-    barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]);
-    var bar = new Typedef('Bar',
-        new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]),
+    barParam.bound = new TypedefType(foo, Nullability.legacy,
+        [new TypeParameterType(barParam, Nullability.legacy)]);
+    var bar = new Typedef(
+        'Bar',
+        new InterfaceType(test.otherClass, Nullability.legacy,
+            [new TypeParameterType(barParam, Nullability.legacy)]),
         typeParameters: [barParam]);
-    fooParam.bound = new TypedefType(bar, [new TypeParameterType(fooParam)]);
+    fooParam.bound = new TypedefType(bar, Nullability.legacy,
+        [new TypeParameterType(fooParam, Nullability.legacy)]);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
@@ -446,21 +474,24 @@
           "test_lib::OtherClass<T*>*;\n'"
           " refers to itself", (TestHarness test) {
     var param = new TypeParameter('T', null);
-    var foo = new Typedef('Foo',
-        new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
+    var foo = new Typedef(
+        'Foo',
+        new InterfaceType(test.otherClass, Nullability.legacy,
+            [new TypeParameterType(param, Nullability.legacy)]),
         typeParameters: [param]);
-    param.bound = new TypedefType(foo, [const DynamicType()]);
+    param.bound =
+        new TypedefType(foo, Nullability.legacy, [const DynamicType()]);
     test.addNode(foo);
   });
   negativeTest(
       'Typedef arity error',
-      "The typedef type test_lib::Foo provides 0 type arguments"
+      "The typedef type test_lib::Foo provides 0 type arguments,"
           " but the typedef declares 1 parameters.", (TestHarness test) {
     var param = test.makeTypeParameter('T');
     var foo =
         new Typedef('Foo', test.otherLegacyRawType, typeParameters: [param]);
     var field = new Field(new Name('field'),
-        type: new TypedefType(foo, []), isStatic: true);
+        type: new TypedefType(foo, Nullability.legacy, []), isStatic: true);
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addMember(field);
   });
@@ -470,7 +501,7 @@
           ", parent is: 'null'", (TestHarness test) {
     var foo = new Typedef('Foo', test.otherLegacyRawType, typeParameters: []);
     var field = new Field(new Name('field'),
-        type: new TypedefType(foo, []), isStatic: true);
+        type: new TypedefType(foo, Nullability.legacy, []), isStatic: true);
     test.enclosingLibrary.addMember(field);
   });
   negativeTest('Non-static top-level field',
@@ -563,7 +594,7 @@
     stubLibrary.name = 'dart.core';
     objectClass = new Class(name: 'Object');
     objectLegacyRawType =
-        new InterfaceType(objectClass, const <DartType>[], Nullability.legacy);
+        new InterfaceType(objectClass, Nullability.legacy, const <DartType>[]);
     stubLibrary.addClass(objectClass);
     enclosingLibrary = new Library(Uri.parse('file://test.dart'));
     component.libraries.add(enclosingLibrary..parent = component);
@@ -574,7 +605,7 @@
         typeParameters: [classTypeParameter],
         supertype: objectClass.asRawSupertype);
     enclosingLegacyRawType = new InterfaceType(enclosingClass,
-        const <DartType>[const DynamicType()], Nullability.legacy);
+        Nullability.legacy, const <DartType>[const DynamicType()]);
     enclosingLibrary.addClass(enclosingClass);
     enclosingMember = new Procedure(new Name('test'), ProcedureKind.Method,
         new FunctionNode(new EmptyStatement()));
@@ -584,7 +615,7 @@
         typeParameters: [makeTypeParameter('OtherT')],
         supertype: objectClass.asRawSupertype);
     otherLegacyRawType = new InterfaceType(
-        otherClass, const <DartType>[const DynamicType()], Nullability.legacy);
+        otherClass, Nullability.legacy, const <DartType>[const DynamicType()]);
     enclosingLibrary.addClass(otherClass);
   }
 }
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 35b8c5e..31872c2 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -99,23 +99,36 @@
 /// Information exposed to the migration client about the location in source
 /// code that led an edge to be introduced into the nullability graph.
 abstract class EdgeOriginInfo {
+  /// If the proximate cause of the edge being introduced into the graph
+  /// corresponds to the type of an element in an already migrated-library, the
+  /// corresponding element; otherwise `null`.
+  ///
+  /// Note that either [node] or [element] will always be non-null.
+  Element get element;
+
   /// The kind of origin represented by this info.
   EdgeOriginKind get kind;
 
-  /// The AST node that led the edge to be introduced into the nullability
-  /// graph.
+  /// If the proximate cause of the edge being introduced into the graph
+  /// corresponds to an AST node in a source file that is being migrated, the
+  /// corresponding AST node; otherwise `null`.
+  ///
+  /// Note that either [node] or [element] will always be non-null.
   AstNode get node;
 
-  /// The source file that [node] appears in.
+  /// If [node] is non-null, the source file that it appears in.  Otherwise
+  /// `null`.
   Source get source;
 }
 
 /// An enumeration of the various kinds of edge origins created by the migration
 /// engine.
 enum EdgeOriginKind {
+  alreadyMigratedType,
   alwaysNullableType,
   compoundAssignment,
   defaultValue,
+  dynamicAssignment,
   expressionChecks,
   fieldFormalParameter,
   forEachVariable,
@@ -153,6 +166,12 @@
   /// of the element.
   void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType);
 
+  /// Called whenever reference is made to an [typeParameter] outside of the
+  /// code being migrated, to report the nullability nodes associated with the
+  /// bound of the type parameter.
+  void externalDecoratedTypeParameterBound(
+      TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType);
+
   /// Called whenever a fix is decided upon, to report the reasons for the fix.
   void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons);
 
diff --git a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
index 9890f67..8d1d030 100644
--- a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
+++ b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/edge_origin.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 
 /// This class transforms ordinary [DartType]s into their corresponding
@@ -22,53 +23,55 @@
 
   /// Transforms [type], which should have come from code that has already been
   /// migrated to NNBD, into the corresponding [DecoratedType].
-  DecoratedType decorate(DartType type) {
+  DecoratedType decorate(DartType type, Element element) {
     if (type.isVoid || type.isDynamic) {
-      return DecoratedType(type, _graph.always);
+      var node = NullabilityNode.forAlreadyMigrated();
+      _graph.makeNullable(node, AlwaysNullableTypeOrigin.forElement(element));
+      return DecoratedType(type, node);
     }
     NullabilityNode node;
     var nullabilitySuffix = (type as TypeImpl).nullabilitySuffix;
     if (nullabilitySuffix == NullabilitySuffix.question) {
-      node = _graph.always;
+      node = NullabilityNode.forAlreadyMigrated();
+      _graph.makeNullable(node, AlreadyMigratedTypeOrigin.forElement(element));
     } else {
-      // Currently, all types passed to this method have nullability suffix `star`
-      // because (a) we don't yet have a migrated SDK, and (b) we haven't added
-      // support to the migrator for analyzing packages that have already been
-      // migrated with NNBD enabled.
-      // TODO(paulberry): fix this assertion when things change.
-      assert(nullabilitySuffix == NullabilitySuffix.star);
-      node = _graph.never;
+      node = NullabilityNode.forAlreadyMigrated();
+      _graph.makeNonNullable(
+          node, AlreadyMigratedTypeOrigin.forElement(element));
     }
     if (type is FunctionType) {
       var typeFormalBounds = type.typeFormals.map((e) {
         var bound = e.bound;
         if (bound == null) {
-          return decorate((_typeProvider.objectType as TypeImpl)
-              .withNullability(NullabilitySuffix.question));
+          return decorate(
+              (_typeProvider.objectType as TypeImpl)
+                  .withNullability(NullabilitySuffix.question),
+              element);
         } else {
-          return decorate(bound);
+          return decorate(bound, element);
         }
       }).toList();
       var positionalParameters = <DecoratedType>[];
       var namedParameters = <String, DecoratedType>{};
       for (var parameter in type.parameters) {
         if (parameter.isPositional) {
-          positionalParameters.add(decorate(parameter.type));
+          positionalParameters.add(decorate(parameter.type, element));
         } else {
-          namedParameters[parameter.name] = decorate(parameter.type);
+          namedParameters[parameter.name] = decorate(parameter.type, element);
         }
       }
       return DecoratedType(type, node,
           typeFormalBounds: typeFormalBounds,
-          returnType: decorate(type.returnType),
+          returnType: decorate(type.returnType, element),
           namedParameters: namedParameters,
           positionalParameters: positionalParameters);
     } else if (type is InterfaceType) {
       var typeParameters = type.element.typeParameters;
       if (typeParameters.isNotEmpty) {
         assert(type.typeArguments.length == typeParameters.length);
-        return DecoratedType(type, node,
-            typeArguments: type.typeArguments.map(decorate).toList());
+        return DecoratedType(type, node, typeArguments: [
+          for (var t in type.typeArguments) decorate(t, element)
+        ]);
       }
       return DecoratedType(type, node);
     } else if (type is TypeParameterType) {
@@ -96,6 +99,6 @@
       // Add FutureOr<T> as a supertype of Future<T>.
       allSupertypes.add(_typeProvider.futureOrType2(type.typeArguments.single));
     }
-    return allSupertypes.map(decorate);
+    return [for (var t in allSupertypes) decorate(t, class_)];
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index 3378ce5..a7a3a60 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -177,7 +177,7 @@
     } else if (type is TypeParameterType) {
       assert(typeArguments == null);
       return DecoratedType(type, NullabilityNode.forInferredType());
-    } else if (type is BottomTypeImpl) {
+    } else if (type is NeverTypeImpl) {
       assert(typeArguments == null);
       return DecoratedType(type, NullabilityNode.forInferredType());
     }
@@ -324,7 +324,7 @@
         return (typeProvider.nullType as TypeImpl)
             .withNullability(NullabilitySuffix.none);
       } else {
-        return BottomTypeImpl.instance;
+        return NeverTypeImpl.instance;
       }
     }
     var nullabilitySuffix =
@@ -367,12 +367,15 @@
                 typeFormalSubstitution),
             parameterKind));
       }
-      return FunctionTypeImpl.synthetic(
-          type_algebra.substitute(
-              returnType.toFinalType(typeProvider), typeFormalSubstitution),
-          newTypeFormals,
-          parameters,
-          nullabilitySuffix: nullabilitySuffix);
+      return FunctionTypeImpl(
+        typeFormals: newTypeFormals,
+        parameters: parameters,
+        returnType: type_algebra.substitute(
+          returnType.toFinalType(typeProvider),
+          typeFormalSubstitution,
+        ),
+        nullabilitySuffix: nullabilitySuffix,
+      );
     } else if (type is InterfaceType) {
       return InterfaceTypeImpl.explicit(type.element,
           [for (var arg in typeArguments) arg.toFinalType(typeProvider)],
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 11598f2..ac9aecd 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -128,9 +128,6 @@
   /// For convenience, a [DecoratedType] representing non-nullable `Type`.
   final DecoratedType _nonNullableTypeType;
 
-  /// For convenience, a [DecoratedType] representing `Null`.
-  final DecoratedType _nullType;
-
   /// For convenience, a [DecoratedType] representing `dynamic`.
   final DecoratedType _dynamicType;
 
@@ -203,7 +200,6 @@
             DecoratedType(typeProvider.boolType, _graph.never),
         _nonNullableTypeType =
             DecoratedType(typeProvider.typeType, _graph.never),
-        _nullType = DecoratedType(typeProvider.nullType, _graph.always),
         _dynamicType = DecoratedType(typeProvider.dynamicType, _graph.always);
 
   /// Gets the decorated type of [element] from [_variables], performing any
@@ -211,7 +207,7 @@
   DecoratedType getOrComputeElementType(Element element,
       {DecoratedType targetType}) {
     Map<TypeParameterElement, DecoratedType> substitution;
-    Element baseElement = element is Member ? element.baseElement : element;
+    Element baseElement = element.declaration;
     if (targetType != null) {
       var classElement = baseElement.enclosingElement as ClassElement;
       if (classElement.typeParameters.isNotEmpty) {
@@ -970,7 +966,11 @@
   @override
   DecoratedType visitNullLiteral(NullLiteral node) {
     _flowAnalysis.nullLiteral(node);
-    return _nullType;
+    var decoratedType =
+        DecoratedType.forImplicitType(typeProvider, node.staticType, _graph);
+    _graph.makeNullable(
+        decoratedType.node, AlwaysNullableTypeOrigin(source, node));
+    return decoratedType;
   }
 
   @override
@@ -1094,8 +1094,12 @@
     Expression returnValue = node.expression;
     final isAsync = node.thisOrAncestorOfType<FunctionBody>().isAsynchronous;
     if (returnValue == null) {
+      var implicitNullType = DecoratedType.forImplicitType(
+          typeProvider, typeProvider.nullType, _graph);
+      _graph.makeNullable(
+          implicitNullType.node, AlwaysNullableTypeOrigin(source, node));
       _checkAssignment(null,
-          source: isAsync ? _futureOf(_nullType) : _nullType,
+          source: isAsync ? _futureOf(implicitNullType) : implicitNullType,
           destination: returnType,
           hard: false);
     } else {
@@ -1622,7 +1626,9 @@
             '(${expression.toSource()}) offset=${expression.offset}');
       }
       EdgeOrigin edgeOrigin;
-      if (!sourceType.type.isDynamic) {
+      if (sourceType.type.isDynamic) {
+        edgeOrigin = DynamicAssignmentOrigin(source, expression);
+      } else {
         if (fromDefaultValue) {
           edgeOrigin = DefaultValueOrigin(source, expression);
         } else {
@@ -1702,10 +1708,7 @@
 
   void _handleConstructorRedirection(
       FormalParameterList parameters, ConstructorName redirectedConstructor) {
-    var callee = redirectedConstructor.staticElement;
-    if (callee is ConstructorMember) {
-      callee = (callee as ConstructorMember).baseElement;
-    }
+    var callee = redirectedConstructor.staticElement.declaration;
     var redirectedClass = callee.enclosingElement;
     var calleeType = _variables.decoratedElementType(callee);
     var typeArguments = redirectedConstructor.type.typeArguments;
@@ -1751,10 +1754,7 @@
                 classElement.thisType,
                 Name(classElement.library.source.uri, declaredElement.name)) ??
             const <ExecutableElement>[]) {
-          if (overriddenElement is ExecutableMember) {
-            var member = overriddenElement as ExecutableMember;
-            overriddenElement = member.baseElement;
-          }
+          overriddenElement = overriddenElement.declaration;
           var overriddenClass =
               overriddenElement.enclosingElement as ClassElement;
           var decoratedOverriddenFunctionType =
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index ec94adce..2899ee8a 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -3,9 +3,33 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 
+/// Edge origin resulting from a type in already-migrated code.
+///
+/// For example, in the Map class in dart:core:
+///   V? operator [](Object key);
+///
+/// this class is used for the edge connecting `always` to the return type of
+/// `operator []`, due to the fact that dart:core has already been migrated and
+/// the type is explicitly nullable.
+///
+/// Note that since a single element can have a complex type, it is likely that
+/// multiple edges will be created with an [AlreadyMigratedTypeOrigin] pointing
+/// to the same type.  To distinguish which edge corresponds to which part of
+/// the element's type, use the callbacks
+/// [NullabilityMigrationInstrumentation.externalDecoratedType] and
+/// [NullabilityMigrationInstrumentation.externalDecoratedTypeParameterBound].
+class AlreadyMigratedTypeOrigin extends EdgeOrigin {
+  AlreadyMigratedTypeOrigin.forElement(Element element)
+      : super.forElement(element);
+
+  @override
+  EdgeOriginKind get kind => EdgeOriginKind.alreadyMigratedType;
+}
+
 /// Edge origin resulting from the use of a type that is always nullable.
 ///
 /// For example, in the following code snippet:
@@ -17,6 +41,9 @@
 class AlwaysNullableTypeOrigin extends EdgeOrigin {
   AlwaysNullableTypeOrigin(Source source, AstNode node) : super(source, node);
 
+  AlwaysNullableTypeOrigin.forElement(Element element)
+      : super.forElement(element);
+
   @override
   EdgeOriginKind get kind => EdgeOriginKind.alwaysNullableType;
 }
@@ -43,6 +70,15 @@
   EdgeOriginKind get kind => EdgeOriginKind.defaultValue;
 }
 
+/// An edge origin used for edges that originated because of an assignment
+/// involving a value with a dynamic type.
+class DynamicAssignmentOrigin extends EdgeOrigin {
+  DynamicAssignmentOrigin(Source source, AstNode node) : super(source, node);
+
+  @override
+  EdgeOriginKind get kind => EdgeOriginKind.dynamicAssignment;
+}
+
 /// Common interface for classes providing information about how an edge came
 /// to be; that is, what was found in the source code that led the migration
 /// tool to create the edge.
@@ -53,7 +89,14 @@
   @override
   final AstNode node;
 
-  EdgeOrigin(this.source, this.node);
+  @override
+  final Element element;
+
+  EdgeOrigin(this.source, this.node) : element = null;
+
+  EdgeOrigin.forElement(this.element)
+      : source = null,
+        node = null;
 }
 
 /// Edge origin resulting from the relationship between a field formal parameter
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index eae5178..b812254 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
@@ -629,34 +628,27 @@
   /// type of the class within which [element] is being accessed; this is used
   /// to perform the correct substitutions.
   DartType _computeMigratedType(Element element, {DartType targetType}) {
-    Element baseElement;
-    if (element is Member) {
-      baseElement = element.baseElement;
-    } else {
-      baseElement = element;
-    }
+    element = element.declaration;
     DartType type;
-    if (baseElement is ClassElement || baseElement is TypeParameterElement) {
+    if (element is ClassElement || element is TypeParameterElement) {
       return typeProvider.typeType;
-    } else if (baseElement is PropertyAccessorElement) {
-      if (baseElement.isSynthetic) {
+    } else if (element is PropertyAccessorElement) {
+      if (element.isSynthetic) {
         type = _variables
-            .decoratedElementType(baseElement.variable)
+            .decoratedElementType(element.variable)
             .toFinalType(typeProvider);
       } else {
-        var functionType = _variables.decoratedElementType(baseElement);
-        var decoratedType = baseElement.isGetter
+        var functionType = _variables.decoratedElementType(element);
+        var decoratedType = element.isGetter
             ? functionType.returnType
             : functionType.positionalParameters[0];
         type = decoratedType.toFinalType(typeProvider);
       }
     } else {
-      type = _variables
-          .decoratedElementType(baseElement)
-          .toFinalType(typeProvider);
+      type = _variables.decoratedElementType(element).toFinalType(typeProvider);
     }
     if (targetType is InterfaceType && targetType.typeArguments.isNotEmpty) {
-      var superclass = baseElement.enclosingElement as ClassElement;
+      var superclass = element.enclosingElement as ClassElement;
       var class_ = targetType.element;
       if (class_ != superclass) {
         var supertype = _decoratedClassHierarchy
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 48d5425..c0d1938 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -126,7 +126,7 @@
             _createDecoratedTypeForClass(classElement, node);
         var functionType = DecoratedType(constructorElement.type, _graph.never,
             returnType: decoratedReturnType,
-            positionalParameters: [],
+            positionalParameters: const [],
             namedParameters: {});
         _variables.recordDecoratedElementType(constructorElement, functionType);
       }
@@ -156,7 +156,7 @@
 
   @override
   DecoratedType visitCompilationUnit(CompilationUnit node) {
-    _graph.migrating(source);
+    _graph.migrating(node.declaredElement.library.source);
     return super.visitCompilationUnit(node);
   }
 
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index d974c23..8812789 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -158,6 +158,19 @@
     return _sourcesBeingMigrated.contains(source);
   }
 
+  /// Creates a graph edge that will try to force the given [node] to be
+  /// non-nullable.
+  void makeNonNullable(NullabilityNode node, EdgeOrigin origin) {
+    connect(node, never, origin, hard: true);
+  }
+
+  /// Creates a graph edge that will try to force the given [node] to be
+  /// nullable.
+  void makeNullable(NullabilityNode node, EdgeOrigin origin,
+      {List<NullabilityNode> guards: const []}) {
+    connect(always, node, origin, guards: guards);
+  }
+
   /// Record source as code that is being migrated.
   void migrating(Source source) {
     _sourcesBeingMigrated.add(source);
@@ -447,6 +460,11 @@
   /// List of edges that have this node as their destination.
   final _upstreamEdges = <NullabilityEdge>[];
 
+  /// Creates a [NullabilityNode] representing the nullability of a variable
+  /// whose type comes from an already-migrated library.
+  factory NullabilityNode.forAlreadyMigrated() =>
+      _NullabilityNodeSimple('migrated');
+
   /// Creates a [NullabilityNode] representing the nullability of an expression
   /// which is nullable iff two other nullability nodes are both nullable.
   ///
@@ -494,6 +512,8 @@
   /// annotate the nullability of that type.
   String get debugSuffix => '?($this)';
 
+  Iterable<EdgeInfo> get downstreamEdges => _downstreamEdges;
+
   /// After nullability propagation, this getter can be used to query whether
   /// the type associated with this node should be considered "exact nullable".
   @visibleForTesting
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 057fc52..20bc39a 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -92,8 +92,10 @@
               'have been stored by the NodeBuilder via '
               'recordTypeParameterBound');
         }
-        decoratedType = _alreadyMigratedCodeDecorator
-            .decorate(typeParameter.bound ?? DynamicTypeImpl.instance);
+        decoratedType = _alreadyMigratedCodeDecorator.decorate(
+            typeParameter.bound ?? DynamicTypeImpl.instance, typeParameter);
+        instrumentation?.externalDecoratedTypeParameterBound(
+            typeParameter, decoratedType);
         _decoratedTypeParameterBounds[typeParameter] = decoratedType;
       }
       return decoratedType;
@@ -181,9 +183,11 @@
 
     DecoratedType decoratedType;
     if (element is FunctionTypedElement) {
-      decoratedType = _alreadyMigratedCodeDecorator.decorate(element.type);
+      decoratedType =
+          _alreadyMigratedCodeDecorator.decorate(element.type, element);
     } else if (element is VariableElement) {
-      decoratedType = _alreadyMigratedCodeDecorator.decorate(element.type);
+      decoratedType =
+          _alreadyMigratedCodeDecorator.decorate(element.type, element);
     } else {
       // TODO(paulberry)
       throw UnimplementedError('Decorating ${element.runtimeType}');
@@ -199,7 +203,6 @@
     var result = <ClassElement, DecoratedType>{};
     for (var decoratedSupertype
         in _alreadyMigratedCodeDecorator.getImmediateSupertypes(class_)) {
-      assert(identical(decoratedSupertype.node, _graph.never));
       var class_ = (decoratedSupertype.type as InterfaceType).element;
       result[class_] = decoratedSupertype;
     }
diff --git a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
index fc51ced..d8131a2 100644
--- a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
+++ b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
@@ -11,96 +11,124 @@
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/already_migrated_code_decorator.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'migration_visitor_test_base.dart';
+
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(_AlreadyMigratedCodeDecoratorTest);
+    defineReflectiveTests(_AlreadyMigratedCodeDecoratorTestNormal);
+    defineReflectiveTests(_AlreadyMigratedCodeDecoratorTestProvisional);
   });
 }
 
-@reflectiveTest
-class _AlreadyMigratedCodeDecoratorTest {
+class _AlreadyMigratedCodeDecoratorTestBase extends Object with EdgeTester {
   final TypeProvider typeProvider;
 
   final AlreadyMigratedCodeDecorator decorator;
 
   final NullabilityGraphForTesting graph;
 
-  factory _AlreadyMigratedCodeDecoratorTest() {
-    return _AlreadyMigratedCodeDecoratorTest._(
-        NullabilityGraphForTesting(), TestTypeProvider());
-  }
+  final NullabilitySuffix suffix;
 
-  _AlreadyMigratedCodeDecoratorTest._(this.graph, this.typeProvider)
+  Element element = _MockElement();
+
+  _AlreadyMigratedCodeDecoratorTestBase(NullabilitySuffix nullabilitySuffix)
+      : this._(nullabilitySuffix, NullabilityGraphForTesting(),
+            TestTypeProvider(nullabilitySuffix: nullabilitySuffix));
+
+  _AlreadyMigratedCodeDecoratorTestBase._(
+      this.suffix, this.graph, this.typeProvider)
       : decorator = AlreadyMigratedCodeDecorator(graph, typeProvider);
 
   NullabilityNode get always => graph.always;
 
   NullabilityNode get never => graph.never;
 
+  void checkAlwaysNullable(NullabilityNode node) {
+    var edge = assertEdge(always, node, hard: false);
+    var origin = graph.getEdgeOrigin(edge);
+    expect(origin.kind, EdgeOriginKind.alwaysNullableType);
+    expect(origin.element, same(element));
+  }
+
   void checkDynamic(DecoratedType decoratedType) {
     expect(decoratedType.type, same(typeProvider.dynamicType));
-    expect(decoratedType.node, same(always));
+    checkAlwaysNullable(decoratedType.node);
+  }
+
+  void checkExplicitlyNonNullable(NullabilityNode node) {
+    var edge = assertEdge(node, never, hard: true);
+    var origin = graph.getEdgeOrigin(edge);
+    expect(origin.kind, EdgeOriginKind.alreadyMigratedType);
+    expect(origin.element, same(element));
+  }
+
+  void checkExplicitlyNullable(NullabilityNode node) {
+    var edge = assertEdge(always, node, hard: false);
+    var origin = graph.getEdgeOrigin(edge);
+    expect(origin.kind, EdgeOriginKind.alreadyMigratedType);
+    expect(origin.element, same(element));
   }
 
   void checkFutureOr(
       DecoratedType decoratedType,
-      NullabilityNode expectedNullability,
+      void Function(NullabilityNode) checkNullability,
       void Function(DecoratedType) checkArgument) {
     expect(decoratedType.type.element, typeProvider.futureOrElement);
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
     checkArgument(decoratedType.typeArguments[0]);
   }
 
-  void checkInt(
-      DecoratedType decoratedType, NullabilityNode expectedNullability) {
+  void checkInt(DecoratedType decoratedType,
+      void Function(NullabilityNode) checkNullability) {
     expect(decoratedType.type.element, typeProvider.intType.element);
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
   }
 
   void checkIterable(
       DecoratedType decoratedType,
-      NullabilityNode expectedNullability,
+      void Function(NullabilityNode) checkNullability,
       void Function(DecoratedType) checkArgument) {
     expect(
         decoratedType.type.element, typeProvider.iterableDynamicType.element);
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
     checkArgument(decoratedType.typeArguments[0]);
   }
 
-  void checkNum(
-      DecoratedType decoratedType, NullabilityNode expectedNullability) {
+  void checkNum(DecoratedType decoratedType,
+      void Function(NullabilityNode) checkNullability) {
     expect(decoratedType.type.element, typeProvider.numType.element);
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
   }
 
-  void checkObject(
-      DecoratedType decoratedType, NullabilityNode expectedNullability) {
+  void checkObject(DecoratedType decoratedType,
+      void Function(NullabilityNode) checkNullability) {
     expect(decoratedType.type.element, typeProvider.objectType.element);
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
   }
 
   void checkTypeParameter(
       DecoratedType decoratedType,
-      NullabilityNode expectedNullability,
+      void Function(NullabilityNode) checkNullability,
       TypeParameterElement expectedElement) {
     var type = decoratedType.type as TypeParameterTypeImpl;
     expect(type.element, same(expectedElement));
-    expect(decoratedType.node, expectedNullability);
+    checkNullability(decoratedType.node);
   }
 
   void checkVoid(DecoratedType decoratedType) {
     expect(decoratedType.type, same(typeProvider.voidType));
-    expect(decoratedType.node, same(always));
+    checkAlwaysNullable(decoratedType.node);
   }
 
   DecoratedType decorate(DartType type) {
-    var decoratedType = decorator.decorate(type);
+    var decoratedType = decorator.decorate(type, element);
     expect(decoratedType.type, same(type));
     return decoratedType;
   }
@@ -112,100 +140,149 @@
   test_decorate_functionType_generic_bounded() {
     var typeFormal = TypeParameterElementImpl.synthetic('T')
       ..bound = typeProvider.numType;
-    var decoratedType = decorate(FunctionTypeImpl.synthetic(
-        TypeParameterTypeImpl(typeFormal), [typeFormal], [],
-        nullabilitySuffix: NullabilitySuffix.star));
+    var decoratedType = decorate(
+      FunctionTypeImpl(
+        typeFormals: [typeFormal],
+        parameters: const [],
+        returnType: TypeParameterTypeImpl(typeFormal),
+        nullabilitySuffix: suffix,
+      ),
+    );
     expect(decoratedType.typeFormalBounds, hasLength(1));
-    checkNum(decoratedType.typeFormalBounds[0], never);
-    checkTypeParameter(decoratedType.returnType, never, typeFormal);
+    checkNum(decoratedType.typeFormalBounds[0], checkExplicitlyNonNullable);
+    checkTypeParameter(
+        decoratedType.returnType, checkExplicitlyNonNullable, typeFormal);
   }
 
   test_decorate_functionType_generic_no_explicit_bound() {
     var typeFormal = TypeParameterElementImpl.synthetic('T');
-    var decoratedType = decorate(FunctionTypeImpl.synthetic(
-        TypeParameterTypeImpl(typeFormal), [typeFormal], [],
-        nullabilitySuffix: NullabilitySuffix.star));
+    var decoratedType = decorate(
+      FunctionTypeImpl(
+        typeFormals: [typeFormal],
+        parameters: const [],
+        returnType: TypeParameterTypeImpl(typeFormal),
+        nullabilitySuffix: suffix,
+      ),
+    );
     expect(decoratedType.typeFormalBounds, hasLength(1));
-    checkObject(decoratedType.typeFormalBounds[0], always);
-    checkTypeParameter(decoratedType.returnType, never, typeFormal);
+    checkObject(decoratedType.typeFormalBounds[0], checkExplicitlyNullable);
+    checkTypeParameter(
+        decoratedType.returnType, checkExplicitlyNonNullable, typeFormal);
   }
 
   test_decorate_functionType_named_parameter() {
-    checkDynamic(decorate(FunctionTypeImpl.synthetic(
-            typeProvider.voidType,
-            [],
-            [
-              ParameterElementImpl.synthetic(
-                  'x', typeProvider.dynamicType, ParameterKind.NAMED)
-            ],
-            nullabilitySuffix: NullabilitySuffix.star))
-        .namedParameters['x']);
+    checkDynamic(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: [
+            ParameterElementImpl.synthetic(
+              'x',
+              typeProvider.dynamicType,
+              ParameterKind.NAMED,
+            )
+          ],
+          returnType: typeProvider.voidType,
+          nullabilitySuffix: suffix,
+        ),
+      ).namedParameters['x'],
+    );
   }
 
   test_decorate_functionType_ordinary_parameter() {
-    checkDynamic(decorate(FunctionTypeImpl.synthetic(
-            typeProvider.voidType,
-            [],
-            [
-              ParameterElementImpl.synthetic(
-                  'x', typeProvider.dynamicType, ParameterKind.REQUIRED)
-            ],
-            nullabilitySuffix: NullabilitySuffix.star))
-        .positionalParameters[0]);
+    checkDynamic(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: [
+            ParameterElementImpl.synthetic(
+              'x',
+              typeProvider.dynamicType,
+              ParameterKind.REQUIRED,
+            )
+          ],
+          returnType: typeProvider.voidType,
+          nullabilitySuffix: suffix,
+        ),
+      ).positionalParameters[0],
+    );
   }
 
   test_decorate_functionType_positional_parameter() {
-    checkDynamic(decorate(FunctionTypeImpl.synthetic(
-            typeProvider.voidType,
-            [],
-            [
-              ParameterElementImpl.synthetic(
-                  'x', typeProvider.dynamicType, ParameterKind.POSITIONAL)
-            ],
-            nullabilitySuffix: NullabilitySuffix.star))
-        .positionalParameters[0]);
+    checkDynamic(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: [
+            ParameterElementImpl.synthetic(
+              'x',
+              typeProvider.dynamicType,
+              ParameterKind.POSITIONAL,
+            )
+          ],
+          returnType: typeProvider.voidType,
+          nullabilitySuffix: suffix,
+        ),
+      ).positionalParameters[0],
+    );
   }
 
   test_decorate_functionType_question() {
-    expect(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.voidType, [], [],
-                nullabilitySuffix: NullabilitySuffix.question))
-            .node,
-        same(always));
+    checkExplicitlyNullable(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: const [],
+          returnType: typeProvider.voidType,
+          nullabilitySuffix: NullabilitySuffix.question,
+        ),
+      ).node,
+    );
   }
 
   test_decorate_functionType_returnType() {
-    checkDynamic(decorate(FunctionTypeImpl.synthetic(
-            typeProvider.dynamicType, [], [],
-            nullabilitySuffix: NullabilitySuffix.star))
-        .returnType);
+    checkDynamic(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: const [],
+          returnType: typeProvider.dynamicType,
+          nullabilitySuffix: suffix,
+        ),
+      ).returnType,
+    );
   }
 
   test_decorate_functionType_star() {
-    expect(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.voidType, [], [],
-                nullabilitySuffix: NullabilitySuffix.star))
-            .node,
-        same(never));
+    checkExplicitlyNonNullable(
+      decorate(
+        FunctionTypeImpl(
+          typeFormals: const [],
+          parameters: const [],
+          returnType: typeProvider.voidType,
+          nullabilitySuffix: suffix,
+        ),
+      ).node,
+    );
   }
 
   test_decorate_interfaceType_simple_question() {
     checkInt(
         decorate(InterfaceTypeImpl(typeProvider.intType.element,
             nullabilitySuffix: NullabilitySuffix.question)),
-        always);
+        checkExplicitlyNullable);
   }
 
   test_decorate_interfaceType_simple_star() {
     checkInt(
         decorate(InterfaceTypeImpl(typeProvider.intType.element,
-            nullabilitySuffix: NullabilitySuffix.star)),
-        never);
+            nullabilitySuffix: suffix)),
+        checkExplicitlyNonNullable);
   }
 
   test_decorate_iterable_dynamic() {
     var decorated = decorate(typeProvider.iterableDynamicType);
-    checkIterable(decorated, never, checkDynamic);
+    checkIterable(decorated, checkExplicitlyNonNullable, checkDynamic);
   }
 
   test_decorate_typeParameterType_question() {
@@ -213,16 +290,15 @@
     checkTypeParameter(
         decorate(TypeParameterTypeImpl(element,
             nullabilitySuffix: NullabilitySuffix.question)),
-        always,
+        checkExplicitlyNullable,
         element);
   }
 
   test_decorate_typeParameterType_star() {
     var element = TypeParameterElementImpl.synthetic('T');
     checkTypeParameter(
-        decorate(TypeParameterTypeImpl(element,
-            nullabilitySuffix: NullabilitySuffix.star)),
-        never,
+        decorate(TypeParameterTypeImpl(element, nullabilitySuffix: suffix)),
+        checkExplicitlyNonNullable,
         element);
   }
 
@@ -231,64 +307,94 @@
   }
 
   test_getImmediateSupertypes_future() {
-    var element = typeProvider.futureElement;
-    var decoratedSupertypes =
-        decorator.getImmediateSupertypes(element).toList();
-    var typeParam = element.typeParameters[0];
+    var class_ = element = typeProvider.futureElement;
+    var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
+    var typeParam = class_.typeParameters[0];
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], never);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
     // Since Future<T> is a subtype of FutureOr<T>, we consider FutureOr<T> to
     // be an immediate supertype, even though the class declaration for Future
     // doesn't mention FutureOr.
-    checkFutureOr(decoratedSupertypes[1], never,
-        (t) => checkTypeParameter(t, never, typeParam));
+    checkFutureOr(decoratedSupertypes[1], checkExplicitlyNonNullable,
+        (t) => checkTypeParameter(t, checkExplicitlyNonNullable, typeParam));
   }
 
   test_getImmediateSupertypes_generic() {
     var t = ElementFactory.typeParameterElement('T');
-    var class_ = ElementFactory.classElement3(
+    var class_ = element = ElementFactory.classElement3(
       name: 'C',
       typeParameters: [t],
       supertype: typeProvider.iterableType2(
-        t.instantiate(nullabilitySuffix: NullabilitySuffix.star),
+        t.instantiate(nullabilitySuffix: suffix),
       ),
     );
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkIterable(decoratedSupertypes[0], never,
-        (type) => checkTypeParameter(type, never, t));
+    checkIterable(decoratedSupertypes[0], checkExplicitlyNonNullable,
+        (type) => checkTypeParameter(type, checkExplicitlyNonNullable, t));
   }
 
   test_getImmediateSupertypes_interface() {
-    var class_ = ElementFactory.classElement('C', typeProvider.objectType);
+    var class_ =
+        element = ElementFactory.classElement('C', typeProvider.objectType);
     class_.interfaces = [typeProvider.numType];
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], never);
-    checkNum(decoratedSupertypes[1], never);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
+    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable);
   }
 
   test_getImmediateSupertypes_mixin() {
-    var class_ = ElementFactory.classElement('C', typeProvider.objectType);
+    var class_ =
+        element = ElementFactory.classElement('C', typeProvider.objectType);
     class_.mixins = [typeProvider.numType];
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], never);
-    checkNum(decoratedSupertypes[1], never);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
+    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable);
   }
 
   test_getImmediateSupertypes_superclassConstraint() {
-    var class_ = ElementFactory.mixinElement(
+    var class_ = element = ElementFactory.mixinElement(
         name: 'C', constraints: [typeProvider.numType]);
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkNum(decoratedSupertypes[0], never);
+    checkNum(decoratedSupertypes[0], checkExplicitlyNonNullable);
   }
 
   test_getImmediateSupertypes_supertype() {
-    var class_ = ElementFactory.classElement('C', typeProvider.objectType);
+    var class_ =
+        element = ElementFactory.classElement('C', typeProvider.objectType);
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkObject(decoratedSupertypes[0], never);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
   }
 }
+
+/// Specialization of [_AlreadyMigratedCodeDecoratorTestBase] for testing the
+/// situation where the already migrated code does not contain star types.  In
+/// the final product, by definition all already-migrated code will be free of
+/// star types.  However, since we do not yet migrate using a fully NNBD-aware
+/// SDK, we need to handle both star and non-star variants on a short term
+/// basis.
+@reflectiveTest
+class _AlreadyMigratedCodeDecoratorTestNormal
+    extends _AlreadyMigratedCodeDecoratorTestBase {
+  _AlreadyMigratedCodeDecoratorTestNormal() : super(NullabilitySuffix.none);
+}
+
+/// Specialization of [_AlreadyMigratedCodeDecoratorTestBase] for testing the
+/// situation where the already migrated code contains star types.  In the final
+/// product, this will never happen.  However, since we do not yet migrate using
+/// a fully NNBD-aware SDK, we need to handle both star and non-star variants on
+/// a short term basis.
+@reflectiveTest
+class _AlreadyMigratedCodeDecoratorTestProvisional
+    extends _AlreadyMigratedCodeDecoratorTestBase {
+  _AlreadyMigratedCodeDecoratorTestProvisional()
+      : super(NullabilitySuffix.star);
+}
+
+class _MockElement implements Element {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index b441ee4..91a9d171 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -38,7 +38,7 @@
   Future<void> _checkMultipleFileChanges(
       Map<String, String> input, Map<String, String> expectedOutput) async {
     for (var path in input.keys) {
-      newFile(path, content: input[path]);
+      driver.getFileSync(newFile(path, content: input[path]).path);
     }
     var listener = new TestMigrationListener();
     var migration =
@@ -1847,6 +1847,32 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_libraryWithParts() async {
+    var root = '/home/test/lib';
+    var path1 = convertPath('$root/lib.dart');
+    var file1 = '''
+part 'src/foo/part.dart';
+''';
+    var expected1 = '''
+part 'src/foo/part.dart';
+''';
+    var path2 = convertPath('$root/src/foo/part.dart');
+    var file2 = '''
+part of '../../lib.dart';
+class C {
+  static void m(C c) {}
+}
+''';
+    var expected2 = '''
+part of '../../lib.dart';
+class C {
+  static void m(C c) {}
+}
+''';
+    await _checkMultipleFileChanges(
+        {path2: file2, path1: file1}, {path1: expected1, path2: expected2});
+  }
+
   test_local_function() async {
     var content = '''
 int f(int i) {
@@ -2374,7 +2400,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38339')
   test_operator_eq_with_inferred_parameter_type() async {
     var content = '''
 class C {
diff --git a/pkg/nnbd_migration/test/decorated_type_test.dart b/pkg/nnbd_migration/test/decorated_type_test.dart
index 22a2dc0..fc317ec 100644
--- a/pkg/nnbd_migration/test/decorated_type_test.dart
+++ b/pkg/nnbd_migration/test/decorated_type_test.dart
@@ -301,13 +301,13 @@
 
   test_toFinalType_bottom_non_nullable() {
     var type =
-        DecoratedType(BottomTypeImpl.instance, never).toFinalType(typeProvider);
+        DecoratedType(NeverTypeImpl.instance, never).toFinalType(typeProvider);
     assertDartType(type, 'Never');
   }
 
   test_toFinalType_bottom_nullable() {
-    var type = DecoratedType(BottomTypeImpl.instance, always)
-        .toFinalType(typeProvider);
+    var type =
+        DecoratedType(NeverTypeImpl.instance, always).toFinalType(typeProvider);
     assertDartType(type, 'Null');
   }
 
@@ -326,7 +326,7 @@
         .toFinalType(typeProvider) as FunctionType;
     assertDartType(
         type,
-        'dynamic Function<T extends List<U>,U extends Object,'
+        'dynamic Function<T extends List<U>, U extends Object, '
         'V extends List<U>>()');
     expect(type.typeFormals[0], isNot(same(t)));
     expect(type.typeFormals[1], isNot(same(u)));
@@ -522,7 +522,7 @@
 
   test_toString_bottom() {
     var node = newNode();
-    var decoratedType = DecoratedType(BottomTypeImpl.instance, node);
+    var decoratedType = DecoratedType(NeverTypeImpl.instance, node);
     expect(decoratedType.toString(), 'Never?($node)');
   }
 
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 9e3cc4e..9bf66c5 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@@ -342,22 +341,29 @@
     assertEdge(node, right, hard: false);
   }
 
-  void assertLUB(
-      NullabilityNode node, NullabilityNode left, NullabilityNode right) {
+  void assertLUB(NullabilityNode node, Object left, Object right) {
     var conditionalNode = node as NullabilityNodeForLUB;
-    expect(conditionalNode.left, same(left));
-    expect(conditionalNode.right, same(right));
+    var leftMatcher = NodeMatcher(left);
+    var rightMatcher = NodeMatcher(right);
+    expect(leftMatcher.matches(conditionalNode.left), true);
+    expect(rightMatcher.matches(conditionalNode.right), true);
   }
 
   /// Checks that there are no nullability nodes upstream from [node] that could
   /// cause it to become nullable.
   void assertNoUpstreamNullability(NullabilityNode node) {
-    // never can never become nullable, even if it has nodes
-    // upstream from it.
-    if (node == never) return;
+    // Store `neverClosure` in a local variable so that we avoid the
+    // computational expense of recomputing it each time through the loop below.
+    var neverClosure = this.neverClosure;
 
+    // Any node with a hard edge to never (or never itself) won't become
+    // nullable, even if it has nodes upstream from it.
+    if (neverClosure.contains(node)) return;
+
+    // Otherwise, make sure that every node directly upstream from this node
+    // has a hard edge to never.
     for (var edge in getEdges(anyNode, node)) {
-      expect(edge.sourceNode, never);
+      expect(neverClosure, contains(edge.sourceNode));
     }
   }
 
@@ -513,7 +519,10 @@
         decoratedTypeAnnotation('int> f').node);
     // If `x` is `Future<int?>`, then the only way to migrate is to make the
     // return type `FutureOr<int?>`.
-    assertEdge(substitutionNode(decoratedTypeAnnotation('int> x').node, never),
+
+    assertEdge(
+        substitutionNode(
+            decoratedTypeAnnotation('int> x').node, inSet(neverClosure)),
         decoratedTypeAnnotation('int> f').node,
         hard: false);
     assertNoEdge(decoratedTypeAnnotation('int> x').node,
@@ -559,7 +568,8 @@
 }
 ''');
     // TODO(paulberry): edge should be hard.
-    assertEdge(always, decoratedTypeAnnotation('List').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('List').node,
+        hard: false);
   }
 
   test_assign_type_parameter_to_bound() async {
@@ -589,7 +599,8 @@
     var iterableInt = decoratedTypeAnnotation('Iterable<int>');
     var listInt = decoratedTypeAnnotation('List<int>');
     assertEdge(listInt.node, iterableInt.node, hard: true);
-    assertEdge(substitutionNode(listInt.typeArguments[0].node, never),
+    assertEdge(
+        substitutionNode(listInt.typeArguments[0].node, inSet(neverClosure)),
         iterableInt.typeArguments[0].node,
         hard: false);
   }
@@ -1152,8 +1163,10 @@
 int f(int i, int j) => i + j;
 ''');
 
-    assertNullCheck(checkExpression('j;'),
-        assertEdge(decoratedTypeAnnotation('int j').node, never, hard: true));
+    assertNullCheck(
+        checkExpression('j;'),
+        assertEdge(decoratedTypeAnnotation('int j').node, inSet(neverClosure),
+            hard: true));
   }
 
   test_binaryExpression_plus_right_check_custom() async {
@@ -1554,7 +1567,7 @@
 
     var nullable_i = decoratedTypeAnnotation('int i').node;
     var nullable_conditional = decoratedExpressionType('(b ?').node;
-    assertLUB(nullable_conditional, always, nullable_i);
+    assertLUB(nullable_conditional, inSet(alwaysPlus), nullable_i);
   }
 
   test_conditionalExpression_right_non_null() async {
@@ -1581,7 +1594,7 @@
 
     var nullable_i = decoratedTypeAnnotation('int i').node;
     var nullable_conditional = decoratedExpressionType('(b ?').node;
-    assertLUB(nullable_conditional, nullable_i, always);
+    assertLUB(nullable_conditional, nullable_i, inSet(alwaysPlus));
   }
 
   test_constructor_default_parameter_value_bool() async {
@@ -1816,7 +1829,9 @@
 }
 ''');
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
-    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+    assertEdge(
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
         decoratedTypeAnnotation('int i').node,
         hard: false);
   }
@@ -1834,7 +1849,9 @@
     var iNode = iMatcher.matchingNode;
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
     assertEdge(
-        substitutionNode(decoratedTypeAnnotation('int> l').node, never), iNode,
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+        iNode,
         hard: false);
   }
 
@@ -1846,7 +1863,9 @@
 }
 ''');
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
-    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+    assertEdge(
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
         decoratedTypeAnnotation('int x').node,
         hard: false);
   }
@@ -1858,7 +1877,9 @@
 }
 ''');
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
-    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+    assertEdge(
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
         decoratedTypeAnnotation('int i').node,
         hard: false);
   }
@@ -1878,7 +1899,9 @@
     var iNode = iMatcher.matchingNode;
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
     assertEdge(
-        substitutionNode(decoratedTypeAnnotation('int> l').node, never), iNode,
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+        iNode,
         hard: false);
   }
 
@@ -1890,7 +1913,9 @@
 }
 ''');
     assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
-    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+    assertEdge(
+        substitutionNode(
+            decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
         decoratedTypeAnnotation('int x').node,
         hard: false);
   }
@@ -2039,7 +2064,8 @@
 void f({int i = null}) {}
 ''');
 
-    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_functionDeclaration_parameter_named_no_default() async {
@@ -2073,7 +2099,8 @@
 void f([int i = null]) {}
 ''');
 
-    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_functionDeclaration_parameter_positionalOptional_no_default() async {
@@ -2174,8 +2201,10 @@
 }
 ''');
 
-    assertNullCheck(checkExpression('null'),
-        assertEdge(always, decoratedTypeAnnotation('int').node, hard: false));
+    assertNullCheck(
+        checkExpression('null'),
+        assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+            hard: false));
   }
 
   test_functionInvocation_return() async {
@@ -2908,7 +2937,7 @@
     final returnTypeEdge = returnTypeEdges.single;
 
     final listArgType = returnTypeEdge.sourceNode;
-    assertEdge(always, listArgType, hard: false);
+    assertEdge(inSet(alwaysPlus), listArgType, hard: false);
   }
 
   test_listLiteral_typeArgument_noNullableElements() async {
@@ -2931,7 +2960,8 @@
 }
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('List').node);
-    assertEdge(always, decoratedTypeAnnotation('String>[').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('String>[').node,
+        hard: false);
   }
 
   test_localVariable_type_inferred() async {
@@ -3126,13 +3156,12 @@
     var nullable_i = decoratedTypeAnnotation('int i').node;
     var nullable_list_t =
         decoratedTypeAnnotation('List<int>').typeArguments[0].node;
-    var addMethod = findNode.methodInvocation('x.add').methodName.staticElement
-        as MethodMember;
+    var addMethod = findNode.methodInvocation('x.add').methodName.staticElement;
     var nullable_t = variables
-        .decoratedElementType(addMethod.baseElement)
+        .decoratedElementType(addMethod.declaration)
         .positionalParameters[0]
         .node;
-    expect(nullable_t, same(never));
+    assertEdge(nullable_t, never, hard: true);
     var check_i = checkExpression('i/*check*/');
     var nullable_list_t_or_nullable_t = check_i
         .checks.edges.single.destinationNode as NullabilityNodeForSubstitution;
@@ -3209,7 +3238,7 @@
 ''');
     var nullable_j = decoratedTypeAnnotation('int j');
     assertNullCheck(checkExpression('j/*check*/'),
-        assertEdge(nullable_j.node, never, hard: true));
+        assertEdge(nullable_j.node, inSet(neverClosure), hard: true));
   }
 
   test_methodInvocation_resolves_to_getter() async {
@@ -3591,8 +3620,10 @@
 }
 ''');
 
-    assertNullCheck(checkExpression('(null)'),
-        assertEdge(always, decoratedTypeAnnotation('int').node, hard: false));
+    assertNullCheck(
+        checkExpression('(null)'),
+        assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+            hard: false));
   }
 
   test_part_metadata() async {
@@ -4041,7 +4072,8 @@
     // i1.toDouble() cannot be a hard edge or i2 will fail assignment
     assertEdge(decoratedTypeAnnotation('int i').node, never, hard: false);
     // i2 gets a soft edge to always due to null assignment
-    assertEdge(always, decoratedTypeAnnotation('int i').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int i').node,
+        hard: false);
   }
 
   test_postDominators_questionQuestionOperator() async {
@@ -4451,7 +4483,7 @@
     assertNullCheck(use, assertEdge(declaration, never, hard: true));
 
     var returnType = decoratedTypeAnnotation('int f').node;
-    assertEdge(never, returnType, hard: false);
+    assertEdge(inSet(neverClosure), returnType, hard: false);
   }
 
   test_prefixExpression_plusPlus() async {
@@ -4466,7 +4498,7 @@
     assertNullCheck(use, assertEdge(declaration, never, hard: true));
 
     var returnType = decoratedTypeAnnotation('int f').node;
-    assertEdge(never, returnType, hard: false);
+    assertEdge(inSet(neverClosure), returnType, hard: false);
   }
 
   test_prefixExpression_plusPlus_dynamic() async {
@@ -4745,7 +4777,8 @@
 }
 ''');
 
-    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_return_null() async {
@@ -4755,8 +4788,10 @@
 }
 ''');
 
-    assertNullCheck(checkExpression('null'),
-        assertEdge(always, decoratedTypeAnnotation('int').node, hard: false));
+    assertNullCheck(
+        checkExpression('null'),
+        assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+            hard: false));
   }
 
   test_return_null_generic() async {
@@ -4768,9 +4803,9 @@
 }
 ''');
     var tNode = decoratedTypeAnnotation('T f').node;
-    assertEdge(always, tNode, hard: false);
-    assertNullCheck(
-        checkExpression('null'), assertEdge(always, tNode, hard: false));
+    assertEdge(inSet(alwaysPlus), tNode, hard: false);
+    assertNullCheck(checkExpression('null'),
+        assertEdge(inSet(alwaysPlus), tNode, hard: false));
   }
 
   test_setOrMapLiteral_map_noTypeArgument_noNullableKeysAndValues() async {
@@ -4801,7 +4836,8 @@
     var mapNode = decoratedTypeAnnotation('Map').node;
 
     assertNoUpstreamNullability(mapNode);
-    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).sourceNode,
+    assertEdge(
+        inSet(alwaysPlus), assertEdge(anyNode, keyNode, hard: false).sourceNode,
         hard: false);
     assertNoUpstreamNullability(
         assertEdge(anyNode, valueNode, hard: false).sourceNode);
@@ -4818,9 +4854,11 @@
     var mapNode = decoratedTypeAnnotation('Map').node;
 
     assertNoUpstreamNullability(mapNode);
-    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).sourceNode,
+    assertEdge(
+        inSet(alwaysPlus), assertEdge(anyNode, keyNode, hard: false).sourceNode,
         hard: false);
-    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
+    assertEdge(inSet(alwaysPlus),
+        assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4837,7 +4875,8 @@
     assertNoUpstreamNullability(mapNode);
     assertNoUpstreamNullability(
         assertEdge(anyNode, keyNode, hard: false).sourceNode);
-    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
+    assertEdge(inSet(alwaysPlus),
+        assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4867,7 +4906,7 @@
 }
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('Map').node);
-    assertEdge(always, decoratedTypeAnnotation('String, int>{').node,
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('String, int>{').node,
         hard: false);
     assertNoUpstreamNullability(decoratedTypeAnnotation('int>{').node);
   }
@@ -4879,9 +4918,10 @@
 }
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('Map').node);
-    assertEdge(always, decoratedTypeAnnotation('String, int>{').node,
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('String, int>{').node,
         hard: false);
-    assertEdge(always, decoratedTypeAnnotation('int>{').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int>{').node,
+        hard: false);
   }
 
   test_setOrMapLiteral_map_typeArguments_nullableValue() async {
@@ -4892,7 +4932,8 @@
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('Map').node);
     assertNoUpstreamNullability(decoratedTypeAnnotation('String, int>{').node);
-    assertEdge(always, decoratedTypeAnnotation('int>{').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int>{').node,
+        hard: false);
   }
 
   test_setOrMapLiteral_set_noTypeArgument_noNullableElements() async {
@@ -4919,7 +4960,8 @@
     var setNode = decoratedTypeAnnotation('Set').node;
 
     assertNoUpstreamNullability(setNode);
-    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
+    assertEdge(inSet(alwaysPlus),
+        assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4943,7 +4985,8 @@
 }
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('Set').node);
-    assertEdge(always, decoratedTypeAnnotation('String>{').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('String>{').node,
+        hard: false);
   }
 
   test_simpleIdentifier_function() async {
@@ -5017,7 +5060,8 @@
     await analyze('''
 int f() => null;
 ''');
-    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_spread_element_list() async {
@@ -5213,7 +5257,7 @@
 main() { x = null; }
 ''');
     var setXType = decoratedTypeAnnotation('int value');
-    assertEdge(always, setXType.node, hard: false);
+    assertEdge(inSet(alwaysPlus), setXType.node, hard: false);
   }
 
   test_topLevelVar_metadata() async {
@@ -5247,7 +5291,7 @@
 double get myPi => pi;
 ''');
     var myPiType = decoratedTypeAnnotation('double get');
-    assertEdge(never, myPiType.node, hard: false);
+    assertEdge(inSet(neverClosure), myPiType.node, hard: false);
   }
 
   test_topLevelVariable_type_inferred() async {
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index 638a853..38bdd97 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -41,6 +41,14 @@
   }
 
   @override
+  void externalDecoratedTypeParameterBound(
+      TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType) {
+    expect(test.externalDecoratedTypeParameterBound,
+        isNot(contains(typeParameter)));
+    test.externalDecoratedTypeParameterBound[typeParameter] = decoratedType;
+  }
+
+  @override
   void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons) {
     test.fixes[fix] = reasons.toList();
   }
@@ -96,6 +104,9 @@
 
   final Map<Element, DecoratedTypeInfo> externalDecoratedType = {};
 
+  final Map<TypeParameterElement, DecoratedTypeInfo>
+      externalDecoratedTypeParameterBound = {};
+
   final List<EdgeInfo> edges = [];
 
   Map<SingleNullabilityFix, List<FixReasonInfo>> fixes = {};
@@ -155,6 +166,40 @@
         'void Function(Object)');
   }
 
+  test_externalDecoratedTypeParameterBound() async {
+    await analyze('''
+import 'dart:math';
+f(Point<int> x) {}
+''');
+    var pointElement = findNode.simple('Point').staticElement as ClassElement;
+    var pointElementTypeParameter = pointElement.typeParameters[0];
+    expect(
+        externalDecoratedTypeParameterBound[pointElementTypeParameter]
+            .type
+            .toString(),
+        'num');
+  }
+
+  test_externalType_nullability_dynamic_edge() async {
+    await analyze('''
+f(List<int> x) {}
+''');
+    var listElement = findNode.simple('List').staticElement as ClassElement;
+    var listElementTypeParameter = listElement.typeParameters[0];
+    var typeParameterBoundNode =
+        externalDecoratedTypeParameterBound[listElementTypeParameter].node;
+    var edge = edges
+        .where((e) =>
+            e.sourceNode == always &&
+            e.destinationNode == typeParameterBoundNode)
+        .single;
+    var origin = edgeOrigin[edge];
+    expect(origin.kind, EdgeOriginKind.alwaysNullableType);
+    expect(origin.element, same(listElementTypeParameter));
+    expect(origin.source, null);
+    expect(origin.node, null);
+  }
+
   test_fix_reason_edge() async {
     await analyze('''
 void f(int x) {
@@ -362,6 +407,21 @@
     expect(origin.node, findNode.simple('x;'));
   }
 
+  test_graphEdge_origin_dynamic_assignment() async {
+    await analyze('''
+int f(dynamic x) => x;
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('dynamic x')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    var matchingEdges = edges
+        .where((e) => e.sourceNode == xNode && e.destinationNode == returnNode)
+        .toList();
+    var origin = edgeOrigin[matchingEdges.single];
+    expect(origin.kind, EdgeOriginKind.dynamicAssignment);
+    expect(origin.source, source);
+    expect(origin.node, findNode.simple('x;'));
+  }
+
   test_graphEdge_soft() async {
     await analyze('''
 int f(int x, bool b) {
@@ -413,7 +473,10 @@
     expect(always.isNullable, true);
     var xNode = explicitTypeNullability[findNode.typeAnnotation('int')];
     var edge = edges.where((e) => e.destinationNode == xNode).single;
-    expect(edge.sourceNode, always);
+    var edgeSource = edge.sourceNode;
+    var upstreamEdge =
+        edges.where((e) => e.destinationNode == edgeSource).single;
+    expect(upstreamEdge.sourceNode, always);
   }
 
   test_immutableNode_never() async {
@@ -729,7 +792,7 @@
         explicitTypeNullability[findNode.typeAnnotation('int')];
     expect(edges.where((e) {
       var destination = e.destinationNode;
-      return e.sourceNode == always &&
+      return _isPointedToByAlways(e.sourceNode) &&
           destination is SubstitutionNodeInfo &&
           destination.innerNode == implicitInvocationTypeArgumentNode;
     }), hasLength(1));
@@ -756,7 +819,7 @@
         explicitTypeNullability[findNode.typeAnnotation('int')];
     expect(edges.where((e) {
       var destination = e.destinationNode;
-      return e.sourceNode == always &&
+      return _isPointedToByAlways(e.sourceNode) &&
           destination is SubstitutionNodeInfo &&
           destination.innerNode == implicitInvocationTypeArgumentNode;
     }), hasLength(1));
@@ -781,7 +844,7 @@
         explicitTypeNullability[findNode.typeAnnotation('int')];
     expect(edges.where((e) {
       var destination = e.destinationNode;
-      return e.sourceNode == always &&
+      return _isPointedToByAlways(e.sourceNode) &&
           destination is SubstitutionNodeInfo &&
           destination.innerNode == implicitInvocationTypeArgumentNode;
     }), hasLength(1));
@@ -802,7 +865,7 @@
         explicitTypeNullability[findNode.typeAnnotation('int')];
     expect(
         edges.where((e) =>
-            e.sourceNode == always &&
+            _isPointedToByAlways(e.sourceNode) &&
             e.destinationNode == implicitListLiteralElementNode),
         hasLength(1));
     expect(
@@ -836,7 +899,7 @@
         hasLength(1));
     expect(
         edges.where((e) =>
-            e.sourceNode == always &&
+            _isPointedToByAlways(e.sourceNode) &&
             e.destinationNode == implicitMapLiteralValueNode),
         hasLength(1));
     expect(
@@ -856,7 +919,7 @@
         explicitTypeNullability[findNode.typeAnnotation('int')];
     expect(
         edges.where((e) =>
-            e.sourceNode == always &&
+            _isPointedToByAlways(e.sourceNode) &&
             e.destinationNode == implicitSetLiteralElementNode),
         hasLength(1));
     expect(
@@ -889,7 +952,7 @@
     var step = propagationSteps.where((s) => s.node == xNode).single;
     expect(step.newState, NullabilityState.ordinaryNullable);
     expect(step.reason, StateChangeReason.downstream);
-    expect(step.edge.sourceNode, always);
+    expect(_isPointedToByAlways(step.edge.sourceNode), true);
     expect(step.edge.destinationNode, xNode);
   }
 
@@ -924,4 +987,9 @@
     expect(sNode.outerNode,
         explicitTypeNullability[findNode.typeAnnotation('T t')]);
   }
+
+  bool _isPointedToByAlways(NullabilityNodeInfo node) {
+    return edges
+        .any((e) => e.sourceNode == always && e.destinationNode == node);
+  }
 }
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index fc1b855..c62a340 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -24,16 +24,7 @@
 import 'abstract_single_unit.dart';
 
 /// A [NodeMatcher] that matches any node, and records what node it matched to.
-class AnyNodeMatcher implements NodeMatcher {
-  final List<NullabilityNode> _matchingNodes = [];
-
-  NullabilityNode get matchingNode => _matchingNodes.single;
-
-  @override
-  void matched(NullabilityNode node) {
-    _matchingNodes.add(node);
-  }
-
+class AnyNodeMatcher extends _RecordingNodeMatcher {
   @override
   bool matches(NullabilityNode node) {
     return true;
@@ -75,8 +66,12 @@
     parameters.addAll(named.entries.map((e) => ParameterElementImpl.synthetic(
         e.key, e.value.type, ParameterKind.NAMED)));
     return DecoratedType(
-        FunctionTypeImpl.synthetic(returnType.type, typeFormals, parameters,
-            nullabilitySuffix: NullabilitySuffix.star),
+        FunctionTypeImpl(
+          typeFormals: typeFormals,
+          parameters: parameters,
+          returnType: returnType.type,
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
         node ?? newNode(),
         typeFormalBounds: typeFormals
             .map((formal) => _decoratedTypeParameterBounds[formal])
@@ -153,11 +148,38 @@
 
 /// Mixin allowing unit tests to check for the presence of graph edges.
 mixin EdgeTester {
+  /// Gets the set of all nodes pointed to by always, plus always itself.
+  Set<NullabilityNode> get alwaysPlus {
+    var result = <NullabilityNode>{graph.always};
+    for (var edge in getEdges(graph.always, anyNode)) {
+      if (edge.guards.isEmpty) {
+        result.add(edge.destinationNode);
+      }
+    }
+    return result;
+  }
+
   /// Returns a [NodeMatcher] that matches any node whatsoever.
   AnyNodeMatcher get anyNode => AnyNodeMatcher();
 
   NullabilityGraphForTesting get graph;
 
+  /// Gets the transitive closure of all nodes with hard edges pointing to
+  /// never, plus never itself.
+  Set<NullabilityNode> get neverClosure {
+    var result = <NullabilityNode>{};
+    var pending = <NullabilityNode>[graph.never];
+    while (pending.isNotEmpty) {
+      var node = pending.removeLast();
+      if (result.add(node)) {
+        for (var edge in getEdges(anyNode, node)) {
+          pending.add(edge.sourceNode);
+        }
+      }
+    }
+    return result;
+  }
+
   /// Asserts that an edge exists with a node matching [source] and a node
   /// matching [destination], and with the given [hard]ness and [guards].
   ///
@@ -229,6 +251,9 @@
     return result;
   }
 
+  /// Returns a [NodeMatcher] that matches any node in the given set.
+  NodeSetMatcher inSet(Set<NullabilityNode> nodes) => NodeSetMatcher(nodes);
+
   /// Creates a [NodeMatcher] matching a substitution node whose inner and outer
   /// nodes match [inner] and [outer].
   ///
@@ -384,6 +409,16 @@
   bool matches(NullabilityNode node);
 }
 
+/// A [NodeMatcher] that matches any node contained in the given set.
+class NodeSetMatcher extends _RecordingNodeMatcher {
+  final Set<NullabilityNode> _targetSet;
+
+  NodeSetMatcher(this._targetSet);
+
+  @override
+  bool matches(NullabilityNode node) => _targetSet.contains(node);
+}
+
 /// A [NodeMatcher] that matches exactly one node.
 class _ExactNodeMatcher implements NodeMatcher {
   final NullabilityNode _expectation;
@@ -397,6 +432,18 @@
   bool matches(NullabilityNode node) => node == _expectation;
 }
 
+/// Base class for [NodeMatcher]s that remember which nodes were matched.
+abstract class _RecordingNodeMatcher implements NodeMatcher {
+  final List<NullabilityNode> _matchingNodes = [];
+
+  NullabilityNode get matchingNode => _matchingNodes.single;
+
+  @override
+  void matched(NullabilityNode node) {
+    _matchingNodes.add(node);
+  }
+}
+
 /// A [NodeMatcher] that matches a substitution node with the given inner and
 /// outer nodes.
 class _SubstitutionNodeMatcher implements NodeMatcher {
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index 16bef49..963d3cf 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -871,7 +871,7 @@
     expect(decoratedFunctionType('f').positionalParameters[0],
         same(decoratedType));
     expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
-    expect(decoratedType.type.toString(), 'T Function<T,U>(U)');
+    expect(decoratedType.type.toString(), 'T Function<T, U>(U)');
     expect(decoratedType.typeFormals, hasLength(2));
     var t = decoratedType.typeFormals[0];
     var u = decoratedType.typeFormals[1];
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index e2f9af1..b26acb9 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -16,9 +16,15 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 
-main() async {
+main(List<String> args) async {
+  if (args.length > 1) {
+    throw 'invalid args. Specify *one* argument to get exceptions of interest.';
+  }
+
+  warnOnNoAssertions();
+  String categoryOfInterest = args.isEmpty ? null : args.single;
   var rootUri = Platform.script.resolve('../../..');
-  var listener = _Listener();
+  var listener = _Listener(categoryOfInterest);
   for (var testPath in [
     'third_party/pkg/charcode',
     'third_party/pkg/collection',
@@ -72,18 +78,38 @@
   for (var entry in sortedExceptions) {
     print('  ${entry.key} (x${entry.value.length})');
   }
+
+  if (categoryOfInterest == null) {
+    print('\n(Note: to show stack traces & nodes for a particular failure,'
+        ' rerun with a search string as an argument.)');
+  }
 }
 
-/// Set this to a non-null value to cause any exception to be printed in full
-/// if its category contains the string.
-const String categoryOfInterest = null;
+void warnOnNoAssertions() {
+  try {
+    assert(false);
+  } catch (e) {
+    return;
+  }
 
-/// Set this to `true` to cause just the exception nodes to be printed when
-/// `categoryOfInterest` is non-null.  Set this to `false` to cause the full
-/// stack trace to be printed.
-const bool printExceptionNodeOnly = false;
+  print('''
+!!!
+!!! Warning! You didn't --enable-asserts!
+!!!
+''');
+}
 
 class _Listener implements NullabilityMigrationListener {
+  /// Set this to `true` to cause just the exception nodes to be printed when
+  /// `_Listener.categoryOfInterest` is non-null.  Set this to `false` to cause
+  /// the full stack trace to be printed.
+  /// TODO(mfairhurst): make this a cli flag?
+  static const bool printExceptionNodeOnly = false;
+
+  /// Set this to a non-null value to cause any exception to be printed in full
+  /// if its category contains the string.
+  final String categoryOfInterest;
+
   final groupedExceptions = <String, List<String>>{};
 
   int numExceptions = 0;
@@ -98,6 +124,8 @@
 
   int numDeadCodeSegmentsFound = 0;
 
+  _Listener(this.categoryOfInterest);
+
   @override
   void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
     if (edit.replacement == '?' && edit.length == 0) {
diff --git a/pkg/telemetry/lib/crash_reporting.dart b/pkg/telemetry/lib/crash_reporting.dart
index ef43e3a..415950c 100644
--- a/pkg/telemetry/lib/crash_reporting.dart
+++ b/pkg/telemetry/lib/crash_reporting.dart
@@ -7,22 +7,23 @@
 
 import 'package:http/http.dart' as http;
 import 'package:stack_trace/stack_trace.dart';
-import 'package:usage/usage.dart';
 
-// Reporting disabled until we're set up on the backend.
-const bool CRASH_REPORTING_DISABLED = true;
+import 'src/utils.dart';
+
+/// Tells crash backend that this is a Dart error (as opposed to, say, Java).
+const String _dartTypeId = 'DartError';
 
 /// Crash backend host.
 const String _crashServerHost = 'clients2.google.com';
 
 /// Path to the crash servlet.
-const String _crashEndpointPath = '/cr/report'; // or, staging_report
+const String _crashEndpointPath = '/cr/report'; // or, 'staging_report'
 
 /// The field corresponding to the multipart/form-data file attachment where
 /// crash backend expects to find the Dart stack trace.
 const String _stackTraceFileField = 'DartError';
 
-/// The name of the file attached as [stackTraceFileField].
+/// The name of the file attached as [_stackTraceFileField].
 ///
 /// The precise value is not important. It is ignored by the crash back end, but
 /// it must be supplied in the request.
@@ -35,42 +36,60 @@
   static final Uri _baseUri = new Uri(
       scheme: 'https', host: _crashServerHost, path: _crashEndpointPath);
 
+  static const int _maxReportsToSend = 1000;
+
   final String crashProductId;
-  final Analytics analytics;
+  final EnablementCallback shouldSend;
   final http.Client _httpClient;
 
-  /// Create a new [CrashReportSender], using the data from the given
-  /// [Analytics] instance.
-  CrashReportSender(this.crashProductId, this.analytics,
-      {http.Client httpClient})
-      : _httpClient = httpClient ?? new http.Client();
+  final ThrottlingBucket _throttle = ThrottlingBucket(10, Duration(minutes: 1));
+  int _reportsSend = 0;
+
+  /// Create a new [CrashReportSender].
+  CrashReportSender(
+    this.crashProductId,
+    this.shouldSend, {
+    http.Client httpClient,
+  }) : _httpClient = httpClient ?? new http.Client();
 
   /// Sends one crash report.
   ///
   /// The report is populated from data in [error] and [stackTrace].
   Future sendReport(dynamic error, {StackTrace stackTrace}) async {
-    if (!analytics.enabled || CRASH_REPORTING_DISABLED) {
+    if (!shouldSend()) {
+      return;
+    }
+
+    // Check if we've sent too many reports recently.
+    if (!_throttle.removeDrop()) {
+      return;
+    }
+
+    // Don't send too many total reports to crash reporting.
+    if (_reportsSend >= _maxReportsToSend) {
       return;
     }
 
     try {
+      final String dartVersion = Platform.version.split(' ').first;
+
       final Uri uri = _baseUri.replace(
         queryParameters: <String, String>{
-          'product': analytics.trackingId,
-          'version': analytics.applicationVersion,
+          'product': crashProductId,
+          'version': dartVersion,
         },
       );
 
       final http.MultipartRequest req = new http.MultipartRequest('POST', uri);
-      req.fields['uuid'] = analytics.clientId;
       req.fields['product'] = crashProductId;
-      req.fields['version'] = analytics.applicationVersion;
+      req.fields['version'] = dartVersion;
       req.fields['osName'] = Platform.operatingSystem;
       req.fields['osVersion'] = Platform.operatingSystemVersion;
-      req.fields['type'] = 'DartError';
+      req.fields['type'] = _dartTypeId;
       req.fields['error_runtime_type'] = '${error.runtimeType}';
+      req.fields['error_message'] = '$error';
 
-      final Chain chain = new Chain.parse(stackTrace.toString());
+      final Chain chain = new Chain.forTrace(stackTrace);
       req.files.add(new http.MultipartFile.fromString(
           _stackTraceFileField, chain.terse.toString(),
           filename: _stackTraceFilename));
@@ -94,3 +113,7 @@
     _httpClient.close();
   }
 }
+
+/// A typedef to allow crash reporting to query as to whether it should send a
+/// crash report.
+typedef bool EnablementCallback();
diff --git a/pkg/telemetry/lib/src/utils.dart b/pkg/telemetry/lib/src/utils.dart
new file mode 100644
index 0000000..04ddace
--- /dev/null
+++ b/pkg/telemetry/lib/src/utils.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math' as math;
+
+/// A throttling algorithm. This models the throttling after a bucket with
+/// water dripping into it at the rate of 1 drop per replenish duration. If the
+/// bucket has water when an operation is requested, 1 drop of water is removed
+/// and the operation is performed. If not the operation is skipped. This
+/// algorithm lets operations be performed in bursts without throttling, but
+/// holds the overall average rate of operations to 1 per replenish duration.
+class ThrottlingBucket {
+  final int bucketSize;
+  final Duration replenishDuration;
+
+  int _drops;
+  int _lastReplenish;
+
+  ThrottlingBucket(this.bucketSize, this.replenishDuration) {
+    _drops = bucketSize;
+    _lastReplenish = new DateTime.now().millisecondsSinceEpoch;
+  }
+
+  bool removeDrop() {
+    _checkReplenish();
+
+    if (_drops <= 0) {
+      return false;
+    } else {
+      _drops--;
+      return true;
+    }
+  }
+
+  void _checkReplenish() {
+    int now = new DateTime.now().millisecondsSinceEpoch;
+
+    int replenishMillis = replenishDuration.inMilliseconds;
+
+    if (_lastReplenish + replenishMillis >= now) {
+      int inc = (now - _lastReplenish) ~/ replenishMillis;
+      _drops = math.min(_drops + inc, bucketSize);
+      _lastReplenish += (replenishMillis * inc);
+    }
+  }
+}
diff --git a/pkg/telemetry/test/crash_reporting_test.dart b/pkg/telemetry/test/crash_reporting_test.dart
index 466e31e..f4867e4 100644
--- a/pkg/telemetry/test/crash_reporting_test.dart
+++ b/pkg/telemetry/test/crash_reporting_test.dart
@@ -24,18 +24,20 @@
     });
 
     test('CrashReportSender', () async {
+      EnablementCallback shouldSend = () {
+        return true;
+      };
+
       AnalyticsMock analytics = new AnalyticsMock()..enabled = true;
       CrashReportSender sender = new CrashReportSender(
-          analytics.trackingId, analytics,
+          analytics.trackingId, shouldSend,
           httpClient: mockClient);
 
       await sender.sendReport('test-error', stackTrace: StackTrace.current);
 
       String body = utf8.decode(request.bodyBytes);
       expect(body, contains('String')); // error.runtimeType
-      expect(body, contains(analytics.trackingId));
-      expect(body, contains('1.0.0'));
-      expect(body, contains(analytics.clientId));
-    }, skip: CRASH_REPORTING_DISABLED);
+      expect(body, contains('test-error'));
+    });
   });
 }
diff --git a/pkg/telemetry/test/utils_test.dart b/pkg/telemetry/test/utils_test.dart
new file mode 100644
index 0000000..2a9fcec
--- /dev/null
+++ b/pkg/telemetry/test/utils_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:telemetry/src/utils.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('ThrottlingBucket', () {
+    test('can send', () {
+      ThrottlingBucket bucket = new ThrottlingBucket(10, Duration(minutes: 1));
+      expect(bucket.removeDrop(), true);
+    });
+
+    test("doesn't send too many", () {
+      ThrottlingBucket bucket = new ThrottlingBucket(10, Duration(minutes: 1));
+      for (int i = 0; i < 10; i++) {
+        expect(bucket.removeDrop(), true);
+      }
+      expect(bucket.removeDrop(), false);
+    });
+  });
+}
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 9064cb5..ce68eba 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -679,10 +679,87 @@
     var progress = Progress.find(data["progress"] as String);
     var nnbdMode = NnbdMode.find(data["nnbd"] as String);
 
+    void addConfiguration(Configuration innerConfiguration,
+        [String namedConfiguration]) {
+      var configuration = TestConfiguration(
+          configuration: innerConfiguration,
+          progress: progress,
+          selectors: selectors,
+          testList: data["test_list_contents"] as List<String>,
+          repeat: data["repeat"] as int,
+          batch: !(data["noBatch"] as bool),
+          batchDart2JS: data["dart2js_batch"] as bool,
+          copyCoreDumps: data["copy_coredumps"] as bool,
+          isVerbose: data["verbose"] as bool,
+          listTests: data["list"] as bool,
+          listStatusFiles: data["list_status_files"] as bool,
+          cleanExit: data["clean_exit"] as bool,
+          silentFailures: data["silent_failures"] as bool,
+          printTiming: data["time"] as bool,
+          printReport: data["report"] as bool,
+          reportInJson: data["report_in_json"] as bool,
+          resetBrowser: data["reset_browser_configuration"] as bool,
+          skipCompilation: data["skip_compilation"] as bool,
+          writeDebugLog: data["write_debug_log"] as bool,
+          writeResults: data["write_results"] as bool,
+          writeLogs: data["write_logs"] as bool,
+          drtPath: data["drt"] as String,
+          chromePath: data["chrome"] as String,
+          safariPath: data["safari"] as String,
+          firefoxPath: data["firefox"] as String,
+          dartPath: data["dart"] as String,
+          dartPrecompiledPath: data["dart_precompiled"] as String,
+          genSnapshotPath: data["gen-snapshot"] as String,
+          keepGeneratedFiles: data["keep_generated_files"] as bool,
+          taskCount: data["tasks"] as int,
+          shardCount: data["shards"] as int,
+          shard: data["shard"] as int,
+          stepName: data["step_name"] as String,
+          testServerPort: data["test_server_port"] as int,
+          testServerCrossOriginPort:
+              data['test_server_cross_origin_port'] as int,
+          testDriverErrorPort: data["test_driver_error_port"] as int,
+          localIP: data["local_ip"] as String,
+          sharedOptions: sharedOptions,
+          packages: data["packages"] as String,
+          packageRoot: data["package_root"] as String,
+          suiteDirectory: data["suite_dir"] as String,
+          outputDirectory: data["output_directory"] as String,
+          reproducingArguments:
+              _reproducingCommand(data, namedConfiguration != null),
+          fastTestsOnly: data["fast_tests"] as bool,
+          printPassingStdout: data["print_passing_stdout"] as bool);
+
+      if (configuration.validate()) {
+        result.add(configuration);
+      }
+    }
+
+    String namedConfigurationOption = data["named_configuration"] as String;
+    if (namedConfigurationOption != null) {
+      List<String> namedConfigurations = namedConfigurationOption.split(',');
+      var testMatrixFile = "tools/bots/test_matrix.json";
+      var testMatrix = TestMatrix.fromPath(testMatrixFile);
+      for (String namedConfiguration in namedConfigurations) {
+        var configuration = testMatrix.configurations.singleWhere(
+            (c) => c.name == namedConfiguration,
+            orElse: () => null);
+        if (configuration == null) {
+          var names = testMatrix.configurations
+              .map((configuration) => configuration.name)
+              .toList();
+          names.sort();
+          _fail('The named configuration "$namedConfiguration" does not exist.'
+              ' The following configurations are available:\n'
+              '  * ${names.join('\n  * ')}');
+        }
+        addConfiguration(configuration);
+      }
+      return result;
+    }
+
     // Expand runtimes.
     for (var runtime in runtimes) {
-      // Start installing the runtime if needed.
-
       // Expand architectures.
       var architectures = data["arch"] as String;
       if (architectures == "all") {
@@ -700,82 +777,28 @@
           for (var modeName in modes.split(",")) {
             var mode = Mode.find(modeName);
             var system = System.find(data["system"] as String);
-            var namedConfiguration =
-                _namedConfiguration(data["named_configuration"] as String);
-            var innerConfiguration = namedConfiguration ??
-                Configuration("custom configuration", architecture, compiler,
-                    mode, runtime, system,
-                    nnbdMode: nnbdMode,
-                    timeout: data["timeout"] as int,
-                    enableAsserts: data["enable_asserts"] as bool,
-                    useAnalyzerCfe: data["use_cfe"] as bool,
-                    useAnalyzerFastaParser:
-                        data["analyzer_use_fasta_parser"] as bool,
-                    useBlobs: data["use_blobs"] as bool,
-                    useElf: data["use_elf"] as bool,
-                    useSdk: data["use_sdk"] as bool,
-                    useHotReload: data["hot_reload"] as bool,
-                    useHotReloadRollback: data["hot_reload_rollback"] as bool,
-                    isHostChecked: data["host_checked"] as bool,
-                    isCsp: data["csp"] as bool,
-                    isMinified: data["minified"] as bool,
-                    vmOptions: vmOptions,
-                    dart2jsOptions: dart2jsOptions,
-                    experiments: experiments,
-                    babel: data['babel'] as String,
-                    builderTag: data["builder_tag"] as String);
-            var configuration = TestConfiguration(
-                configuration: innerConfiguration,
-                progress: progress,
-                selectors: selectors,
-                testList: data["test_list_contents"] as List<String>,
-                repeat: data["repeat"] as int,
-                batch: !(data["noBatch"] as bool),
-                batchDart2JS: data["dart2js_batch"] as bool,
-                copyCoreDumps: data["copy_coredumps"] as bool,
-                isVerbose: data["verbose"] as bool,
-                listTests: data["list"] as bool,
-                listStatusFiles: data["list_status_files"] as bool,
-                cleanExit: data["clean_exit"] as bool,
-                silentFailures: data["silent_failures"] as bool,
-                printTiming: data["time"] as bool,
-                printReport: data["report"] as bool,
-                reportInJson: data["report_in_json"] as bool,
-                resetBrowser: data["reset_browser_configuration"] as bool,
-                skipCompilation: data["skip_compilation"] as bool,
-                writeDebugLog: data["write_debug_log"] as bool,
-                writeResults: data["write_results"] as bool,
-                writeLogs: data["write_logs"] as bool,
-                drtPath: data["drt"] as String,
-                chromePath: data["chrome"] as String,
-                safariPath: data["safari"] as String,
-                firefoxPath: data["firefox"] as String,
-                dartPath: data["dart"] as String,
-                dartPrecompiledPath: data["dart_precompiled"] as String,
-                genSnapshotPath: data["gen-snapshot"] as String,
-                keepGeneratedFiles: data["keep_generated_files"] as bool,
-                taskCount: data["tasks"] as int,
-                shardCount: data["shards"] as int,
-                shard: data["shard"] as int,
-                stepName: data["step_name"] as String,
-                testServerPort: data["test_server_port"] as int,
-                testServerCrossOriginPort:
-                    data['test_server_cross_origin_port'] as int,
-                testDriverErrorPort: data["test_driver_error_port"] as int,
-                localIP: data["local_ip"] as String,
-                sharedOptions: sharedOptions,
-                packages: data["packages"] as String,
-                packageRoot: data["package_root"] as String,
-                suiteDirectory: data["suite_dir"] as String,
-                outputDirectory: data["output_directory"] as String,
-                reproducingArguments:
-                    _reproducingCommand(data, namedConfiguration != null),
-                fastTestsOnly: data["fast_tests"] as bool,
-                printPassingStdout: data["print_passing_stdout"] as bool);
-
-            if (configuration.validate()) {
-              result.add(configuration);
-            }
+            var configuration = Configuration("custom configuration",
+                architecture, compiler, mode, runtime, system,
+                nnbdMode: nnbdMode,
+                timeout: data["timeout"] as int,
+                enableAsserts: data["enable_asserts"] as bool,
+                useAnalyzerCfe: data["use_cfe"] as bool,
+                useAnalyzerFastaParser:
+                    data["analyzer_use_fasta_parser"] as bool,
+                useBlobs: data["use_blobs"] as bool,
+                useElf: data["use_elf"] as bool,
+                useSdk: data["use_sdk"] as bool,
+                useHotReload: data["hot_reload"] as bool,
+                useHotReloadRollback: data["hot_reload_rollback"] as bool,
+                isHostChecked: data["host_checked"] as bool,
+                isCsp: data["csp"] as bool,
+                isMinified: data["minified"] as bool,
+                vmOptions: vmOptions,
+                dart2jsOptions: dart2jsOptions,
+                experiments: experiments,
+                babel: data['babel'] as String,
+                builderTag: data["builder_tag"] as String);
+            addConfiguration(configuration);
           }
         }
       }
@@ -934,25 +957,6 @@
   OptionParseException(this.message);
 }
 
-Configuration _namedConfiguration(String template) {
-  if (template == null) return null;
-
-  var testMatrixFile = "tools/bots/test_matrix.json";
-  var testMatrix = TestMatrix.fromPath(testMatrixFile);
-  var configuration = testMatrix.configurations
-      .singleWhere((c) => c.name == template, orElse: () => null);
-  if (configuration == null) {
-    var names = testMatrix.configurations
-        .map((configuration) => configuration.name)
-        .toList();
-    names.sort();
-    _fail('The named configuration "$template" does not exist. The following '
-        'configurations are available:\n  * ${names.join('\n  * ')}');
-  }
-
-  return configuration;
-}
-
 /// Throws an [OptionParseException] with [message].
 void _fail(String message) {
   throw OptionParseException(message);
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index 0d35524..be93c90 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -45,7 +45,6 @@
 
 Future testConfigurations(List<TestConfiguration> configurations) async {
   var startTime = DateTime.now();
-  var startStopwatch = Stopwatch()..start();
 
   // Extract global options from first configuration.
   var firstConf = configurations[0];
@@ -209,7 +208,7 @@
   }
 
   if (firstConf.writeResults) {
-    eventListener.add(ResultWriter(firstConf, startTime, startStopwatch));
+    eventListener.add(ResultWriter(firstConf.outputDirectory));
   }
 
   if (firstConf.copyCoreDumps) {
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 0389d59..6461397 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -708,15 +708,11 @@
 /// Writes a results.json file with a line for each test.
 /// Each line is a json map with the test name and result and expected result.
 class ResultWriter extends EventListener {
-  final TestConfiguration _configuration;
   final List<Map> _results = [];
   final List<Map> _logs = [];
   final String _outputDirectory;
-  final Stopwatch _startStopwatch;
-  final DateTime _startTime;
 
-  ResultWriter(this._configuration, this._startTime, this._startStopwatch)
-      : _outputDirectory = _configuration.outputDirectory;
+  ResultWriter(this._outputDirectory);
 
   void allTestsKnown() {
     // Write an empty result log file, that will be overwritten if any tests
@@ -729,10 +725,6 @@
       lines.map((l) => l + '\n').join();
 
   void done(TestCase test) {
-    if (_configuration != test.configuration) {
-      throw Exception("Two configurations in the same run. "
-          "Cannot output results for multiple configurations.");
-    }
     final name = test.displayName;
     final index = name.indexOf('/');
     final suite = name.substring(0, index);
@@ -742,7 +734,7 @@
 
     final record = {
       "name": name,
-      "configuration": _configuration.configuration.name,
+      "configuration": test.configuration.configuration.name,
       "suite": suite,
       "test_name": testName,
       "time_ms": time.inMilliseconds,
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 00753c0..00de5c9 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -682,7 +682,9 @@
 
     if (compiler.errors.isNotEmpty) {
       if (component != null) {
-        result = new CompilationResult.errors(compiler.errors,
+        result = new CompilationResult.errors(
+            compiler.errors,
+            // ignore: DEPRECATED_MEMBER_USE
             serializeComponent(component, filter: (lib) => !lib.isExternal));
       } else {
         result = new CompilationResult.errors(compiler.errors, null);
@@ -693,6 +695,7 @@
       // [kernelForProgram] is marked `external`, so we can use that bit to
       // decide what to exclude.
       result = new CompilationResult.ok(
+          // ignore: DEPRECATED_MEMBER_USE
           serializeComponent(component, filter: (lib) => !lib.isExternal));
     }
   } catch (error, stack) {
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
index 24d2fa0..ac3e756 100644
--- a/pkg/vm/bin/protobuf_aware_treeshaker.dart
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -29,7 +29,10 @@
 
 import 'package:args/args.dart';
 import 'package:kernel/kernel.dart';
+import 'package:kernel/binary/ast_to_binary.dart';
 import 'package:kernel/binary/limited_ast_to_binary.dart';
+import 'package:vm/kernel_front_end.dart'
+    show runGlobalTransformations, ErrorDetector;
 import 'package:kernel/target/targets.dart' show TargetFlags, getTarget;
 import 'package:meta/meta.dart';
 import 'package:vm/target/install.dart' show installAdditionalTargets;
@@ -45,14 +48,19 @@
     ..addOption('target',
         allowed: ['dart_runner', 'flutter', 'flutter-runner', 'vm'],
         defaultsTo: 'vm',
-        help: 'A platform.dill file to append to the input. If not given, no '
-            'platform.dill will be appended.')
+        help: 'Target platform.')
+    ..addFlag('aot',
+        help: 'If set, produces kernel file for AOT compilation (enables '
+            'global transformations). Otherwise, writes regular dill.',
+        defaultsTo: false)
+    ..addFlag('gen-bytecode',
+        help:
+            'If true, the kernel file will be output in bytecode format. Defaults to true if --aot, false otherwise')
     ..addFlag('write-txt',
         help: 'Also write the result in kernel-text format as <out.dill>.txt',
         defaultsTo: false)
     ..addFlag('remove-core-libs',
-        help:
-            'If set, the resulting dill file will not include `dart:` libraries',
+        help: 'If set, the output dill file will not include `dart:` libraries',
         defaultsTo: false)
     ..addMultiOption('define',
         abbr: 'D',
@@ -70,6 +78,7 @@
   } on FormatException catch (e) {
     print(e.message);
   }
+
   if (argResults == null || argResults['help'] || argResults.rest.length != 2) {
     String script = 'protobuf_aware_treeshaker.dart';
     print(
@@ -80,6 +89,11 @@
     exit(-1);
   }
 
+  if (argResults['aot'] && argResults['remove-core-libs']) {
+    print('The `--aot` option is incompatible with `--remove-core-libs`');
+    exit(-1);
+  }
+
   return argResults;
 }
 
@@ -103,22 +117,50 @@
 
   installAdditionalTargets();
 
-  treeshaker.TransformationInfo info = treeshaker.transformComponent(
-      component, environment, getTarget(argResults['target'], TargetFlags()),
-      collectInfo: argResults['verbose']);
+  final target = getTarget(argResults['target'], TargetFlags());
 
-  if (argResults['verbose']) {
-    for (String fieldName in info.removedMessageFields) {
-      print('Removed $fieldName');
-    }
-    for (Class removedClass in info.removedMessageClasses) {
-      print('Removed $removedClass');
+  // The [component] is treeshaken and has TFA annotations. Write output.
+  if (argResults['aot']) {
+    const bool useGlobalTypeFlowAnalysis = true;
+    const bool enableAsserts = false;
+    const bool useProtobufAwareTreeShaker = true;
+    final nopErrorDetector = ErrorDetector();
+    runGlobalTransformations(
+      target,
+      component,
+      useGlobalTypeFlowAnalysis,
+      enableAsserts,
+      useProtobufAwareTreeShaker,
+      nopErrorDetector,
+    );
+  } else {
+    treeshaker.TransformationInfo info = treeshaker.transformComponent(
+        component, environment, target,
+        collectInfo: argResults['verbose']);
+
+    if (argResults['verbose']) {
+      for (String fieldName in info.removedMessageFields) {
+        print('Removed $fieldName');
+      }
+      for (Class removedClass in info.removedMessageClasses) {
+        print('Removed $removedClass');
+      }
     }
   }
 
-  await writeComponent(component, output,
-      removeCoreLibs: argResults['remove-core-libs'],
-      removeSource: argResults['remove-source']);
+  if (argResults['aot']) {
+    // Write kernel file for AOT compilation.
+    final sink = File(output).openWrite();
+    final printer = BinaryPrinter(sink);
+    printer.writeComponentFile(component);
+    await sink.close();
+  } else {
+    // Clean out the AOT-only TFA annotations and write regular dill.
+    component.metadata.clear();
+    await writeComponent(component, output,
+        removeCoreLibs: argResults['remove-core-libs'],
+        removeSource: argResults['remove-source']);
+  }
   if (argResults['write-txt']) {
     writeComponentToText(component, path: output + '.txt');
   }
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index 912eede..10dd830 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -740,4 +740,10 @@
     emitSourcePosition();
     _emitInstructionD(Opcode.kNullCheck, rd);
   }
+
+  @pragma('vm:prefer-inline')
+  void emitInitLateField(int rd) {
+    emitSourcePosition();
+    _emitInstructionD(Opcode.kInitLateField, rd);
+  }
 }
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index ff4bc6d..a860cd6 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
 /// Before bumping current bytecode version format, make sure that
 /// all users have switched to a VM which is able to consume new
 /// version of bytecode.
-const int currentBytecodeFormatVersion = 25;
+const int currentBytecodeFormatVersion = 26;
 
 enum Opcode {
   kUnusedOpcode000,
@@ -181,9 +181,11 @@
   kStoreIndexedTOS,
   kUnused20,
 
+  // Late fields and variables.
+  kInitLateField,
+  kInitLateField_Wide,
+
   // Static fields.
-  kUnused40,
-  kUnused41,
   kStoreStaticTOS,
   kStoreStaticTOS_Wide,
 
@@ -412,6 +414,8 @@
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kStoreIndexedTOS: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kInitLateField: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kLoadStatic: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kStoreStaticTOS: const Format(
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index 6acb9ff..704bef6 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -329,7 +329,7 @@
 }
 
 class FieldDeclaration {
-  static const hasInitializerFlag = 1 << 0;
+  static const hasNontrivialInitializerFlag = 1 << 0;
   static const hasGetterFlag = 1 << 1;
   static const hasSetterFlag = 1 << 2;
   static const isReflectableFlag = 1 << 3;
@@ -346,6 +346,7 @@
   static const hasAttributesFlag = 1 << 14;
   static const isLateFlag = 1 << 15;
   static const isExtensionMemberFlag = 1 << 16;
+  static const hasInitializerFlag = 1 << 17;
 
   final int flags;
   final ObjectHandle name;
@@ -389,7 +390,7 @@
     if ((flags & hasInitializerCodeFlag) != 0) {
       writer.writeLinkOffset(initializerCode);
     }
-    if ((flags & hasInitializerFlag) == 0) {
+    if ((flags & hasNontrivialInitializerFlag) == 0) {
       writer.writePackedObject(value);
     }
     if ((flags & hasGetterFlag) != 0) {
@@ -421,8 +422,9 @@
     final initializerCode = ((flags & hasInitializerCodeFlag) != 0)
         ? reader.readLinkOffset<Code>()
         : null;
-    final value =
-        ((flags & hasInitializerFlag) == 0) ? reader.readPackedObject() : null;
+    final value = ((flags & hasNontrivialInitializerFlag) == 0)
+        ? reader.readPackedObject()
+        : null;
     final getterName =
         ((flags & hasGetterFlag) != 0) ? reader.readPackedObject() : null;
     final setterName =
@@ -484,11 +486,14 @@
     if ((flags & hasSourcePositionsFlag) != 0) {
       sb.write(', pos = $position, end-pos = $endPosition');
     }
+    if ((flags & hasInitializerFlag) != 0) {
+      sb.write(', has-initializer');
+    }
     sb.writeln();
     if ((flags & hasInitializerCodeFlag) != 0) {
       sb.write('    initializer\n$initializerCode\n');
     }
-    if ((flags & hasInitializerFlag) == 0) {
+    if ((flags & hasNontrivialInitializerFlag) == 0) {
       sb.write('    value = $value\n');
     }
     if ((flags & hasAnnotationsFlag) != 0) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 6b1b024..6e97d4a 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -207,6 +207,7 @@
 
   @override
   visitLibrary(Library node) {
+    // ignore: DEPRECATED_MEMBER_USE
     if (node.isExternal) {
       return;
     }
@@ -574,21 +575,24 @@
         value = _getConstant(field.initializer);
       }
     } else {
-      flags |= FieldDeclaration.hasInitializerFlag;
+      flags |= FieldDeclaration.hasNontrivialInitializerFlag;
     }
     if (initializer != null) {
       flags |= FieldDeclaration.hasInitializerCodeFlag;
     }
+    if (field.initializer != null) {
+      flags |= FieldDeclaration.hasInitializerFlag;
+    }
     final name = objectTable.getNameHandle(
         field.name.library, objectTable.mangleMemberName(field, false, false));
     ObjectHandle getterName;
     ObjectHandle setterName;
-    if (!field.isStatic || (initializer != null)) {
+    if (_needsGetter(field)) {
       flags |= FieldDeclaration.hasGetterFlag;
       getterName = objectTable.getNameHandle(
           field.name.library, objectTable.mangleMemberName(field, true, false));
     }
-    if (!field.isStatic && !field.isFinal) {
+    if (_needsSetter(field)) {
       flags |= FieldDeclaration.hasSetterFlag;
       setterName = objectTable.getNameHandle(
           field.name.library, objectTable.mangleMemberName(field, false, true));
@@ -949,9 +953,35 @@
   }
 
   bool hasInitializerCode(Field field) =>
-      (field.isStatic || options.emitInstanceFieldInitializers) &&
+      (field.isStatic ||
+          field.isLate ||
+          options.emitInstanceFieldInitializers) &&
       !_hasTrivialInitializer(field);
 
+  bool _needsGetter(Field field) {
+    // All instance fields need a getter.
+    if (!field.isStatic) return true;
+
+    // Static fields also need a getter if they have a non-trivial initializer,
+    // because it needs to be initialized lazily.
+    if (!_hasTrivialInitializer(field)) return true;
+
+    // Static late fields with no initializer also need a getter, to check if
+    // it's been initialized.
+    return field.isLate && field.initializer == null;
+  }
+
+  bool _needsSetter(Field field) {
+    // Static fields never need a setter.
+    if (field.isStatic) return false;
+
+    // Late instance fields always need a setter.
+    if (field.isLate) return true;
+
+    // Otherwise, the field only needs a setter if it isn't final.
+    return !field.isFinal;
+  }
+
   void _genNativeCall(String nativeName) {
     final function = enclosingMember.function;
     assert(function != null);
@@ -1120,14 +1150,20 @@
     if (!isRedirecting) {
       initializedFields = new Set<Field>();
       for (var field in node.enclosingClass.fields) {
-        if (!field.isStatic && field.initializer != null) {
-          if (initializedInInitializersList.contains(field)) {
-            // Do not store a value into the field as it is going to be
-            // overwritten by initializers list.
-            _generateNode(field.initializer);
-            asm.emitDrop1();
-          } else {
-            _genFieldInitializer(field, field.initializer);
+        if (!field.isStatic) {
+          if (field.isLate) {
+            if (!initializedInInitializersList.contains(field)) {
+              _genLateFieldInitializer(field);
+            }
+          } else if (field.initializer != null) {
+            if (initializedInInitializersList.contains(field)) {
+              // Do not store a value into the field as it is going to be
+              // overwritten by initializers list.
+              _generateNode(field.initializer);
+              asm.emitDrop1();
+            } else {
+              _genFieldInitializer(field, field.initializer);
+            }
           }
         }
       }
@@ -1138,7 +1174,9 @@
     if (!isRedirecting) {
       nullableFields = <ObjectHandle>[];
       for (var field in node.enclosingClass.fields) {
-        if (!field.isStatic && !initializedFields.contains(field)) {
+        if (!field.isStatic &&
+            !field.isLate &&
+            !initializedFields.contains(field)) {
           nullableFields.add(objectTable.getHandle(field));
         }
       }
@@ -1162,6 +1200,22 @@
     initializedFields.add(field);
   }
 
+  void _genLateFieldInitializer(Field field) {
+    assert(!field.isStatic);
+
+    if (field.initializer != null && _hasTrivialInitializer(field)) {
+      _genFieldInitializer(field, field.initializer);
+      return;
+    }
+
+    _genPushReceiver();
+
+    final int cpIndex = cp.addInstanceField(field);
+    asm.emitInitLateField(cpIndex);
+
+    initializedFields.add(field);
+  }
+
   void _genArguments(Expression receiver, Arguments arguments,
       {int storeReceiverToLocal}) {
     if (arguments.types.isNotEmpty) {
@@ -1893,6 +1947,14 @@
       _handleDefaultTypeArguments(function, done);
 
       asm.bind(done);
+    } else if (isClosure &&
+        !(parentFunction != null &&
+            parentFunction.dartAsyncMarker != AsyncMarker.Sync)) {
+      // Closures can be called dynamically with arbitrary arguments,
+      // so they should check number of type arguments, even if
+      // closure is not generic.
+      // Synthetic async_op closures don't need this check.
+      asm.emitCheckFunctionTypeArgs(0, locals.scratchVarIndexInFrame);
     }
 
     // Open initial scope before the first CheckStack, as VM might
@@ -1906,7 +1968,8 @@
         asm.localVariableTable
             .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
       }
-      if (locals.hasReceiver) {
+      if (locals.hasReceiver &&
+          (!isClosure || locals.isCaptured(locals.receiverVar))) {
         _declareLocalVariable(locals.receiverVar, function.fileOffset);
       }
       for (var v in function.positionalParameters) {
@@ -2116,7 +2179,7 @@
       assert(host.typeParameters.length == targetTypeParameters.length);
       for (int i = 0; i < targetTypeParameters.length; ++i) {
         map[targetTypeParameters[i]] =
-            new TypeParameterType(host.typeParameters[i]);
+            new TypeParameterType(host.typeParameters[i], Nullability.legacy);
       }
     }
     return Substitution.fromMap(map);
@@ -2304,7 +2367,7 @@
     final DartType bound = (forwardingTypeParameterBounds != null)
         ? forwardingTypeParameterBounds[typeParam]
         : typeParam.bound;
-    final DartType type = new TypeParameterType(typeParam);
+    final DartType type = new TypeParameterType(typeParam, Nullability.legacy);
     _genPushInstantiatorAndFunctionTypeArguments([type, bound]);
     asm.emitPushConstant(cp.addType(type));
     asm.emitPushConstant(cp.addType(bound));
@@ -3529,7 +3592,7 @@
     if (target is Field) {
       if (target.isConst) {
         _genPushConstExpr(target.initializer);
-      } else if (_hasTrivialInitializer(target)) {
+      } else if (!_needsGetter(target)) {
         asm.emitLoadStatic(cp.addStaticField(target));
       } else {
         _genDirectCall(target, objectTable.getArgDescHandle(0), 0,
diff --git a/pkg/vm/lib/bytecode/generics.dart b/pkg/vm/lib/bytecode/generics.dart
index 5e60ef1..4fe55e8 100644
--- a/pkg/vm/lib/bytecode/generics.dart
+++ b/pkg/vm/lib/bytecode/generics.dart
@@ -28,7 +28,7 @@
   }
   final types = new List<DartType>(typeParameters.length);
   for (int i = 0; i < typeParameters.length; ++i) {
-    types[i] = new TypeParameterType(typeParameters[i]);
+    types[i] = new TypeParameterType(typeParameters[i], Nullability.legacy);
   }
   return types;
 }
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 6261edb..88812ec 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -638,6 +638,14 @@
         _useVariable(_currentFrame.factoryTypeArgsVar);
       }
     }
+
+    // Erase promoted bound in type parameter types as it makes no
+    // difference at run time, but types which are different only in
+    // promoted bounds are not equal when compared using DartType.operator==,
+    // which prevents reusing of type arguments.
+    // See dartbug.com/39240 for context.
+    node.promotedBound = null;
+
     node.visitChildren(this);
   }
 
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 063361f..1d8e290 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -2323,8 +2323,8 @@
               (Reference fieldRef, Constant value) => new MapEntry(
                   objectTable.getHandle(fieldRef.asField),
                   objectTable.getHandle(value))),
-          objectTable.getHandle(
-              new InterfaceType(node.classNode, node.typeArguments))));
+          objectTable.getHandle(new InterfaceType(
+              node.classNode, Nullability.legacy, node.typeArguments))));
 
   @override
   ObjectHandle visitTearOffConstant(TearOffConstant node) =>
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 448405e..e35422e 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -106,7 +106,7 @@
       help:
           'Split resulting kernel file into multiple files (one per package).',
       defaultsTo: false);
-  args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: null);
+  args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false);
   args.addMultiOption('bytecode-options',
       help: 'Specify options for bytecode generation:',
       valueHelp: 'opt1,opt2,...',
@@ -157,7 +157,7 @@
   final bool tfa = options['tfa'];
   final bool linkPlatform = options['link-platform'];
   final bool embedSources = options['embed-sources'];
-  final bool genBytecode = options['gen-bytecode'] ?? aot;
+  final bool genBytecode = options['gen-bytecode'];
   final bool dropAST = options['drop-ast'];
   final bool enableAsserts = options['enable-asserts'];
   final bool useProtobufTreeShaker = options['protobuf-tree-shaker'];
@@ -169,6 +169,18 @@
     return badUsageExitCode;
   }
 
+  if (aot) {
+    if (!linkPlatform) {
+      print('Error: --no-link-platform option cannot be used with --aot');
+      return badUsageExitCode;
+    }
+    if (splitOutputByPackages) {
+      print(
+          'Error: --split-output-by-packages option cannot be used with --aot');
+      return badUsageExitCode;
+    }
+  }
+
   final BytecodeOptions bytecodeOptions = new BytecodeOptions(
     enableAsserts: enableAsserts,
     emitSourceFiles: embedSources,
@@ -308,12 +320,10 @@
 
   // Run global transformations only if component is correct.
   if (aot && component != null) {
-    await _runGlobalTransformations(
-        source,
-        options,
+    await runGlobalTransformations(
+        options.target,
         component,
         useGlobalTypeFlowAnalysis,
-        environmentDefines,
         enableAsserts,
         useProtobufTreeShaker,
         errorDetector);
@@ -363,12 +373,10 @@
   options.environmentDefines = environmentDefines;
 }
 
-Future _runGlobalTransformations(
-    Uri source,
-    CompilerOptions compilerOptions,
+Future runGlobalTransformations(
+    Target target,
     Component component,
     bool useGlobalTypeFlowAnalysis,
-    Map<String, String> environmentDefines,
     bool enableAsserts,
     bool useProtobufTreeShaker,
     ErrorDetector errorDetector) async {
@@ -389,8 +397,7 @@
   unreachable_code_elimination.transformComponent(component, enableAsserts);
 
   if (useGlobalTypeFlowAnalysis) {
-    globalTypeFlow.transformComponent(
-        compilerOptions.target, coreTypes, component);
+    globalTypeFlow.transformComponent(target, coreTypes, component);
   } else {
     devirtualization.transformComponent(coreTypes, component);
     no_dynamic_invocations_annotator.transformComponent(component);
@@ -404,8 +411,7 @@
     protobuf_tree_shaker.removeUnusedProtoReferences(
         component, coreTypes, null);
 
-    globalTypeFlow.transformComponent(
-        compilerOptions.target, coreTypes, component);
+    globalTypeFlow.transformComponent(target, coreTypes, component);
   }
 
   // TODO(35069): avoid recomputing CSA by reading it from the platform files.
@@ -669,6 +675,7 @@
 
 String packageFor(Library lib) {
   // Core libraries are not written into any package kernel binaries.
+  // ignore: DEPRECATED_MEMBER_USE
   if (lib.isExternal) return null;
 
   // Packages are written into their own kernel binaries.
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 2b10f69..ff8e4ca 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -91,6 +91,7 @@
   @override
   visitLibrary(Library node) {
     if (_trace) {
+      // ignore: DEPRECATED_MEMBER_USE
       String external = node.isExternal ? " (external)" : "";
       print("[devirt] Processing library ${node.name}${external}");
     }
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index e807469..4837963 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -299,10 +299,10 @@
     }
     if (kNativeTypeIntStart.index <= nativeType_.index &&
         nativeType_.index <= kNativeTypeIntEnd.index) {
-      return InterfaceType(intClass);
+      return InterfaceType(intClass, Nullability.legacy);
     }
     if (nativeType_ == NativeType.kFloat || nativeType_ == NativeType.kDouble) {
-      return InterfaceType(doubleClass);
+      return InterfaceType(doubleClass, Nullability.legacy);
     }
     if (nativeType_ == NativeType.kVoid) {
       return VoidType();
@@ -326,7 +326,7 @@
         .map((t) => convertNativeTypeToDartType(t, /*allowStructs=*/ false))
         .toList();
     if (argumentTypes.contains(null)) return null;
-    return FunctionType(argumentTypes, returnType);
+    return FunctionType(argumentTypes, returnType, Nullability.legacy);
   }
 
   NativeType getType(Class c) {
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 78d3d6a..249a45a 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -131,8 +131,10 @@
   bool _isPointerType(Field field) {
     return env.isSubtypeOf(
         field.type,
-        InterfaceType(pointerClass,
-            [InterfaceType(nativeTypesClasses[NativeType.kNativeType.index])]),
+        InterfaceType(pointerClass, Nullability.legacy, [
+          InterfaceType(nativeTypesClasses[NativeType.kNativeType.index],
+              Nullability.legacy)
+        ]),
         SubtypeCheckMode.ignoringNullabilities);
   }
 
@@ -163,8 +165,9 @@
             f.fileUri);
       } else {
         final DartType dartType = f.type;
-        final DartType nativeType =
-            InterfaceType(nativeTypesClasses[nativeTypeAnnos.first.index]);
+        final DartType nativeType = InterfaceType(
+            nativeTypesClasses[nativeTypeAnnos.first.index],
+            Nullability.legacy);
         // TODO(36730): Support structs inside structs.
         final DartType shouldBeDartType =
             convertNativeTypeToDartType(nativeType, /*allowStructs=*/ false);
@@ -266,12 +269,12 @@
   Expression _runtimeBranchOnLayout(Map<Abi, int> values) {
     return MethodInvocation(
         ConstantExpression(
-            ListConstant(InterfaceType(intClass), [
+            ListConstant(InterfaceType(intClass, Nullability.legacy), [
               IntConstant(values[Abi.wordSize64]),
               IntConstant(values[Abi.wordSize32Align32]),
               IntConstant(values[Abi.wordSize32Align64])
             ]),
-            InterfaceType(intClass)),
+            InterfaceType(intClass, Nullability.legacy)),
         Name("[]"),
         Arguments([StaticInvocation(abiMethod, Arguments([]))]),
         listElementAt);
@@ -285,8 +288,9 @@
       Field field, NativeType type, Map<Abi, int> offsets) {
     final DartType nativeType = type == NativeType.kPointer
         ? field.type
-        : InterfaceType(nativeTypesClasses[type.index]);
-    final DartType pointerType = InterfaceType(pointerClass, [nativeType]);
+        : InterfaceType(nativeTypesClasses[type.index], Nullability.legacy);
+    final DartType pointerType =
+        InterfaceType(pointerClass, Nullability.legacy, [nativeType]);
     final Name pointerName = Name('#_ptr_${field.name.name}');
 
     // Sample output:
@@ -371,7 +375,7 @@
         isStatic: true,
         isFinal: true,
         initializer: _runtimeBranchOnLayout(sizes),
-        type: InterfaceType(intClass));
+        type: InterfaceType(intClass, Nullability.legacy));
     _makeEntryPoint(sizeOf);
     struct.addMember(sizeOf);
   }
@@ -424,7 +428,7 @@
           pragmaName.reference: StringConstant("vm:entry-point"),
           pragmaOptions.reference: NullConstant()
         }),
-        InterfaceType(pragmaClass, [])));
+        InterfaceType(pragmaClass, Nullability.legacy, [])));
   }
 
   NativeType _getFieldType(Class c) {
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4bf6586..e8562ab 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -79,7 +79,7 @@
 
   @override
   visitClass(Class node) {
-    env.thisType = InterfaceType(node);
+    env.thisType = InterfaceType(node, Nullability.legacy);
     try {
       _ensureNotExtendsOrImplementsSealedClass(node);
       return super.visitClass(node);
@@ -125,8 +125,8 @@
     final Member target = node.target;
     try {
       if (target == fromFunctionMethod) {
-        final DartType nativeType =
-            InterfaceType(nativeFunctionClass, [node.arguments.types[0]]);
+        final DartType nativeType = InterfaceType(
+            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final Expression func = node.arguments.positional[0];
         final DartType dartType = func.getStaticType(env);
 
@@ -235,7 +235,7 @@
     final Arguments args = Arguments([
       node.arguments.positional.single
     ], types: [
-      InterfaceType(nativeFunctionClass, [nativeSignature])
+      InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeSignature])
     ]);
 
     final Expression lookupResult = MethodInvocation(
@@ -260,11 +260,12 @@
   // Creating this closure requires a runtime call, so we save the result in a
   // synthetic top-level field to avoid recomputing it.
   Expression _replaceFromFunction(StaticInvocation node) {
-    final nativeFunctionType =
-        InterfaceType(nativeFunctionClass, node.arguments.types);
+    final nativeFunctionType = InterfaceType(
+        nativeFunctionClass, Nullability.legacy, node.arguments.types);
     final Field field = Field(
         Name("_#ffiCallback${callbackCount++}", currentLibrary),
-        type: InterfaceType(pointerClass, [nativeFunctionType]),
+        type: InterfaceType(
+            pointerClass, Nullability.legacy, [nativeFunctionType]),
         initializer: StaticInvocation(
             pointerFromFunctionProcedure,
             Arguments([
@@ -289,8 +290,8 @@
       // in 'dynamic_library_patch.dart'. Dynamic invocations of 'asFunction'
       // and 'lookupFunction' are not legal and throw a runtime exception.
       if (target == lookupFunctionMethod) {
-        final DartType nativeType =
-            InterfaceType(nativeFunctionClass, [node.arguments.types[0]]);
+        final DartType nativeType = InterfaceType(
+            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final DartType dartType = node.arguments.types[1];
 
         _ensureNativeTypeValid(nativeType, node);
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 73c7e0b..610a20d 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -59,6 +59,7 @@
 
   @override
   TreeNode visitLibrary(Library node) {
+    // ignore: DEPRECATED_MEMBER_USE
     if (!node.isExternal) {
       transformList(node.classes, this, node);
     }
@@ -67,6 +68,7 @@
 
   @override
   TreeNode visitClass(Class c) {
+    // ignore: DEPRECATED_MEMBER_USE
     if (c.enclosingLibrary.isExternal) {
       return c;
     }
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
index 5c35c72..a272248 100644
--- a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -224,7 +224,9 @@
               NullLiteral(), // valueOf
               NullLiteral(), // enumValues
             ],
-            types: <DartType>[InterfaceType(coreTypes.nullClass)],
+            types: <DartType>[
+              InterfaceType(coreTypes.nullClass, Nullability.nullable)
+            ],
           ),
         );
       }
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 285b3ac..259d06e 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -952,8 +952,8 @@
     final cached = useCache ? cachedFlattenedTypeArgs[klass] : null;
     if (cached != null) return cached;
 
-    final flattenedTypeArguments = List<DartType>.from(
-        klass.typeParameters.map((t) => new TypeParameterType(t)));
+    final flattenedTypeArguments = List<DartType>.from(klass.typeParameters
+        .map((t) => new TypeParameterType(t, Nullability.legacy)));
 
     for (final Supertype intf in hierarchy.genericSupertypesOf(klass)) {
       int offset = findOverlap(flattenedTypeArguments, intf.typeArguments);
@@ -1528,7 +1528,8 @@
     if (field.isStatic) {
       fieldValue.setValue(value, this, /*receiver_type=*/ null);
     } else {
-      final receiver = new Type.cone(new InterfaceType(field.parent));
+      final receiver =
+          new Type.cone(new InterfaceType(field.parent, Nullability.legacy));
       fieldValue.setValue(value, this, receiver);
     }
   }
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index 01529f7..efcf37f 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -403,7 +403,7 @@
       if (computed is AnyType) return const AnyType();
       types[i] = computed;
     }
-    return new RuntimeType(new InterfaceType(klass), types);
+    return new RuntimeType(new InterfaceType(klass, Nullability.legacy), types);
   }
 }
 
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index b3e7028..23902dc 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -1556,7 +1556,8 @@
     }
 
     if (createRuntimeType) {
-      return new RuntimeType(new InterfaceType(type.classNode),
+      return new RuntimeType(
+          new InterfaceType(type.classNode, Nullability.legacy),
           new List<RuntimeType>.from(flattenedTypeExprs));
     } else {
       final instantiate =
@@ -1606,14 +1607,13 @@
 }
 
 class CreateAllSummariesVisitor extends RecursiveVisitor<Null> {
-  final TypeEnvironment _environment;
   final SummaryCollector _summaryCollector;
 
-  CreateAllSummariesVisitor(Target target, this._environment,
+  CreateAllSummariesVisitor(Target target, TypeEnvironment environment,
       ClassHierarchy hierarchy, GenericInterfacesInfo genericInterfacesInfo)
       : _summaryCollector = new SummaryCollector(
             target,
-            _environment,
+            environment,
             hierarchy,
             new EmptyEntryPointsListener(),
             new NativeCodeOracle(null, null),
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4b5a7a1..4f5bf7b 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -59,9 +59,9 @@
     // TODO(alexmarkov): cache the created raw type or use a CoreTypes object
     return new InterfaceType(
         type.classNode,
+        Nullability.legacy,
         new List<DartType>.filled(
-            type.classNode.typeParameters.length, const DynamicType()),
-        Nullability.legacy);
+            type.classNode.typeParameters.length, const DynamicType()));
   } else if (type is FunctionType) {
     // TODO(alexmarkov): support function types
     return const DynamicType();
@@ -871,7 +871,7 @@
           .take(klass.typeParameters.length)
           .map((pt) => pt.representedType)
           .toList();
-      return new InterfaceType(klass, typeArguments);
+      return new InterfaceType(klass, Nullability.legacy, typeArguments);
     } else {
       return _type;
     }
diff --git a/pkg/vm/test/bytecode/object_table_test.dart b/pkg/vm/test/bytecode/object_table_test.dart
index 75ad973..98923e8 100644
--- a/pkg/vm/test/bytecode/object_table_test.dart
+++ b/pkg/vm/test/bytecode/object_table_test.dart
@@ -81,8 +81,10 @@
   });
 
   test('simple-types', () {
-    final h1a = objectTable.getHandle(new InterfaceType(coreTypes.intClass));
-    final h1b = objectTable.getHandle(new InterfaceType(coreTypes.intClass));
+    final h1a = objectTable
+        .getHandle(new InterfaceType(coreTypes.intClass, Nullability.legacy));
+    final h1b = objectTable
+        .getHandle(new InterfaceType(coreTypes.intClass, Nullability.legacy));
     final h2a = objectTable.getHandle(const DynamicType());
     final h2b = objectTable.getHandle(new DynamicType());
     Expect.identical(h1a, h1b);
@@ -92,20 +94,28 @@
     Expect.equals(true, h2a.isCacheable);
     Expect.equals(false, h1a.shouldBeIncludedIntoIndexTable); // 2 uses
     objectTable.getHandle(new InterfaceType(
-        coreTypes.listClass, [new InterfaceType(coreTypes.intClass)]));
+        coreTypes.listClass,
+        Nullability.legacy,
+        [new InterfaceType(coreTypes.intClass, Nullability.legacy)]));
     Expect.equals(true, h1a.shouldBeIncludedIntoIndexTable); // 3 uses
   });
 
   test('recursive-types', () {
     final base = addClass(lib1, "Base", [new TypeParameter("T")]);
     final derived1 = addClass(lib1, "Derived");
-    derived1.supertype = new Supertype(base, [new InterfaceType(derived1)]);
+    derived1.supertype =
+        new Supertype(base, [new InterfaceType(derived1, Nullability.legacy)]);
     final derived2 = addClass(lib2, "Derived");
-    derived2.supertype = new Supertype(base, [new InterfaceType(derived2)]);
-    final h1a = objectTable.getHandle(new InterfaceType(derived1));
-    final h1b = objectTable.getHandle(new InterfaceType(derived1));
-    final h2a = objectTable.getHandle(new InterfaceType(derived2));
-    final h2b = objectTable.getHandle(new InterfaceType(derived2));
+    derived2.supertype =
+        new Supertype(base, [new InterfaceType(derived2, Nullability.legacy)]);
+    final h1a =
+        objectTable.getHandle(new InterfaceType(derived1, Nullability.legacy));
+    final h1b =
+        objectTable.getHandle(new InterfaceType(derived1, Nullability.legacy));
+    final h2a =
+        objectTable.getHandle(new InterfaceType(derived2, Nullability.legacy));
+    final h2b =
+        objectTable.getHandle(new InterfaceType(derived2, Nullability.legacy));
     Expect.identical(h1a, h1b);
     Expect.identical(h2a, h2b);
     Expect.notEquals(h1a, h2a);
diff --git a/pkg/vm/test/bytecode/recursive_types_validator_test.dart b/pkg/vm/test/bytecode/recursive_types_validator_test.dart
index 44c4522..6e27e46 100644
--- a/pkg/vm/test/bytecode/recursive_types_validator_test.dart
+++ b/pkg/vm/test/bytecode/recursive_types_validator_test.dart
@@ -29,8 +29,8 @@
     Component component = createMockSdkComponent();
     CoreTypes coreTypes = new CoreTypes(component);
     objectSuper = coreTypes.objectClass.asThisSupertype;
-    intType = new InterfaceType(coreTypes.intClass);
-    doubleType = new InterfaceType(coreTypes.doubleClass);
+    intType = new InterfaceType(coreTypes.intClass, Nullability.legacy);
+    doubleType = new InterfaceType(coreTypes.doubleClass, Nullability.legacy);
 
     // Add the test library.
     lib = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'lib');
@@ -49,9 +49,10 @@
     // class Derived<T> extends Base<Derived<T>>
     TypeParameter t = new TypeParameter('T');
     Class derived = addClass('Derived', [t]);
-    DartType derivedOfT =
-        new InterfaceType(derived, [new TypeParameterType(t)]);
-    DartType derivedOfInt = new InterfaceType(derived, [intType]);
+    DartType derivedOfT = new InterfaceType(derived, Nullability.legacy,
+        [new TypeParameterType(t, Nullability.legacy)]);
+    DartType derivedOfInt =
+        new InterfaceType(derived, Nullability.legacy, [intType]);
     derived.supertype = new Supertype(base, [derivedOfT]);
 
     validator.validateType(derivedOfT);
@@ -65,10 +66,12 @@
     // class Derived<T> extends Base<Derived<Derived<int>>>
     TypeParameter t = new TypeParameter('T');
     Class derived = addClass('Derived', [t]);
-    DartType derivedOfT =
-        new InterfaceType(derived, [new TypeParameterType(t)]);
-    DartType derivedOfInt = new InterfaceType(derived, [intType]);
-    DartType derivedOfDerivedOfInt = new InterfaceType(derived, [derivedOfInt]);
+    DartType derivedOfT = new InterfaceType(derived, Nullability.legacy,
+        [new TypeParameterType(t, Nullability.legacy)]);
+    DartType derivedOfInt =
+        new InterfaceType(derived, Nullability.legacy, [intType]);
+    DartType derivedOfDerivedOfInt =
+        new InterfaceType(derived, Nullability.legacy, [derivedOfInt]);
     derived.supertype = new Supertype(base, [derivedOfDerivedOfInt]);
 
     validator.validateType(derivedOfT);
@@ -83,10 +86,12 @@
     // class Derived<T> extends Base<Derived<Derived<T>>>
     TypeParameter t = new TypeParameter('T');
     Class derived = addClass('Derived', [t]);
-    DartType derivedOfT =
-        new InterfaceType(derived, [new TypeParameterType(t)]);
-    DartType derivedOfInt = new InterfaceType(derived, [intType]);
-    DartType derivedOfDerivedOfT = new InterfaceType(derived, [derivedOfT]);
+    DartType derivedOfT = new InterfaceType(derived, Nullability.legacy,
+        [new TypeParameterType(t, Nullability.legacy)]);
+    DartType derivedOfInt =
+        new InterfaceType(derived, Nullability.legacy, [intType]);
+    DartType derivedOfDerivedOfT =
+        new InterfaceType(derived, Nullability.legacy, [derivedOfT]);
     derived.supertype = new Supertype(base, [derivedOfDerivedOfT]);
 
     Expect.throws(() {
@@ -109,21 +114,23 @@
     TypeParameter v = new TypeParameter('V');
     Class derived2 = addClass('Derived2', [v]);
 
-    DartType derived2OfU =
-        new InterfaceType(derived2, [new TypeParameterType(u)]);
+    DartType derived2OfU = new InterfaceType(derived2, Nullability.legacy,
+        [new TypeParameterType(u, Nullability.legacy)]);
     derived1.supertype = new Supertype(base, [derived2OfU]);
 
-    DartType derived1OfV =
-        new InterfaceType(derived1, [new TypeParameterType(v)]);
+    DartType derived1OfV = new InterfaceType(derived1, Nullability.legacy,
+        [new TypeParameterType(v, Nullability.legacy)]);
     derived2.supertype = new Supertype(base, [derived1OfV]);
 
-    DartType derived1OfU =
-        new InterfaceType(derived1, [new TypeParameterType(u)]);
-    DartType derived1OfInt = new InterfaceType(derived1, [intType]);
+    DartType derived1OfU = new InterfaceType(derived1, Nullability.legacy,
+        [new TypeParameterType(u, Nullability.legacy)]);
+    DartType derived1OfInt =
+        new InterfaceType(derived1, Nullability.legacy, [intType]);
 
-    DartType derived2OfV =
-        new InterfaceType(derived2, [new TypeParameterType(v)]);
-    DartType derived2OfInt = new InterfaceType(derived2, [intType]);
+    DartType derived2OfV = new InterfaceType(derived2, Nullability.legacy,
+        [new TypeParameterType(v, Nullability.legacy)]);
+    DartType derived2OfInt =
+        new InterfaceType(derived2, Nullability.legacy, [intType]);
 
     validator.validateType(derived1OfU);
     Expect.isTrue(validator.isRecursive(derived1OfU));
@@ -149,11 +156,13 @@
     TypeParameter q2 = new TypeParameter('Q2');
     Class e = addClass('E', [q1, q2]);
 
-    DartType eOfQ1Int =
-        new InterfaceType(e, [new TypeParameterType(q1), intType]);
-    e.supertype = new Supertype(f, [eOfQ1Int, new TypeParameterType(q2)]);
+    DartType eOfQ1Int = new InterfaceType(e, Nullability.legacy,
+        [new TypeParameterType(q1, Nullability.legacy), intType]);
+    e.supertype = new Supertype(
+        f, [eOfQ1Int, new TypeParameterType(q2, Nullability.legacy)]);
 
-    DartType eOfIntDouble = new InterfaceType(e, [intType, doubleType]);
+    DartType eOfIntDouble =
+        new InterfaceType(e, Nullability.legacy, [intType, doubleType]);
 
     validator.validateType(eOfIntDouble);
     validator.validateType(e.thisType);
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 3d2dc5d..1689617 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -49,10 +49,11 @@
   test('factory-constructors', () {
     Class c1 = new Class(name: 'C1');
     Class c2 = new Class(name: 'C2', typeParameters: [new TypeParameter('E')]);
-    InterfaceType t1 = new InterfaceType(c1);
-    InterfaceType t2Raw = new InterfaceType(c2);
-    InterfaceType t2Generic = new InterfaceType(c2, [t1]);
-    FunctionType f1 = new FunctionType([t1], const VoidType());
+    InterfaceType t1 = new InterfaceType(c1, Nullability.legacy);
+    InterfaceType t2Raw = new InterfaceType(c2, Nullability.legacy);
+    InterfaceType t2Generic = new InterfaceType(c2, Nullability.legacy, [t1]);
+    FunctionType f1 =
+        new FunctionType([t1], const VoidType(), Nullability.legacy);
 
     expect(new Type.empty(), equals(const EmptyType()));
 
@@ -85,10 +86,14 @@
   test('union-intersection', () {
     // T1 <: T3, T2 <: T3
 
-    InterfaceType t1 = new InterfaceType(new Class(name: 'T1'));
-    InterfaceType t2 = new InterfaceType(new Class(name: 'T2'));
-    InterfaceType t3 = new InterfaceType(new Class(name: 'T3'));
-    InterfaceType t4 = new InterfaceType(new Class(name: 'T4'));
+    InterfaceType t1 =
+        new InterfaceType(new Class(name: 'T1'), Nullability.legacy);
+    InterfaceType t2 =
+        new InterfaceType(new Class(name: 'T2'), Nullability.legacy);
+    InterfaceType t3 =
+        new InterfaceType(new Class(name: 'T3'), Nullability.legacy);
+    InterfaceType t4 =
+        new InterfaceType(new Class(name: 'T4'), Nullability.legacy);
 
     final empty = new EmptyType();
     final any = new AnyType();
@@ -275,12 +280,13 @@
     final c2 = new Class(name: 'C2');
     final c3 = new Class(name: 'C3');
 
-    final t1a = new InterfaceType(c1);
-    final t1b = new InterfaceType(c1);
-    final t2 = new InterfaceType(c2);
-    final f1a = new FunctionType([t1a], const VoidType());
-    final f1b = new FunctionType([t1b], const VoidType());
-    final f2 = new FunctionType([t1a, t1a], const VoidType());
+    final t1a = new InterfaceType(c1, Nullability.legacy);
+    final t1b = new InterfaceType(c1, Nullability.legacy);
+    final t2 = new InterfaceType(c2, Nullability.legacy);
+    final f1a = new FunctionType([t1a], const VoidType(), Nullability.legacy);
+    final f1b = new FunctionType([t1b], const VoidType(), Nullability.legacy);
+    final f2 =
+        new FunctionType([t1a, t1a], const VoidType(), Nullability.legacy);
 
     final cid1 = const IntClassId(1);
     final cid2 = const IntClassId(2);
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index b186fa7..224709f 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -9,7 +9,7 @@
 
 Class '', script = '#lib'
 
-Field 'asyncInFieldInitializer', type = FunctionType (dart:async::Future < dart:core::int >) -> dart:async::Future < dart:core::Null >, getter = 'get:asyncInFieldInitializer', reflectable, static
+Field 'asyncInFieldInitializer', type = FunctionType (dart:async::Future < dart:core::int >) -> dart:async::Future < dart:core::Null >, getter = 'get:asyncInFieldInitializer', reflectable, static, has-initializer
     initializer
 Bytecode {
   Entry                3
@@ -73,6 +73,7 @@
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   AllocateContext      0, 9
   PopLocal             r0
@@ -1560,6 +1561,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   AllocateContext      1, 9
   StoreLocal           r1
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index 0bd9929..b06373c 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -9,13 +9,13 @@
 
 Class '', script = '#lib'
 
-Field '_stdinFD', type = dart:core::int, reflectable, static
+Field '_stdinFD', type = dart:core::int, reflectable, static, has-initializer
     value = const 0
 
-Field '_stdoutFD', type = dart:core::int, reflectable, static
+Field '_stdoutFD', type = dart:core::int, reflectable, static, has-initializer
     value = const 1
 
-Field '_stderrFD', type = dart:core::int, reflectable, static
+Field '_stderrFD', type = dart:core::int, reflectable, static, has-initializer
     value = const 2
 
 Field '_rawScript', type = dart:core::String, reflectable, static
@@ -238,7 +238,7 @@
 Class '_ScheduleImmediate', script = '#lib'
     extends dart:core::Object
 
-Field '_closure', type = FunctionType (FunctionType () -> void) -> void, reflectable, static
+Field '_closure', type = FunctionType (FunctionType () -> void) -> void, reflectable, static, has-initializer
     value = null
 
 Function '', constructor, reflectable
@@ -263,7 +263,7 @@
     extends dart:core::Object
     implements [#lib::_Namespace]
 
-Field '_cachedNamespace', type = #lib::_NamespaceImpl, reflectable, static
+Field '_cachedNamespace', type = #lib::_NamespaceImpl, reflectable, static, has-initializer
     value = null
 
 Function '_', constructor, reflectable, debuggable
@@ -488,37 +488,37 @@
 Class 'VMLibraryHooks', script = '#lib'
     extends dart:core::Object
 
-Field 'timerFactory', type = dynamic, reflectable, static
+Field 'timerFactory', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'eventHandlerSendData', type = dynamic, reflectable, static
+Field 'eventHandlerSendData', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'timerMillisecondClock', type = dynamic, reflectable, static
+Field 'timerMillisecondClock', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'resourceReadAsBytes', type = dynamic, reflectable, static
+Field 'resourceReadAsBytes', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'packageRootString', type = dynamic, reflectable, static
+Field 'packageRootString', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'packageConfigString', type = dynamic, reflectable, static
+Field 'packageConfigString', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'packageRootUriFuture', type = dynamic, reflectable, static
+Field 'packageRootUriFuture', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'packageConfigUriFuture', type = dynamic, reflectable, static
+Field 'packageConfigUriFuture', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field 'resolvePackageUriFuture', type = dynamic, reflectable, static
+Field 'resolvePackageUriFuture', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field '_computeScriptUri', type = dynamic, reflectable, static
+Field '_computeScriptUri', type = dynamic, reflectable, static, has-initializer
     value = null
 
-Field '_cachedScript', type = dynamic, reflectable, static
+Field '_cachedScript', type = dynamic, reflectable, static, has-initializer
     value = null
 
 Function '', constructor, reflectable
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 1297978..383b1c0 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -69,6 +69,7 @@
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   JumpIfUnchecked      L1
   Push                 FP[-5]
@@ -768,6 +769,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
+  CheckFunctionTypeArgs 0, r2
   CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#6
@@ -847,7 +849,7 @@
 Class 'B', script = '#lib'
     extends dart:core::Object
 
-Field 'foo', type = dart:core::int, getter = 'get:foo', setter = 'set:foo', reflectable
+Field 'foo', type = dart:core::int, getter = 'get:foo', setter = 'set:foo', reflectable, has-initializer
     value = null
 
 Function '', constructor, reflectable
@@ -987,6 +989,7 @@
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   AllocateContext      1, 2
   StoreLocal           r1
@@ -1057,6 +1060,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextParent
@@ -1085,6 +1089,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextVar       0, 0
@@ -1242,6 +1247,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#5
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextVar       1, 0
@@ -1258,6 +1264,7 @@
   Push                 FP[-6]
   LoadFieldTOS         CP#5
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   JumpIfUnchecked      L1
   Push                 FP[-5]
@@ -1360,6 +1367,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#7
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   Push                 r0
@@ -1457,6 +1465,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#5
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextVar       0, 0
@@ -1515,6 +1524,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   AllocateClosure      CP#3
   StoreLocal           r3
@@ -1548,6 +1558,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   PushNull
   ReturnTOS
@@ -1556,7 +1567,7 @@
 Class 'E', script = '#lib', abstract
     extends dart:core::Object
 
-Field 'foo1', type = FunctionType (dart:core::int, dart:core::int) -> dart:core::int, getter = 'get:foo1', setter = 'set:foo1', reflectable
+Field 'foo1', type = FunctionType (dart:core::int, dart:core::int) -> dart:core::int, getter = 'get:foo1', setter = 'set:foo1', reflectable, has-initializer
     value = null
 
 Function '', constructor, reflectable
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
index 0f6d5a0..ce083da 100644
--- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -29,16 +29,16 @@
 Field 'foo1', type = dart:core::int, getter = 'get:foo1', setter = 'set:foo1', reflectable
     value = null
 
-Field 'foo2', type = dart:core::int, getter = 'get:foo2', setter = 'set:foo2', reflectable
+Field 'foo2', type = dart:core::int, getter = 'get:foo2', setter = 'set:foo2', reflectable, has-initializer
     value = null
 
-Field 'foo3', type = dart:core::int, getter = 'get:foo3', setter = 'set:foo3', reflectable
+Field 'foo3', type = dart:core::int, getter = 'get:foo3', setter = 'set:foo3', reflectable, has-initializer
     value = const 42
 
 Field 'foo4', type = dart:core::int, getter = 'get:foo4', setter = 'set:foo4', reflectable
     value = null
 
-Field 'foo5', type = dart:core::int, getter = 'get:foo5', setter = 'set:foo5', reflectable
+Field 'foo5', type = dart:core::int, getter = 'get:foo5', setter = 'set:foo5', reflectable, has-initializer
     value = const 43
 
 Function '', constructor, reflectable, debuggable
@@ -162,13 +162,13 @@
 Class 'B', script = '#lib'
     extends #lib::A
 
-Field 'foo6', type = dart:core::int, getter = 'get:foo6', setter = 'set:foo6', reflectable
+Field 'foo6', type = dart:core::int, getter = 'get:foo6', setter = 'set:foo6', reflectable, has-initializer
     value = const 46
 
-Field 'foo7', type = dart:core::int, reflectable, static
+Field 'foo7', type = dart:core::int, reflectable, static, has-initializer
     value = const 47
 
-Field 'foo8', type = dart:core::int, reflectable, static, const, final
+Field 'foo8', type = dart:core::int, reflectable, static, const, final, has-initializer
     value = const 48
 
 Function '', constructor, reflectable, debuggable
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index cb085fd..b3d07d01 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -217,10 +217,10 @@
     type-params <dart:core::Object T1, dart:core::Object T2> (args: 2)
     extends dart:core::Object
 
-Field 't1', type = #lib::Base::TypeParam/0, getter = 'get:t1', setter = 'set:t1', reflectable
+Field 't1', type = #lib::Base::TypeParam/0, getter = 'get:t1', setter = 'set:t1', reflectable, has-initializer
     value = null
 
-Field 't2', type = #lib::Base::TypeParam/1, getter = 'get:t2', setter = 'set:t2', reflectable
+Field 't2', type = #lib::Base::TypeParam/1, getter = 'get:t2', setter = 'set:t2', reflectable, has-initializer
     value = null
 
 Function '', constructor, reflectable, debuggable
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index b698f7ce..e90a55c 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -9,7 +9,7 @@
 
 Class '', script = '#lib'
 
-Field 'c1', type = #lib::A, getter = 'get:c1', reflectable, static, const, final
+Field 'c1', type = #lib::A, getter = 'get:c1', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -22,13 +22,13 @@
 }
 
 
-Field 'c2', type = dart:core::String, reflectable, static, const, final
+Field 'c2', type = dart:core::String, reflectable, static, const, final, has-initializer
     value = 'hello!'
 
-Field 'c3', type = dart:core::int, reflectable, static, const, final
+Field 'c3', type = dart:core::int, reflectable, static, const, final, has-initializer
     value = const 6
 
-Field 'c4', type = #lib::C, getter = 'get:c4', reflectable, static, const, final
+Field 'c4', type = #lib::C, getter = 'get:c4', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -41,7 +41,7 @@
 }
 
 
-Field 'c5', type = #lib::D, getter = 'get:c5', reflectable, static, const, final
+Field 'c5', type = #lib::D, getter = 'get:c5', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -54,7 +54,7 @@
 }
 
 
-Field 'fieldWithDoubleLiteralInitializer', type = dart:core::double, reflectable, static
+Field 'fieldWithDoubleLiteralInitializer', type = dart:core::double, reflectable, static, has-initializer
     value = const 1.0
 
 Function 'test_constants1', static, reflectable, debuggable
@@ -420,7 +420,7 @@
 Field '_name', type = dart:core::String, getter = 'get:_name', reflectable, final
     value = null
 
-Field 'values', type = dart:core::List < #lib::A >, getter = 'get:values', reflectable, static, const, final
+Field 'values', type = dart:core::List < #lib::A >, getter = 'get:values', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -433,7 +433,7 @@
 }
 
 
-Field 'elem1', type = #lib::A, getter = 'get:elem1', reflectable, static, const, final
+Field 'elem1', type = #lib::A, getter = 'get:elem1', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -446,7 +446,7 @@
 }
 
 
-Field 'elem2', type = #lib::A, getter = 'get:elem2', reflectable, static, const, final
+Field 'elem2', type = #lib::A, getter = 'get:elem2', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -459,7 +459,7 @@
 }
 
 
-Field 'elem3', type = #lib::A, getter = 'get:elem3', reflectable, static, const, final
+Field 'elem3', type = #lib::A, getter = 'get:elem3', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
@@ -472,7 +472,7 @@
 }
 
 
-Field 'elem4', type = #lib::A, getter = 'get:elem4', reflectable, static, const, final
+Field 'elem4', type = #lib::A, getter = 'get:elem4', reflectable, static, const, final, has-initializer
     initializer
 Bytecode {
   Entry                0
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index a64977c..4bc3448 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -341,6 +341,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   PopLocal             r2
@@ -377,6 +378,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   PopLocal             r2
@@ -723,6 +725,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#7
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextVar       0, 0
@@ -831,6 +834,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
+  CheckFunctionTypeArgs 0, r1
   CheckStack           0
   Push                 r0
   LoadContextVar       0, 0
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index 0bdecc9..bfd3d22 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -17,7 +17,7 @@
 OPTIONS=()
 GEN_KERNEL_OPTIONS=()
 PACKAGES=
-BUILD_ELF=0
+BUILD_ASM=0
 
 ARGV=()
 for arg in "$@"; do
@@ -36,8 +36,8 @@
     -D* )
     GEN_KERNEL_OPTIONS+=("$arg")
     ;;
-    --build-elf)
-    BUILD_ELF=1
+    --build-assembly)
+    BUILD_ASM=1
     ;;
     --*)
     OPTIONS+=("$arg")
@@ -56,12 +56,12 @@
 SOURCE_FILE="${ARGV[0]}"
 SNAPSHOT_FILE="${ARGV[1]}"
 
-if [ $BUILD_ELF -eq 1 ]; then
+if [ $BUILD_ASM -eq 1 ]; then
   GEN_SNAPSHOT_OPTION="--snapshot-kind=app-aot-assembly"
   GEN_SNAPSHOT_FILENAME="--assembly=${SNAPSHOT_FILE}.S"
 else
-  GEN_SNAPSHOT_OPTION="--snapshot-kind=app-aot-blobs"
-  GEN_SNAPSHOT_FILENAME="--blobs_container_filename=${SNAPSHOT_FILE}"
+  GEN_SNAPSHOT_OPTION="--snapshot-kind=app-aot-elf"
+  GEN_SNAPSHOT_FILENAME="--elf=${SNAPSHOT_FILE}"
 fi
 
 function follow_links() {
@@ -109,6 +109,6 @@
      "$SNAPSHOT_FILE.dill"
 
 # Step 3: Assemble the assembly file into an ELF object.
-if [ $BUILD_ELF -eq 1 ]; then
+if [ $BUILD_ASM -eq 1 ]; then
     gcc -shared -o "$SNAPSHOT_FILE" "${SNAPSHOT_FILE}.S"
 fi
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 1369c7b..4933877 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -917,26 +917,6 @@
   }
 }
 
-dart_executable("dartaotruntime") {
-  extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [
-    "..:libdart_precompiled_runtime",
-    "../platform:libdart_platform_precompiled_runtime",
-  ]
-  extra_sources = [
-    "builtin.cc",
-    "gzip.cc",
-    "gzip.h",
-    "loader.cc",
-    "loader.h",
-    "main.cc",
-    "observatory_assets_empty.cc",
-    "snapshot_empty.cc",
-  ]
-
-  extra_deps += [ ":elf_loader" ]
-}
-
 executable("process_test") {
   sources = [
     "process_test.cc",
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index 245e83c..a305f65 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -560,7 +560,7 @@
       pentry->token_count += count;
     }
     ASSERT(pentry->token_count <= kTokenCount);
-    bool is_ready = pentry->token_count > 0 && pentry->IsReady();
+    bool is_ready = pentry->IsReady();
     if (!was_ready && is_ready) {
       active_readers_.Add(pentry);
     }
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 91e6cd8..958e5c3 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -236,14 +236,14 @@
                                GetHashmapHashFromFd(fd));
             di->Close();
             delete di;
-            socket->SetClosedFd();
           }
+          socket->CloseFd();
         } else {
           ASSERT(new_mask == 0);
           socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
           di->Close();
           delete di;
-          socket->SetClosedFd();
+          socket->CloseFd();
         }
 
         DartUtils::PostInt32(port, 1 << kDestroyedEvent);
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index bae6f32..8c963c4 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -447,14 +447,15 @@
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         di->Close();
         delete di;
-        socket->SetClosedFd();
+        socket->CloseFd();
       }
+      socket->SetClosedFd();
     } else {
       ASSERT(new_mask == 0);
       socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
       di->Close();
       delete di;
-      socket->SetClosedFd();
+      socket->CloseFd();
     }
     if (port != 0) {
       const bool success = DartUtils::PostInt32(port, 1 << kDestroyedEvent);
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 8ae3151..48ef4ef 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -246,14 +246,14 @@
                                GetHashmapHashFromFd(fd));
             di->Close();
             delete di;
-            socket->SetClosedFd();
           }
+          socket->CloseFd();
         } else {
           ASSERT(new_mask == 0);
           socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
           di->Close();
           delete di;
-          socket->SetClosedFd();
+          socket->CloseFd();
         }
         DartUtils::PostInt32(port, 1 << kDestroyedEvent);
       } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) {
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 1a2b20e..904ae0a 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -252,14 +252,14 @@
                                GetHashmapHashFromFd(fd));
             di->Close();
             delete di;
-            socket->SetClosedFd();
           }
+          socket->CloseFd();
         } else {
           ASSERT(new_mask == 0);
           socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
           di->Close();
           delete di;
-          socket->SetClosedFd();
+          socket->CloseFd();
         }
 
         DartUtils::PostInt32(port, 1 << kDestroyedEvent);
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 177ff33..4187405 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -1071,9 +1071,9 @@
         if (registry->CloseSafe(socket)) {
           ASSERT(listen_socket->Mask() == 0);
           listen_socket->Close();
-          socket->SetClosedFd();
+          socket->CloseFd();
         }
-
+        socket->SetClosedFd();
         DartUtils::PostInt32(msg->dart_port, 1 << kDestroyedEvent);
       } else {
         UNREACHABLE();
@@ -1151,7 +1151,7 @@
       } else if (IS_COMMAND(msg->data, kCloseCommand)) {
         handle->SetPortAndMask(msg->dart_port, 0);
         handle->Close();
-        socket->SetClosedFd();
+        socket->CloseFd();
       } else {
         UNREACHABLE();
       }
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 32c6d9c..a9a2241 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -23,7 +23,6 @@
   V(snapshot_depfile, snapshot_deps_filename)                                  \
   V(depfile, depfile)                                                          \
   V(depfile_output_filename, depfile_output_filename)                          \
-  V(shared_blobs, shared_blobs_filename)                                       \
   V(save_compilation_trace, save_compilation_trace_filename)                   \
   V(load_compilation_trace, load_compilation_trace_filename)                   \
   V(save_type_feedback, save_type_feedback_filename)                           \
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index b36364a..727b18f 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -196,10 +196,10 @@
                                process_stderr->fd(), exit_event->fd(), &result);
   // Process::Wait() closes the file handles, so blow away the fds in the
   // Sockets so that they don't get picked up by the finalizer on _NativeSocket.
-  process_stdin->SetClosedFd();
-  process_stdout->SetClosedFd();
-  process_stderr->SetClosedFd();
-  exit_event->SetClosedFd();
+  process_stdin->CloseFd();
+  process_stdout->CloseFd();
+  process_stderr->CloseFd();
+  exit_event->CloseFd();
   if (success) {
     Dart_Handle out = result.stdout_data();
     ThrowIfError(out);
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 019b33c..9db41a0 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -126,17 +126,16 @@
         }
 
         // This socket creation is the exact same as the one which originally
-        // created the socket. We therefore increment the refcount and reuse
-        // the file descriptor.
+        // created the socket. Feed same fd and store it into native field
+        // of dart socket_object. Sockets here will share same fd but contain a
+        // different port() through EventHandler_SendData.
+        Socket* socketfd = new Socket(os_socket->fd);
         os_socket->ref_count++;
-
-        // The same Socket is used by a second Dart _NativeSocket object.
-        // It Retains a reference.
-        os_socket->socketfd->Retain();
         // We set as a side-effect the file descriptor on the dart
         // socket_object.
-        Socket::ReuseSocketIdNativeField(socket_object, os_socket->socketfd,
+        Socket::ReuseSocketIdNativeField(socket_object, socketfd,
                                          Socket::kFinalizerListening);
+        InsertByFd(socketfd, os_socket);
         return Dart_True();
       }
     }
@@ -194,36 +193,33 @@
 }
 
 bool ListeningSocketRegistry::CloseOneSafe(OSSocket* os_socket,
-                                           bool update_hash_maps) {
+                                           Socket* socket) {
   ASSERT(!mutex_.TryLock());
   ASSERT(os_socket != NULL);
   ASSERT(os_socket->ref_count > 0);
   os_socket->ref_count--;
+  RemoveByFd(socket);
   if (os_socket->ref_count > 0) {
     return false;
   }
-  if (update_hash_maps) {
-    // We free the OS socket by removing it from two datastructures.
-    RemoveByFd(os_socket->socketfd);
 
-    OSSocket* prev = NULL;
-    OSSocket* current = LookupByPort(os_socket->port);
-    while (current != os_socket) {
-      ASSERT(current != NULL);
-      prev = current;
-      current = current->next;
-    }
+  OSSocket* prev = NULL;
+  OSSocket* current = LookupByPort(os_socket->port);
+  while (current != os_socket) {
+    ASSERT(current != NULL);
+    prev = current;
+    current = current->next;
+  }
 
-    if ((prev == NULL) && (current->next == NULL)) {
-      // Remove last element from the list.
-      RemoveByPort(os_socket->port);
-    } else if (prev == NULL) {
-      // Remove first element of the list.
-      InsertByPort(os_socket->port, current->next);
-    } else {
-      // Remove element from the list which is not the first one.
-      prev->next = os_socket->next;
-    }
+  if ((prev == NULL) && (current->next == NULL)) {
+    // Remove last element from the list.
+    RemoveByPort(os_socket->port);
+  } else if (prev == NULL) {
+    // Remove first element of the list.
+    InsertByPort(os_socket->port, current->next);
+  } else {
+    // Remove element from the list which is not the first one.
+    prev->next = os_socket->next;
   }
 
   ASSERT(os_socket->ref_count == 0);
@@ -233,10 +229,11 @@
 
 void ListeningSocketRegistry::CloseAllSafe() {
   MutexLocker ml(&mutex_);
-
   for (SimpleHashMap::Entry* cursor = sockets_by_fd_.Start(); cursor != NULL;
        cursor = sockets_by_fd_.Next(cursor)) {
-    CloseOneSafe(reinterpret_cast<OSSocket*>(cursor->value), false);
+    OSSocket* os_socket = reinterpret_cast<OSSocket*>(cursor->value);
+    ASSERT(os_socket != NULL);
+    delete os_socket;
   }
 }
 
@@ -244,7 +241,7 @@
   ASSERT(!mutex_.TryLock());
   OSSocket* os_socket = LookupByFd(socketfd);
   if (os_socket != NULL) {
-    return CloseOneSafe(os_socket, true);
+    return CloseOneSafe(os_socket, socketfd);
   } else {
     // A finalizer may direct the event handler to close a listening socket
     // that it has never seen before. In this case, we return true to direct
@@ -1060,7 +1057,7 @@
                                  void* data) {
   Socket* socket = reinterpret_cast<Socket*>(data);
   if (socket->fd() >= 0) {
-    socket->SetClosedFd();
+    socket->CloseFd();
   }
   socket->Release();
 }
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index a23ff65..c3ea9fe 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -49,6 +49,12 @@
   explicit Socket(intptr_t fd);
 
   intptr_t fd() const { return fd_; }
+
+  // Close fd and may need to decrement the count of handle by calling
+  // release().
+  void CloseFd();
+  // Set fd_ to closed. On fuchsia and win, shared socket should not
+  // release handle but only SetClosedFd().
   void SetClosedFd();
 
   Dart_Port isolate_port() const { return isolate_port_; }
@@ -194,7 +200,7 @@
     bool v6_only;
     bool shared;
     int ref_count;
-    Socket* socketfd;
+    intptr_t fd;
 
     // Singly linked lists of OSSocket instances which listen on the same port
     // but on different addresses.
@@ -210,8 +216,9 @@
           v6_only(v6_only),
           shared(shared),
           ref_count(0),
-          socketfd(socketfd),
-          next(NULL) {}
+          next(NULL) {
+      fd = socketfd->fd();
+    }
   };
 
   static const intptr_t kInitialSocketsCount = 8;
@@ -246,7 +253,7 @@
   void InsertByFd(Socket* fd, OSSocket* socket);
   void RemoveByFd(Socket* fd);
 
-  bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps);
+  bool CloseOneSafe(OSSocket* os_socket, Socket* socket);
   void CloseAllSafe();
 
   SimpleHashMap sockets_by_port_;
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 5547672..78e1f8e 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -23,6 +23,10 @@
       port_(ILLEGAL_PORT),
       udp_receive_buffer_(NULL) {}
 
+void Socket::CloseFd() {
+  SetClosedFd();
+}
+
 void Socket::SetClosedFd() {
   fd_ = kClosedFd;
 }
diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc
index 5454c7e..b4c0b10 100644
--- a/runtime/bin/socket_fuchsia.cc
+++ b/runtime/bin/socket_fuchsia.cc
@@ -51,11 +51,15 @@
       udp_receive_buffer_(NULL) {}
 
 void Socket::SetClosedFd() {
+  fd_ = kClosedFd;
+}
+
+void Socket::CloseFd() {
   ASSERT(fd_ != kClosedFd);
   IOHandle* handle = reinterpret_cast<IOHandle*>(fd_);
   ASSERT(handle != NULL);
   handle->Release();
-  fd_ = kClosedFd;
+  SetClosedFd();
 }
 
 static intptr_t Create(const RawAddr& addr) {
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index f2bb4aa..c993fcb 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -24,6 +24,10 @@
       port_(ILLEGAL_PORT),
       udp_receive_buffer_(NULL) {}
 
+void Socket::CloseFd() {
+  SetClosedFd();
+}
+
 void Socket::SetClosedFd() {
   fd_ = kClosedFd;
 }
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index fc81838..f87482e 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -22,6 +22,10 @@
       port_(ILLEGAL_PORT),
       udp_receive_buffer_(NULL) {}
 
+void Socket::CloseFd() {
+  SetClosedFd();
+}
+
 void Socket::SetClosedFd() {
   fd_ = kClosedFd;
 }
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 79820da..5d476e9 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -30,11 +30,15 @@
   ASSERT(handle != NULL);
 }
 
-void Socket::SetClosedFd() {
+void Socket::CloseFd() {
   ASSERT(fd_ != kClosedFd);
   Handle* handle = reinterpret_cast<Handle*>(fd_);
   ASSERT(handle != NULL);
   handle->Release();
+  SetClosedFd();
+}
+
+void Socket::SetClosedFd() {
   fd_ = kClosedFd;
 }
 
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 10ae2e3..41044e9 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -238,7 +238,8 @@
           .listen((line) {
         print('>testee>err> $line');
       });
-      process.exitCode.then((exitCode) {
+      process.exitCode.then((exitCode) async {
+        await serviceInfoDir.delete(recursive: true);
         if ((exitCode != 0) && !killedByTester) {
           throw "Testee exited with $exitCode";
         }
@@ -255,7 +256,6 @@
       uri = Uri.parse(infoJson['uri']);
       completer.complete(uri);
       print('** Signaled to run test queries on $uri');
-      await serviceInfoDir.delete(recursive: true);
     });
     return completer.future;
   }
diff --git a/runtime/tests/vm/dart/regress_38743_test.dart b/runtime/tests/vm/dart/regress_38743_test.dart
new file mode 100644
index 0000000..f10dd93
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_38743_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--stacktrace_every=1 --deterministic --optimization-counter-threshold=6 --optimization-filter=baz
+
+// Regression test for https://github.com/dart-lang/sdk/issues/38743.
+// Verifies that VM doesn't crash when collecting debugger stack traces in
+// closures inside instance methods.
+
+class A {
+  foo(unusedArg0) {
+    baz() {
+      for (int i = 0; i < 3; ++i) {
+        print('[$i] $unusedArg0');
+      }
+    }
+
+    baz();
+  }
+}
+
+main() {
+  A().foo(null);
+}
diff --git a/runtime/tests/vm/dart/use_bare_instructions_flag_test.dart b/runtime/tests/vm/dart/use_bare_instructions_flag_test.dart
index bb8cc83..aaf6db8 100644
--- a/runtime/tests/vm/dart/use_bare_instructions_flag_test.dart
+++ b/runtime/tests/vm/dart/use_bare_instructions_flag_test.dart
@@ -46,14 +46,14 @@
     await Future.wait(<Future>[
       run(genSnapshot, <String>[
         '--use-bare-instructions',
-        '--snapshot-kind=app-aot-blobs',
-        '--blobs_container_filename=$scriptBareSnapshot',
+        '--snapshot-kind=app-aot-elf',
+        '--elf=$scriptBareSnapshot',
         scriptDill,
       ]),
       run(genSnapshot, <String>[
         '--no-use-bare-instructions',
-        '--snapshot-kind=app-aot-blobs',
-        '--blobs_container_filename=$scriptNonBareSnapshot',
+        '--snapshot-kind=app-aot-elf',
+        '--elf=$scriptNonBareSnapshot',
         scriptDill,
       ]),
     ]);
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index dc259ce..2c6b877 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -12,8 +12,11 @@
   return "/" + segments.join("/");
 }
 
-test(String sdkRoot, {bool useElf: false}) async {
-  if (Platform.isMacOS && useElf) return;
+test(String sdkRoot, {bool useAsm: false}) async {
+  if (Platform.isMacOS || Platform.isWindows) {
+    // Missing necessary utilities.
+    return;
+  }
 
   // Generate the snapshot profile.
   final String thisTestPath =
@@ -28,11 +31,11 @@
     snapshotPath,
   ];
 
-  if (useElf) {
-    precompiler2Args.insert(0, "--build-elf");
+  if (useAsm) {
+    precompiler2Args.insert(0, "--build-assembly");
   }
 
-  final ProcessResult result = await Process.run(
+  ProcessResult result = await Process.run(
     "pkg/vm/tool/precompiler2",
     precompiler2Args,
     workingDirectory: sdkRoot,
@@ -41,9 +44,7 @@
 
   // The precompiler2 script tried using GCC for the wrong architecture. We
   // don't have a workaround for this now.
-  if (useElf &&
-      result.exitCode != 0 &&
-      result.stderr.contains("Assembler messages")) {
+  if (result.exitCode != 0 && result.stderr.contains("Assembler messages")) {
     return;
   }
 
@@ -52,19 +53,18 @@
   print(result.stdout);
 
   Expect.equals(result.exitCode, 0);
-  if (!useElf) {
-    Expect.equals(
-        "WARNING: app-aot-blobs snapshots have been deprecated and support for "
-        "generating them will be removed soon. Please use the app-aot-elf or "
-        "app-aot-assembly snapshot kinds in conjunction with the portable ELF "
-        "loader from //runtime/bin:elf_loader if necessary. See "
-        "http://dartbug.com/38764 for more details.\x0A",
-        result.stderr);
-  } else {
-    Expect.equals("", result.stderr);
-  }
+  Expect.equals("", result.stderr);
   Expect.equals("", result.stdout);
 
+  result = await Process.run("strip", [snapshotPath]);
+
+  // Same issue: strip can't process a cross-compiled ELF.
+  if (result.exitCode != 0 &&
+      (result.stderr.contains("Unable to recognise") ||
+          result.stderr.contains("non-object and non-archive"))) {
+    return;
+  }
+
   final V8SnapshotProfile profile = V8SnapshotProfile.fromJson(JsonDecoder()
       .convert(File("${temp.path}/profile.heapsnapshot").readAsStringSync()));
 
@@ -93,12 +93,17 @@
   // Verify that the actual size of the snapshot is close to the sum of the
   // shallow sizes of all objects in the profile. They will not be exactly equal
   // because of global headers and padding.
-  if (useElf) {
-    await Process.run("strip", [snapshotPath]);
-  }
   final int actual = await File(snapshotPath).length();
   final int expected = profile.accountedBytes;
-  Expect.isTrue((actual - expected).abs() / actual < 0.02);
+  print("Expected size: $expected, actual size: $actual.");
+  if ((actual - expected).abs() / actual > 0.03) {
+    if (useAsm) {
+      print("Failure on Assembly snapshot type.");
+    } else {
+      print("Failure on ELF snapshot type.");
+    }
+    Expect.fail("Difference cannot be greater than 3% of actual.");
+  }
 }
 
 Match matchComplete(RegExp regexp, String line) {
@@ -188,7 +193,7 @@
       .replaceRange(sdkBaseSegments.length - 3, sdkBaseSegments.length, []);
   String sdkRoot = path(sdkBaseSegments);
 
-  test(sdkRoot, useElf: false);
-  test(sdkRoot, useElf: true);
+  await test(sdkRoot, useAsm: true);
+  await test(sdkRoot, useAsm: false);
   testMacros(sdkRoot);
 }
diff --git a/runtime/tools/bin_to_assembly.py b/runtime/tools/bin_to_assembly.py
index fc539e3..9ec13e7 100755
--- a/runtime/tools/bin_to_assembly.py
+++ b/runtime/tools/bin_to_assembly.py
@@ -83,11 +83,11 @@
         with open(options.input, "rb") as input_file:
             if options.target_os in ["win"]:
                 for byte in input_file.read():
-                    output_file.write("byte %d\n" % ord(byte))
+                    output_file.write("byte %d\n" % (byte if isinstance(byte, int) else ord(byte)))
                     size += 1
             else:
                 for byte in input_file.read():
-                    output_file.write(".byte %d\n" % ord(byte))
+                    output_file.write(".byte %d\n" % (byte if isinstance(byte, int) else ord(byte)))
                     size += 1
 
         if options.target_os not in ["mac", "ios", "win"]:
diff --git a/runtime/tools/create_archive.py b/runtime/tools/create_archive.py
index c0b7c89..7bc93d5 100755
--- a/runtime/tools/create_archive.py
+++ b/runtime/tools/create_archive.py
@@ -98,7 +98,7 @@
         line = '   '
         lineCounter = 0
         for byte in tar_archive:
-            line += r" %d," % ord(byte)
+            line += r" %d," % (byte if isinstance(byte, int) else ord(byte))
             lineCounter += 1
             if lineCounter == 10:
                 out.write(line + '\n')
@@ -180,7 +180,7 @@
         else:
             return MakeCCFile(options)
 
-    except Exception, inst:
+    except Exception as inst:
         sys.stderr.write('create_archive.py exception\n')
         sys.stderr.write(str(inst))
         sys.stderr.write('\n')
diff --git a/runtime/tools/create_string_literal.py b/runtime/tools/create_string_literal.py
index b7db388..68a969b 100755
--- a/runtime/tools/create_string_literal.py
+++ b/runtime/tools/create_string_literal.py
@@ -85,7 +85,7 @@
             return -1
 
         return 0
-    except Exception, inst:
+    except Exception as inst:
         sys.stderr.write('create_string_literal.py exception\n')
         sys.stderr.write(str(inst))
         sys.stderr.write('\n')
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index e351fe2..d47151e 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,7 +14,7 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.64';
+const String version = '1.65';
 
 // Restriction on statements and expressions.
 const int stmtDepth = 1;
@@ -26,6 +26,7 @@
 const int numGlobalMethods = 4;
 const int numMethodParams = 4;
 const int numClasses = 4;
+const int numExtensionMethodsPerClass = 3;
 
 // Naming conventions.
 const varName = 'var';
@@ -34,6 +35,158 @@
 const fieldName = 'fld';
 const methodName = 'foo';
 
+/// Enum for the different types of methods generated by the fuzzer.
+enum MethodType { globalMethod, ffiMethod, instanceMethod, extensionMethod }
+
+/// Base class for all methods in the program generated by DartFuzz.
+abstract class Method {
+  Method(this.name, this.parameters, this.fuzzer);
+
+  DartType get returnType => parameters[0];
+
+  void emitFunctionBody() {
+    if (fuzzer.rollDice(10)) {
+      // Emit a method using "=>" syntax.
+      fuzzer.emit(' => ');
+      fuzzer.emitExpr(0, returnType, includeSemicolon: true);
+    } else {
+      fuzzer.emitBraceWrapped(() {
+        assert(fuzzer.localVars.isEmpty);
+        if (fuzzer.emitStatements(0)) {
+          fuzzer.emitReturn();
+        }
+        assert(fuzzer.localVars.isEmpty);
+      });
+    }
+  }
+
+  void emitFunctionDefinition() {
+    final type = returnType.name;
+    fuzzer.emitLn('$type ${name}', newline: false);
+    fuzzer.emitParenWrapped(() => fuzzer.emitParDecls(parameters));
+    emitFunctionBody();
+    fuzzer.emitNewline();
+    fuzzer.emitNewline();
+  }
+
+  void emitCall(int depth,
+      {RhsFilter rhsFilter,
+      bool includeSemicolon = false,
+      bool extensionApplication = false}) {
+    String outputName = name;
+    fuzzer.emitLn(outputName, newline: false);
+    fuzzer.emitExprList(depth + 1, parameters, rhsFilter: rhsFilter);
+    if (includeSemicolon) {
+      fuzzer.emit(';');
+    }
+  }
+
+  // Main emitter for a method.
+  void emit() {
+    emitFunctionDefinition();
+  }
+
+  final String name;
+  final List<DartType> parameters;
+  final DartFuzz fuzzer;
+}
+
+/// Class for global methods generated by DartFuzz.
+class GlobalMethod extends Method {
+  GlobalMethod(String name, List<DartType> parameters, DartFuzz fuzzer)
+      : super(name, parameters, fuzzer);
+}
+
+/// Class for ffi methods generated by DartFuzz.
+class FfiMethod extends Method {
+  FfiMethod(
+      String namePrefix, int index, List<DartType> parameters, DartFuzz fuzzer)
+      : ffiCastName = "${namePrefix}FfiCast${index}",
+        super("${namePrefix}Ffi${index}", parameters, fuzzer) {}
+
+  @override
+  void emitFunctionBody() {
+    fuzzer.emitBraceWrapped(() {
+      assert(fuzzer.localVars.isEmpty);
+      if (fuzzer.emitStatements(0)) {
+        fuzzer.emitReturn();
+      }
+      assert(fuzzer.localVars.isEmpty);
+    });
+  }
+
+  @override
+  void emit() {
+    fuzzer.emitFfiTypedef(this);
+    emitFunctionDefinition();
+    fuzzer.emitFfiCast("${ffiCastName}", "${name}", "${name}Type", parameters);
+    fuzzer.emitNewline();
+    fuzzer.emitNewline();
+  }
+
+  final String ffiCastName;
+}
+
+/// Class for instance methods generated by DartFuzz.
+class InstanceMethod extends Method {
+  InstanceMethod(
+      String name, List<DartType> parameters, DartFuzz fuzzer, this.className)
+      : super(name, parameters, fuzzer) {}
+
+  @override
+  void emitCall(int depth,
+      {RhsFilter rhsFilter,
+      bool includeSemicolon = false,
+      bool extensionApplication = false}) {
+    String outputName = name;
+    if (fuzzer.currentClass == null) {
+      // If we're calling an instance method from outside the class, then we
+      // should construct an object of that class first.
+      outputName = "${className}().${name}";
+    }
+    fuzzer.emitLn(outputName, newline: false);
+    fuzzer.emitExprList(depth + 1, parameters, rhsFilter: rhsFilter);
+    if (includeSemicolon) {
+      fuzzer.emit(';');
+    }
+  }
+
+  final String className;
+}
+
+// Class for extension methods generated by DartFuzz.
+class ExtensionMethod extends Method {
+  ExtensionMethod(String name, List<DartType> parameters, DartFuzz fuzzer,
+      this.className, this.extensionName)
+      : super(name, parameters, fuzzer) {}
+
+  @override
+  void emitCall(int depth,
+      {RhsFilter rhsFilter,
+      bool includeSemicolon = false,
+      bool extensionApplication = false}) {
+    String outputName = name;
+    if (fuzzer.currentClass == null) {
+      // If we're calling an extension method from outside the class, we can
+      // call it using an object of the class or using explicit extension
+      // application.
+      if (extensionApplication) {
+        outputName = "${extensionName}(${className}()).${name}";
+      } else {
+        outputName = "${className}().${name}";
+      }
+    }
+    fuzzer.emitLn(outputName, newline: false);
+    fuzzer.emitExprList(depth + 1, parameters, rhsFilter: rhsFilter);
+    if (includeSemicolon) {
+      fuzzer.emit(';');
+    }
+  }
+
+  final String className;
+  final String extensionName;
+}
+
 // Class that tracks the state of the filter applied to the
 // right-hand-side of an assignment in order to avoid generating
 // left-hand-side variables.
@@ -133,28 +286,25 @@
     iterVars = <String>[];
     globalVars = fillTypes1(limit: numGlobalVars);
     globalVars.addAll(dartType.allTypes);
-    globalMethods =
-        fillTypes2(limit2: numGlobalMethods, limit1: numMethodParams);
+    globalMethods = getMethods(
+        numGlobalMethods, numMethodParams, MethodType.globalMethod,
+        namePrefix: methodName);
     classFields = fillTypes2(limit2: numClasses, limit1: numLocalVars);
     final int numClassMethods = 1 + numClasses - classFields.length;
-    classMethods = fillTypes3(classFields.length,
-        limit2: numClassMethods, limit1: numMethodParams);
+    classMethods =
+        getClassMethods(classFields.length, numClassMethods, numMethodParams);
     virtualClassMethods = <Map<int, List<int>>>[];
     classParents = <int>[];
     // Setup optional ffi methods and types.
-    final ffiStatus = <bool>[for (final _ in globalMethods) false];
     if (ffi) {
-      List<List<DartType>> globalMethodsFfi = fillTypes2(
-          limit2: numGlobalMethods, limit1: numMethodParams, isFfi: true);
-      for (var m in globalMethodsFfi) {
-        globalMethods.add(m);
-        ffiStatus.add(true);
-      }
+      globalMethods.addAll(getMethods(
+          numGlobalMethods, numMethodParams, MethodType.ffiMethod,
+          namePrefix: methodName));
     }
     // Generate.
     emitHeader();
     emitVariableDeclarations(varName, globalVars);
-    emitMethods(methodName, globalMethods, ffiStatus);
+    emitMethods(globalMethods);
     emitClasses();
     emitMain();
     // Sanity.
@@ -165,6 +315,40 @@
     assert(localVars.isEmpty);
   }
 
+  List<Method> getMethods(int maxMethods, int maxParams, MethodType type,
+      {String className = "", String extensionName = "", String namePrefix}) {
+    final List<Method> list = <Method>[];
+    for (int i = 0, n = chooseOneUpTo(maxMethods); i < n; i++) {
+      final List<DartType> params =
+          fillTypes1(limit: maxParams, isFfi: type == MethodType.ffiMethod);
+      switch (type) {
+        case MethodType.globalMethod:
+          list.add(GlobalMethod("${namePrefix}${i}", params, this));
+          break;
+        case MethodType.ffiMethod:
+          list.add(FfiMethod(namePrefix, i, params, this));
+          break;
+        case MethodType.instanceMethod:
+          list.add(
+              InstanceMethod("${namePrefix}${i}", params, this, className));
+          break;
+        case MethodType.extensionMethod:
+          list.add(ExtensionMethod(
+              "${namePrefix}${i}", params, this, className, extensionName));
+          break;
+      }
+    }
+    return list;
+  }
+
+  List<List<Method>> getClassMethods(
+          int numClasses, int maxMethods, int maxParams) =>
+      [
+        for (int i = 0; i < numClasses; i++)
+          getMethods(maxMethods, maxParams, MethodType.instanceMethod,
+              className: "X${i}", namePrefix: "${methodName}${i}_")
+      ];
+
   //
   // General Helpers.
   //
@@ -466,43 +650,11 @@
     emitNewline();
   }
 
-  void emitMethod(
-      String name, int index, List<DartType> method, bool isFfiMethod) {
-    final type = method[0].name;
-    final methodName = '$name${isFfiMethod ? "Ffi" : ''}$index';
-    if (isFfiMethod) {
-      emitFfiTypedef("${name}Ffi${index}Type", method);
-    }
-    emitLn('$type $methodName', newline: false);
-    emitParenWrapped(() => emitParDecls(method));
-    if (!isFfiMethod && rollDice(10)) {
-      // Emit a method using "=>" syntax.
-      emit(' => ');
-      emitExpr(0, method[0], includeSemicolon: true);
-    } else {
-      emitBraceWrapped(() {
-        assert(localVars.isEmpty);
-        if (emitStatements(0)) {
-          emitReturn();
-        }
-        assert(localVars.isEmpty);
-      });
-    }
-    if (isFfiMethod) {
-      emitFfiCast("${name}${index}", "${name}Ffi${index}",
-          "${name}Ffi${index}Type", method);
-    }
-    emitNewline();
-    emitNewline();
-  }
-
-  void emitMethods(String name, List<List<DartType>> methods,
-      [List<bool> ffiStatus]) {
+  void emitMethods(List<Method> methods) {
     for (int i = 0; i < methods.length; i++) {
-      List<DartType> method = methods[i];
+      Method method = methods[i];
       currentMethod = i;
-      final bool isFfiMethod = ffiStatus != null && ffiStatus[i];
-      emitMethod(name, i, method, isFfiMethod);
+      methods[i].emit();
       currentMethod = null;
     }
   }
@@ -519,8 +671,7 @@
         if (rollDice(8)) {
           currentClass = parentClass;
           currentMethod = j;
-          emitMethod('$methodName${parentClass}_', j,
-              classMethods[parentClass][j], false);
+          classMethods[parentClass][j].emit();
           vcm[parentClass].add(currentMethod);
           currentMethod = null;
           currentClass = null;
@@ -562,7 +713,7 @@
         emitVariableDeclarations('$fieldName${i}_', classFields[i]);
         currentClass = i;
         emitVirtualMethods();
-        emitMethods('$methodName${i}_', classMethods[i]);
+        emitMethods(classMethods[currentClass]);
         emitFunctionDefinition('run', () {
           if (i > 0) {
             // FIXME(bkonyi): fix potential issue where we try to apply a class
@@ -574,12 +725,32 @@
           assert(localVars.isEmpty);
         }, retType: 'void');
       });
+      emitNewline();
+      emitNewline();
+      emitExtensionMethods();
       currentClass = null;
-      emitNewline();
-      emitNewline();
     }
   }
 
+  void emitExtensionMethods() {
+    classMethods[currentClass].addAll(getMethods(numExtensionMethodsPerClass,
+        numMethodParams, MethodType.extensionMethod,
+        className: "X${currentClass}",
+        extensionName: "XE${currentClass}",
+        namePrefix: "${methodName}${currentClass}_Extension"));
+    emit("extension XE$currentClass on X$currentClass ");
+    emitBraceWrapped(() {
+      for (int i = 0; i < classMethods[currentClass].length; i++) {
+        currentMethod = i;
+        if (classMethods[currentClass][i] is ExtensionMethod)
+          classMethods[currentClass][i].emit();
+        currentMethod = null;
+      }
+    });
+    emitNewline();
+    emitNewline();
+  }
+
   void emitLoadFfiLib() {
     if (ffi) {
       emitLn(
@@ -602,7 +773,7 @@
         for (int i = 0; i < globalMethods.length; i++) {
           final outputName = '$methodName$i';
           emitTryCatchFinally(() {
-            emitCall(1, outputName, globalMethods[i], includeSemicolon: true);
+            globalMethods[i].emitCall(1, includeSemicolon: true);
           }, () {
             emitPrint('$outputName() throws');
           });
@@ -612,13 +783,11 @@
         // Call each class method once.
         for (int i = 0; i < classMethods.length; i++) {
           for (int j = 0; j < classMethods[i].length; j++) {
-            final outputName = 'X${i}().$methodName${i}_${j}';
             emitNewline();
             emitTryCatchFinally(() {
-              emitCall(1, outputName, classMethods[i][j],
-                  includeSemicolon: true);
+              classMethods[i][j].emitCall(1, includeSemicolon: true);
             }, () {
-              emitPrint('$outputName() throws');
+              emitPrint('X$i().${classMethods[i][j].name}() throws');
             });
           }
           // Call each virtual class method once.
@@ -631,8 +800,8 @@
                 final outputName = 'X${i}().$methodName${parentClass}_${j}';
                 emitNewline();
                 emitTryCatchFinally(
-                    () => emitCall(1, outputName, classMethods[parentClass][j],
-                        includeSemicolon: true),
+                    () => classMethods[parentClass][j]
+                        .emitCall(1, includeSemicolon: true),
                     () => emitPrint('$outputName() throws'));
               }
             }
@@ -1628,23 +1797,14 @@
     });
   }
 
-  // Emit call to a specific method.
-  void emitCall(int depth, String name, List<DartType> proto,
-      {RhsFilter rhsFilter, bool includeSemicolon = false}) {
-    emitLn(name, newline: false);
-    emitExprList(depth + 1, proto, rhsFilter: rhsFilter);
-    if (includeSemicolon) {
-      emit(';');
-    }
-  }
-
   // Helper for a method call.
-  bool pickedCall(
-      int depth, DartType tp, String name, List<List<DartType>> protos, int m,
+  bool pickedCall(int depth, DartType tp, List<Method> methods, int m,
       {RhsFilter rhsFilter}) {
     for (int i = m - 1; i >= 0; i--) {
-      if (tp == protos[i][0]) {
-        emitCall(depth + 1, "$name$i", protos[i], rhsFilter: rhsFilter);
+      if (tp == methods[i].returnType) {
+        bool extensionApplication = methods[i] is ExtensionMethod && coinFlip();
+        methods[i].emitCall(depth + 1,
+            rhsFilter: rhsFilter, extensionApplication: extensionApplication);
         return true;
       }
     }
@@ -1657,7 +1817,7 @@
     if (currentClass == null) {
       // Outside a class but inside a method: call backward in global methods.
       if (currentMethod != null &&
-          pickedCall(depth, tp, methodName, globalMethods, currentMethod,
+          pickedCall(depth, tp, globalMethods, currentMethod,
               rhsFilter: rhsFilter)) {
         return;
       }
@@ -1684,10 +1844,9 @@
         m1 = currentMethod;
       }
       final int m2 = globalMethods.length;
-      if (pickedCall(depth, tp, '$methodName${classIndex}_',
-              classMethods[classIndex], m1, rhsFilter: rhsFilter) ||
-          pickedCall(depth, tp, methodName, globalMethods, m2,
-              rhsFilter: rhsFilter)) {
+      if (pickedCall(depth, tp, classMethods[classIndex], m1,
+              rhsFilter: rhsFilter) ||
+          pickedCall(depth, tp, globalMethods, m2, rhsFilter: rhsFilter)) {
         return;
       }
     }
@@ -1838,22 +1997,13 @@
     return list;
   }
 
-  List<List<List<DartType>>> fillTypes3(int n,
-      {int limit2 = 4, int limit1 = 4}) {
-    final list = <List<List<DartType>>>[];
-    for (int i = 0; i < n; i++) {
-      list.add(fillTypes2(limit2: limit2, limit1: limit1));
-    }
-    return list;
-  }
-
   List<DartType> getCurrentProto() {
     if (currentClass != null) {
       if (currentMethod != null) {
-        return classMethods[currentClass][currentMethod];
+        return classMethods[currentClass][currentMethod].parameters;
       }
     } else if (currentMethod != null) {
-      return globalMethods[currentMethod];
+      return globalMethods[currentMethod].parameters;
     }
     return null;
   }
@@ -1876,8 +2026,9 @@
     }
   }
 
-  void emitFfiTypedef(String typeName, List<DartType> pars) {
-    emit("typedef ${typeName} = ");
+  void emitFfiTypedef(Method method) {
+    List<DartType> pars = method.parameters;
+    emit("typedef ${method.name}Type = ");
     emitFfiType(pars[0]);
     emit(' Function');
     emitParenWrapped(
@@ -1957,14 +2108,14 @@
   // which can lead to infinite loops.
   List<String> iterVars;
 
-  // Prototypes of all global methods (first element is return type).
-  List<List<DartType>> globalMethods;
+  // List of all global methods.
+  List<Method> globalMethods;
 
   // Types of fields over all classes.
   List<List<DartType>> classFields;
 
-  // Prototypes of all methods over all classes (first element is return type).
-  List<List<List<DartType>>> classMethods;
+  // List of methods over all classes.
+  List<List<Method>> classMethods;
 
   // List of virtual functions per class. Map is from parent class index to List
   // of overloaded functions from that parent.
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 39593aa..f8f2ba1 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -121,7 +121,7 @@
         constructor.isFactory &&
         constructor.name.isNotEmpty) {
       addToTable(
-          typeString(classElement.type),
+          typeString(classElement.thisType),
           '${classElement.name}.${constructor.name}',
           protoString(null, constructor.parameters));
     }
@@ -135,7 +135,7 @@
             protoString(null, method.parameters));
       } else {
         addToTable(typeString(method.returnType), method.name,
-            protoString(classElement.type, method.parameters));
+            protoString(classElement.thisType, method.parameters));
       }
     }
   }
@@ -147,7 +147,7 @@
             '${classElement.name}.${variable.name}', 'Vv');
       } else {
         addToTable(typeString(variable.type), variable.name,
-            '${typeString(classElement.type)}v');
+            '${typeString(classElement.thisType)}v');
       }
     }
   }
diff --git a/runtime/tools/dartfuzz/gen_type_table.dart b/runtime/tools/dartfuzz/gen_type_table.dart
index d6cbd3d..f2a08eb 100644
--- a/runtime/tools/dartfuzz/gen_type_table.dart
+++ b/runtime/tools/dartfuzz/gen_type_table.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 
 import 'gen_util.dart';
 
@@ -1123,7 +1124,10 @@
       } else {
         return true;
       }
-      ParameterizedType ptx = pType.instantiate([iType]);
+      ParameterizedType ptx = pType.element.instantiate(
+        typeArguments: [iType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
       newITypes.add(ptx);
       if (iType.typeArguments.length >= 1) {
         complexTypes.add(getConstName(ptx.displayName));
@@ -1141,7 +1145,10 @@
         } else {
           return true;
         }
-        ParameterizedType ptx = pType.instantiate([iType1, iType2]);
+        ParameterizedType ptx = pType.element.instantiate(
+          typeArguments: [iType1, iType2],
+          nullabilitySuffix: NullabilitySuffix.star,
+        );
         newITypes.add(ptx);
         if (iType1.typeArguments.length >= 1 ||
             iType2.typeArguments.length >= 1) {
@@ -1262,7 +1269,7 @@
       // Compute heuristic to decide whether to include the type.
       int no = countOperators(classElement);
       if (no > operatorCountThreshold) {
-        allTypes.add(classElement.type);
+        allTypes.add(classElement.thisType);
       }
     }
   }
diff --git a/runtime/tools/gen_library_src_paths.py b/runtime/tools/gen_library_src_paths.py
index 56d770a..97f4ae1 100755
--- a/runtime/tools/gen_library_src_paths.py
+++ b/runtime/tools/gen_library_src_paths.py
@@ -126,7 +126,7 @@
             return -1
 
         return 0
-    except Exception, inst:
+    except Exception as inst:
         sys.stderr.write('gen_library_src_paths.py exception\n')
         sys.stderr.write(str(inst))
         sys.stderr.write('\n')
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 2c75b06..6796fb5 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2924,8 +2924,11 @@
       AutoTraceObject(type);
       WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
-      s->Write<int8_t>(type->ptr()->type_state_);
-      s->Write<int8_t>(type->ptr()->nullability_);
+      const uint8_t combined =
+          (type->ptr()->type_state_ << 4) | type->ptr()->nullability_;
+      ASSERT(type->ptr()->type_state_ == (combined >> 4));
+      ASSERT(type->ptr()->nullability_ == (combined & 0xf));
+      s->Write<uint8_t>(combined);
     }
     count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
@@ -2933,8 +2936,11 @@
       AutoTraceObject(type);
       WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
-      s->Write<int8_t>(type->ptr()->type_state_);
-      s->Write<int8_t>(type->ptr()->nullability_);
+      const uint8_t combined =
+          (type->ptr()->type_state_ << 4) | type->ptr()->nullability_;
+      ASSERT(type->ptr()->type_state_ == (combined >> 4));
+      ASSERT(type->ptr()->nullability_ == (combined & 0xf));
+      s->Write<uint8_t>(combined);
     }
   }
 
@@ -2975,8 +2981,9 @@
                                      is_canonical);
       ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
-      type->ptr()->type_state_ = d->Read<int8_t>();
-      type->ptr()->nullability_ = d->Read<int8_t>();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->type_state_ = combined >> 4;
+      type->ptr()->nullability_ = combined & 0xf;
     }
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -2986,8 +2993,9 @@
                                      is_canonical);
       ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
-      type->ptr()->type_state_ = d->Read<int8_t>();
-      type->ptr()->nullability_ = d->Read<int8_t>();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->type_state_ = combined >> 4;
+      type->ptr()->nullability_ = combined & 0xf;
     }
   }
 
@@ -3141,8 +3149,11 @@
       s->Write<int32_t>(type->ptr()->parameterized_class_id_);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int16_t>(type->ptr()->index_);
-      s->Write<uint8_t>(type->ptr()->flags_);
-      s->Write<int8_t>(type->ptr()->nullability_);
+      const uint8_t combined =
+          (type->ptr()->flags_ << 4) | type->ptr()->nullability_;
+      ASSERT(type->ptr()->flags_ == (combined >> 4));
+      ASSERT(type->ptr()->nullability_ == (combined & 0xf));
+      s->Write<uint8_t>(combined);
     }
   }
 
@@ -3176,8 +3187,9 @@
       type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->index_ = d->Read<int16_t>();
-      type->ptr()->flags_ = d->Read<uint8_t>();
-      type->ptr()->nullability_ = d->Read<int8_t>();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->flags_ = combined >> 4;
+      type->ptr()->nullability_ = combined & 0xf;
     }
   }
 
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index c04569b..8a61638 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -336,7 +336,7 @@
   }
 
   if (!field_.IsNull() && field_.is_static() && !field_.is_const() &&
-      field_.has_initializer()) {
+      field_.has_nontrivial_initializer()) {
     processed = true;
     function_ = field_.EnsureInitializerFunction();
     error_ = CompileFunction(function_);
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 09bb182..ef81ad9f 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -919,7 +919,7 @@
       AddConstObject(Instance::Cast(value));
     }
 
-    if (field.has_initializer()) {
+    if (field.has_nontrivial_initializer()) {
       // Should not be in the middle of initialization while precompiling.
       ASSERT(value.raw() != Object::transition_sentinel().raw());
 
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 69e2ec7..2f0d0d0 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -245,6 +245,8 @@
 
     case KernelBytecode::kPushConstant:
     case KernelBytecode::kPushConstant_Wide:
+    case KernelBytecode::kInitLateField:
+    case KernelBytecode::kInitLateField_Wide:
     case KernelBytecode::kStoreStaticTOS:
     case KernelBytecode::kStoreStaticTOS_Wide:
     case KernelBytecode::kLoadStatic:
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 60a737d..e1bce80 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1209,6 +1209,7 @@
         // Only intrinsify getter if the field cannot contain a mutable double.
         // Reading from a mutable double box requires allocating a fresh double.
         if (field.is_instance() && !field.needs_load_guard() &&
+            !field.is_late() &&
             (FLAG_precompiled_mode || !IsPotentialUnboxedField(field))) {
           SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
           GenerateGetterIntrinsic(compiler::target::Field::OffsetOf(field));
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2f00b22..35c221b 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1091,10 +1091,11 @@
   // Check that all non-Smi objects are heap allocated and in old space.
   ASSERT(value.IsSmi() || value.IsOld());
 #if defined(DEBUG)
-  // Generally, instances in the flow graph should be canonical. Smis and
-  // null values are canonical by construction and so we skip them here.
+  // Generally, instances in the flow graph should be canonical. Smis, null
+  // values, and sentinel values are canonical by construction and so we skip
+  // them here.
   if (!value.IsNull() && !value.IsSmi() && value.IsInstance() &&
-      !value.IsCanonical()) {
+      !value.IsCanonical() && (value.raw() != Object::sentinel().raw())) {
     // The only allowed type for which IsCanonical() never answers true is
     // TypeParameter. (They are treated as canonical due to how they are
     // created, but there is no way to canonicalize a new TypeParameter
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 7188785..3324814 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -107,8 +107,8 @@
   "frontend/bytecode_reader.h",
   "frontend/bytecode_scope_builder.cc",
   "frontend/bytecode_scope_builder.h",
-  "frontend/constant_evaluator.cc",
-  "frontend/constant_evaluator.h",
+  "frontend/constant_reader.cc",
+  "frontend/constant_reader.h",
   "frontend/flow_graph_builder.cc",
   "frontend/flow_graph_builder.h",
   "frontend/kernel_binary_flowgraph.cc",
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index dd1ae70..2e8c237 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -696,7 +696,6 @@
 
   const intptr_t expected_num_type_args = DecodeOperandA().value();
   LocalVariable* type_args_var = LocalVariableAt(DecodeOperandE().value());
-  ASSERT(function().IsGeneric());
 
   if (throw_no_such_method_ == nullptr) {
     throw_no_such_method_ = B->BuildThrowNoSuchMethod();
@@ -1313,13 +1312,30 @@
   code_ += B->StoreStaticField(position_, field);
 }
 
+void BytecodeFlowGraphBuilder::BuildInitLateField() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  }
+
+  LoadStackSlots(1);
+  Operand cp_index = DecodeOperandD();
+
+  const Field& field = Field::Cast(ConstantAt(cp_index, 1).value());
+  ASSERT(Smi::Cast(ConstantAt(cp_index).value()).Value() * kWordSize ==
+         field.Offset());
+
+  code_ += B->Constant(Object::sentinel());
+  code_ += B->StoreInstanceField(
+      field, StoreInstanceFieldInstr::Kind::kInitializing, kNoStoreBarrier);
+}
+
 void BytecodeFlowGraphBuilder::BuildLoadStatic() {
   const Constant operand = ConstantAt(DecodeOperandD());
   const auto& field = Field::Cast(operand.value());
   // All constant expressions (including access to const fields) are evaluated
   // in bytecode. However, values of injected cid fields are only available in
   // the VM. In such case, evaluate const fields with known value here.
-  if (field.is_const() && !field.has_initializer()) {
+  if (field.is_const() && !field.has_nontrivial_initializer()) {
     const auto& value = Object::ZoneHandle(Z, field.StaticValue());
     ASSERT((value.raw() != Object::sentinel().raw()) &&
            (value.raw() != Object::transition_sentinel().raw()));
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index c32f8d2..cbc4c49 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -1956,7 +1956,7 @@
                                                  bool discard_fields) {
   // Field flags, must be in sync with FieldDeclaration constants in
   // pkg/vm/lib/bytecode/declarations.dart.
-  const int kHasInitializerFlag = 1 << 0;
+  const int kHasNontrivialInitializerFlag = 1 << 0;
   const int kHasGetterFlag = 1 << 1;
   const int kHasSetterFlag = 1 << 2;
   const int kIsReflectableFlag = 1 << 3;
@@ -1973,6 +1973,7 @@
   const int kHasAttributesFlag = 1 << 14;
   const int kIsLateFlag = 1 << 15;
   const int kIsExtensionMemberFlag = 1 << 16;
+  const int kHasInitializerFlag = 1 << 17;
 
   const int num_fields = reader_.ReadListLength();
   if ((num_fields == 0) && !cls.is_enum_class()) {
@@ -1993,9 +1994,12 @@
     const bool is_static = (flags & kIsStaticFlag) != 0;
     const bool is_final = (flags & kIsFinalFlag) != 0;
     const bool is_const = (flags & kIsConstFlag) != 0;
-    const bool has_initializer = (flags & kHasInitializerFlag) != 0;
+    const bool is_late = (flags & kIsLateFlag) != 0;
+    const bool has_nontrivial_initializer =
+        (flags & kHasNontrivialInitializerFlag) != 0;
     const bool has_pragma = (flags & kHasPragmaFlag) != 0;
     const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0;
+    const bool has_initializer = (flags & kHasInitializerFlag) != 0;
 
     name ^= ReadObject();
     type ^= ReadObject();
@@ -2023,14 +2027,19 @@
     field.set_is_covariant((flags & kIsCovariantFlag) != 0);
     field.set_is_generic_covariant_impl((flags & kIsGenericCovariantImplFlag) !=
                                         0);
-    field.set_has_initializer(has_initializer);
+    field.set_has_nontrivial_initializer(has_nontrivial_initializer);
     field.set_is_late((flags & kIsLateFlag) != 0);
     field.set_is_extension_member(is_extension_member);
+    field.set_has_initializer(has_initializer);
 
-    if (!has_initializer) {
+    if (!has_nontrivial_initializer) {
       value ^= ReadObject();
       if (is_static) {
-        field.SetStaticValue(value, true);
+        if (field.is_late() && !has_initializer) {
+          field.SetStaticValue(Object::sentinel(), true);
+        } else {
+          field.SetStaticValue(value, true);
+        }
       } else {
         field.set_saved_initial_value(value);
         // Null-initialized instance fields are tracked separately for each
@@ -2072,7 +2081,7 @@
       function.set_accessor_field(field);
       function.set_is_declared_in_bytecode(true);
       function.set_is_extension_member(is_extension_member);
-      if (is_const && has_initializer) {
+      if (is_const && has_nontrivial_initializer) {
         function.set_bytecode_offset(field.bytecode_offset());
       }
       H.SetupFieldAccessorFunction(cls, function, type);
@@ -2080,10 +2089,10 @@
     }
 
     if ((flags & kHasSetterFlag) != 0) {
-      ASSERT((!is_static) && (!is_final) && (!is_const));
+      ASSERT(is_late || ((!is_static) && (!is_final)));
+      ASSERT(!is_const);
       name ^= ReadObject();
-      function = Function::New(name, RawFunction::kImplicitSetter,
-                               false,  // is_static
+      function = Function::New(name, RawFunction::kImplicitSetter, is_static,
                                false,  // is_const
                                false,  // is_abstract
                                false,  // is_external
@@ -3670,7 +3679,7 @@
 
   const auto& field = Field::Handle(zone, function.accessor_field());
   return field.is_declared_in_bytecode() && field.is_const() &&
-         field.has_initializer();
+         field.has_nontrivial_initializer();
 }
 
 }  // namespace kernel
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
deleted file mode 100644
index 643e0b4..0000000
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ /dev/null
@@ -1,1371 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "vm/compiler/frontend/constant_evaluator.h"
-
-#include "vm/compiler/aot/precompiler.h"
-#include "vm/compiler/frontend/kernel_to_il.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/longjump.h"
-#include "vm/object_store.h"
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-
-namespace dart {
-namespace kernel {
-
-#define Z (zone_)
-#define H (translation_helper_)
-#define T (type_translator_)
-#define I Isolate::Current()
-
-ConstantEvaluator::ConstantEvaluator(KernelReaderHelper* helper,
-                                     TypeTranslator* type_translator,
-                                     ActiveClass* active_class,
-                                     FlowGraphBuilder* flow_graph_builder)
-    : helper_(helper),
-      isolate_(Isolate::Current()),
-      zone_(helper->zone_),
-      translation_helper_(helper->translation_helper_),
-      type_translator_(*type_translator),
-      active_class_(active_class),
-      flow_graph_builder_(flow_graph_builder),
-      script_(helper->script()),
-      result_(Instance::Handle(zone_)) {}
-
-bool ConstantEvaluator::IsCached(intptr_t offset) {
-  return GetCachedConstant(offset, &result_);
-}
-
-RawInstance* ConstantEvaluator::EvaluateExpression(intptr_t offset,
-                                                   bool reset_position) {
-  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
-  if (!GetCachedConstant(offset, &result_)) {
-    BailoutIfBackgroundCompilation();
-
-    ASSERT(IsAllowedToEvaluate());
-    intptr_t original_offset = helper_->ReaderOffset();
-    helper_->SetOffset(offset);
-    uint8_t payload = 0;
-    Tag tag = helper_->ReadTag(&payload);  // read tag.
-    switch (tag) {
-      case kVariableGet:
-        EvaluateVariableGet(/* is_specialized = */ false);
-        break;
-      case kSpecializedVariableGet:
-        EvaluateVariableGet(/* is_specialized = */ true);
-        break;
-      case kPropertyGet:
-        EvaluatePropertyGet();
-        break;
-      case kDirectPropertyGet:
-        EvaluateDirectPropertyGet();
-        break;
-      case kStaticGet:
-        EvaluateStaticGet();
-        break;
-      case kMethodInvocation:
-        EvaluateMethodInvocation();
-        break;
-      case kDirectMethodInvocation:
-        EvaluateDirectMethodInvocation();
-        break;
-      case kSuperMethodInvocation:
-        EvaluateSuperMethodInvocation();
-        break;
-      case kStaticInvocation:
-      case kConstStaticInvocation:
-        EvaluateStaticInvocation();
-        break;
-      case kConstConstructorInvocation:
-        EvaluateConstructorInvocationInternal();
-        break;
-      case kNot:
-        EvaluateNot();
-        break;
-      case kLogicalExpression:
-        EvaluateLogicalExpression();
-        break;
-      case kConditionalExpression:
-        EvaluateConditionalExpression();
-        break;
-      case kStringConcatenation:
-        EvaluateStringConcatenation();
-        break;
-      case kListConcatenation:
-      case kSetConcatenation:
-      case kMapConcatenation:
-      case kInstanceCreation:
-      case kFileUriExpression:
-        // These only occur inside unevaluated constants, so if we decide to
-        // remove support for late evaluation of environment constants from
-        // dill files in the VM, an implementation here will not be necessary.
-        H.ReportError(
-            script_, TokenPosition::kNoSource,
-            "Unexpected unevaluated constant, All constant expressions"
-            " are expected to be evaluated at this point %s (%d)",
-            Reader::TagName(tag), tag);
-        break;
-      case kSymbolLiteral:
-        EvaluateSymbolLiteral();
-        break;
-      case kTypeLiteral:
-        EvaluateTypeLiteral();
-        break;
-      case kAsExpression:
-        EvaluateAsExpression();
-        break;
-      case kConstListLiteral:
-        EvaluateListLiteralInternal();
-        break;
-      case kConstSetLiteral:
-        // Set literals are currently desugared in the frontend and will not
-        // reach the VM. See http://dartbug.com/35124 for discussion.
-        H.ReportError(script_, TokenPosition::kNoSource,
-                      "Unexpected set literal constant, this constant"
-                      " is expected to be evaluated at this point %s (%d)",
-                      Reader::TagName(tag), tag);
-        break;
-      case kConstMapLiteral:
-        EvaluateMapLiteralInternal();
-        break;
-      case kLet:
-        EvaluateLet();
-        break;
-      case kBlockExpression: {
-        UNIMPLEMENTED();
-        break;
-      }
-      case kInstantiation:
-        EvaluatePartialTearoffInstantiation();
-        break;
-      case kBigIntLiteral:
-        EvaluateBigIntLiteral();
-        break;
-      case kStringLiteral:
-        EvaluateStringLiteral();
-        break;
-      case kSpecializedIntLiteral:
-        EvaluateIntLiteral(payload);
-        break;
-      case kNegativeIntLiteral:
-        EvaluateIntLiteral(true);
-        break;
-      case kPositiveIntLiteral:
-        EvaluateIntLiteral(false);
-        break;
-      case kDoubleLiteral:
-        EvaluateDoubleLiteral();
-        break;
-      case kTrueLiteral:
-        EvaluateBoolLiteral(true);
-        break;
-      case kFalseLiteral:
-        EvaluateBoolLiteral(false);
-        break;
-      case kNullLiteral:
-        EvaluateNullLiteral();
-        break;
-      case kConstantExpression:
-        helper_->ReadPosition();
-        helper_->SkipDartType();
-        result_ = EvaluateConstantExpression(helper_->ReadUInt());
-        break;
-      case kDeprecated_ConstantExpression:
-        result_ = EvaluateConstantExpression(helper_->ReadUInt());
-        break;
-      case kInvalidExpression: {
-        helper_->ReadPosition();  // Skip position.
-        const String& message = H.DartString(helper_->ReadStringReference());
-        // Invalid expression message has pointer to the source code, no need to
-        // report it twice.
-        H.ReportError(helper_->script(), TokenPosition::kNoSource, "%s",
-                      message.ToCString());
-        break;
-      }
-      default:
-        H.ReportError(
-            script_, TokenPosition::kNoSource,
-            "Not a constant expression: unexpected kernel tag %s (%d)",
-            Reader::TagName(tag), tag);
-    }
-
-    CacheConstantValue(offset, result_);
-    if (reset_position) helper_->SetOffset(original_offset);
-  } else {
-    if (!reset_position) {
-      helper_->SetOffset(offset);
-      helper_->SkipExpression();
-    }
-  }
-  return result_.raw();
-}
-
-Instance& ConstantEvaluator::EvaluateListLiteral(intptr_t offset,
-                                                 bool reset_position) {
-  if (!GetCachedConstant(offset, &result_)) {
-    BailoutIfBackgroundCompilation();
-
-    ASSERT(IsAllowedToEvaluate());
-    intptr_t original_offset = helper_->ReaderOffset();
-    helper_->SetOffset(offset);
-    helper_->ReadTag();  // skip tag.
-    EvaluateListLiteralInternal();
-
-    CacheConstantValue(offset, result_);
-    if (reset_position) helper_->SetOffset(original_offset);
-  }
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return Instance::ZoneHandle(Z, result_.raw());
-}
-
-Instance& ConstantEvaluator::EvaluateMapLiteral(intptr_t offset,
-                                                bool reset_position) {
-  if (!GetCachedConstant(offset, &result_)) {
-    BailoutIfBackgroundCompilation();
-
-    ASSERT(IsAllowedToEvaluate());
-    intptr_t original_offset = helper_->ReaderOffset();
-    helper_->SetOffset(offset);
-    helper_->ReadTag();  // skip tag.
-    EvaluateMapLiteralInternal();
-
-    CacheConstantValue(offset, result_);
-    if (reset_position) helper_->SetOffset(original_offset);
-  }
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return Instance::ZoneHandle(Z, result_.raw());
-}
-
-Instance& ConstantEvaluator::EvaluateConstructorInvocation(
-    intptr_t offset,
-    bool reset_position) {
-  if (!GetCachedConstant(offset, &result_)) {
-    BailoutIfBackgroundCompilation();
-
-    ASSERT(IsAllowedToEvaluate());
-    intptr_t original_offset = helper_->ReaderOffset();
-    helper_->SetOffset(offset);
-    helper_->ReadTag();  // skip tag.
-    EvaluateConstructorInvocationInternal();
-
-    CacheConstantValue(offset, result_);
-    if (reset_position) helper_->SetOffset(original_offset);
-  }
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return Instance::ZoneHandle(Z, result_.raw());
-}
-
-Instance& ConstantEvaluator::EvaluateStaticInvocation(intptr_t offset,
-                                                      bool reset_position) {
-  if (!GetCachedConstant(offset, &result_)) {
-    BailoutIfBackgroundCompilation();
-
-    ASSERT(IsAllowedToEvaluate());
-    intptr_t original_offset = helper_->ReaderOffset();
-    helper_->SetOffset(offset);
-    helper_->ReadTag();  // skip tag.
-    EvaluateStaticInvocation();
-
-    CacheConstantValue(offset, result_);
-    if (reset_position) helper_->SetOffset(original_offset);
-  }
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return Instance::ZoneHandle(Z, result_.raw());
-}
-
-RawObject* ConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) {
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    return EvaluateExpression(offset);
-  } else {
-    return H.thread()->StealStickyError();
-  }
-}
-
-RawObject* ConstantEvaluator::EvaluateAnnotations() {
-  intptr_t list_length = helper_->ReadListLength();  // read list length.
-  const Array& metadata_values =
-      Array::Handle(Z, Array::New(list_length, H.allocation_space()));
-  Instance& value = Instance::Handle(Z);
-  for (intptr_t i = 0; i < list_length; ++i) {
-    // this will (potentially) read the expression, but reset the position.
-    value = EvaluateExpression(helper_->ReaderOffset());
-    helper_->SkipExpression();  // read (actual) initializer.
-    metadata_values.SetAt(i, value);
-  }
-  return metadata_values.raw();
-}
-
-RawInstance* ConstantEvaluator::EvaluateConstantExpression(
-    intptr_t constant_offset) {
-  ASSERT(!H.constants().IsNull());
-  ASSERT(!H.constants_table().IsNull());  // raw bytes
-
-  // For kernel-level cache (in contrast with script-level caching),
-  // we need to access the raw constants array inside the shared
-  // KernelProgramInfo directly, so that all scripts will see the
-  // results after new insertions. These accesses at kernel-level
-  // must be locked since mutator and background compiler can
-  // access the array at the same time.
-  {
-    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
-    KernelConstantsMap constant_map(H.info().constants());
-    result_ ^= constant_map.GetOrNull(constant_offset);
-    ASSERT(constant_map.Release().raw() == H.info().constants());
-  }
-
-  // On miss, evaluate, and insert value.
-  if (result_.IsNull()) {
-    result_ = EvaluateConstant(constant_offset);
-    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
-    KernelConstantsMap constant_map(H.info().constants());
-    auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
-    ASSERT(insert == result_.raw());
-    H.info().set_constants(constant_map.Release());  // update!
-  }
-  return result_.raw();
-}
-
-bool ConstantEvaluator::IsInstanceConstant(intptr_t constant_offset,
-                                           const Class& clazz) {
-  // Get reader directly into raw bytes of constant table.
-  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
-  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
-  reader.SetOffset(reader.ReaderOffset() + constant_offset);
-  // Peek for an instance of the given clazz.
-  if (reader.ReadByte() == kInstanceConstant) {
-    const NameIndex index = reader.ReadCanonicalNameReference();
-    return H.LookupClassByKernelClass(index) == clazz.raw();
-  }
-  return false;
-}
-
-RawInstance* ConstantEvaluator::EvaluateConstant(intptr_t constant_offset) {
-  // Get reader directly into raw bytes of constant table.
-  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
-  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
-  reader.SetOffset(reader.ReaderOffset() + constant_offset);
-  // Construct constant from raw bytes.
-  Instance& instance = Instance::Handle(Z);
-  const intptr_t constant_tag = reader.ReadByte();
-  switch (constant_tag) {
-    case kNullConstant:
-      instance = Instance::null();
-      break;
-    case kBoolConstant:
-      instance = reader.ReadByte() == 1 ? Object::bool_true().raw()
-                                        : Object::bool_false().raw();
-      break;
-    case kIntConstant: {
-      uint8_t payload = 0;
-      Tag integer_tag = reader.ReadTag(&payload);  // read tag.
-      switch (integer_tag) {
-        case kBigIntLiteral: {
-          const String& value = H.DartString(reader.ReadStringReference());
-          instance = Integer::New(value, Heap::kOld);
-          break;
-        }
-        case kSpecializedIntLiteral: {
-          const int64_t value =
-              static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
-          instance = Integer::New(value, Heap::kOld);
-          break;
-        }
-        case kNegativeIntLiteral: {
-          const int64_t value = -static_cast<int64_t>(reader.ReadUInt());
-          instance = Integer::New(value, Heap::kOld);
-          break;
-        }
-        case kPositiveIntLiteral: {
-          const int64_t value = reader.ReadUInt();
-          instance = Integer::New(value, Heap::kOld);
-          break;
-        }
-        default:
-          H.ReportError(
-              script_, TokenPosition::kNoSource,
-              "Cannot lazily read integer: unexpected kernel tag %s (%d)",
-              Reader::TagName(integer_tag), integer_tag);
-      }
-      break;
-    }
-    case kDoubleConstant:
-      instance = Double::New(reader.ReadDouble(), Heap::kOld);
-      break;
-    case kStringConstant:
-      instance = H.DartSymbolPlain(reader.ReadStringReference()).raw();
-      break;
-    case kSymbolConstant: {
-      Library& library = Library::Handle(Z);
-      library = Library::InternalLibrary();
-      const auto& symbol_class =
-          Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
-      const auto& symbol_name_field = Field::Handle(
-          Z, symbol_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
-      ASSERT(!symbol_name_field.IsNull());
-      const NameIndex index = reader.ReadCanonicalNameReference();
-      if (index == -1) {
-        library = Library::null();
-      } else {
-        library = H.LookupLibraryByKernelLibrary(index);
-      }
-      const String& symbol =
-          H.DartIdentifier(library, reader.ReadStringReference());
-      instance = Instance::New(symbol_class, Heap::kOld);
-      instance.SetField(symbol_name_field, symbol);
-      break;
-    }
-    case kListConstant: {
-      const auto& corelib = Library::Handle(Z, Library::CoreLibrary());
-      const auto& list_class =
-          Class::Handle(Z, corelib.LookupClassAllowPrivate(Symbols::_List()));
-      // Build type from the raw bytes (needs temporary translator).
-      TypeTranslator type_translator(&reader, active_class_, true);
-      auto& type_arguments =
-          TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
-      AbstractType& type = type_translator.BuildType();
-      type_arguments.SetTypeAt(0, type);
-      // Instantiate class.
-      type = Type::New(list_class, type_arguments, TokenPosition::kNoSource);
-      type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
-                                          ClassFinalizer::kCanonicalize);
-      type_arguments = type.arguments();
-      // Fill array with constant elements.
-      const intptr_t length = reader.ReadUInt();
-      const Array& array =
-          Array::Handle(Z, ImmutableArray::New(length, Heap::kOld));
-      array.SetTypeArguments(type_arguments);
-      Instance& constant = Instance::Handle(Z);
-      for (intptr_t j = 0; j < length; ++j) {
-        // Recurse into lazily evaluating all "sub" constants
-        // needed to evaluate the current constant.
-        const intptr_t entry_offset = reader.ReadUInt();
-        ASSERT(entry_offset < constant_offset);  // DAG!
-        constant = EvaluateConstantExpression(entry_offset);
-        array.SetAt(j, constant);
-      }
-      instance = array.raw();
-      break;
-    }
-    case kInstanceConstant: {
-      const NameIndex index = reader.ReadCanonicalNameReference();
-      const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
-      if (!klass.is_declaration_loaded() && !klass.is_declared_in_bytecode()) {
-        FATAL1(
-            "Trying to evaluate an instance constant whose references class "
-            "%s is not loaded yet.",
-            klass.ToCString());
-      }
-      const auto& obj = Object::Handle(Z, klass.EnsureIsFinalized(H.thread()));
-      ASSERT(obj.IsNull());
-      instance = Instance::New(klass, Heap::kOld);
-      // Build type from the raw bytes (needs temporary translator).
-      TypeTranslator type_translator(&reader, active_class_, true);
-      const intptr_t number_of_type_arguments = reader.ReadUInt();
-      if (klass.NumTypeArguments() > 0) {
-        auto& type_arguments = TypeArguments::Handle(
-            Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
-        for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
-          type_arguments.SetTypeAt(j, type_translator.BuildType());
-        }
-        // Instantiate class.
-        auto& type = AbstractType::Handle(
-            Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
-        type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
-                                            ClassFinalizer::kCanonicalize);
-        type_arguments = type.arguments();
-        instance.SetTypeArguments(type_arguments);
-      } else {
-        ASSERT(number_of_type_arguments == 0);
-      }
-      // Set the fields.
-      const intptr_t number_of_fields = reader.ReadUInt();
-      Field& field = Field::Handle(Z);
-      Instance& constant = Instance::Handle(Z);
-      for (intptr_t j = 0; j < number_of_fields; ++j) {
-        field = H.LookupFieldByKernelField(reader.ReadCanonicalNameReference());
-        // Recurse into lazily evaluating all "sub" constants
-        // needed to evaluate the current constant.
-        const intptr_t entry_offset = reader.ReadUInt();
-        ASSERT(entry_offset < constant_offset);  // DAG!
-        constant = EvaluateConstantExpression(entry_offset);
-        instance.SetField(field, constant);
-      }
-      break;
-    }
-    case kPartialInstantiationConstant: {
-      // Recurse into lazily evaluating the "sub" constant
-      // needed to evaluate the current constant.
-      const intptr_t entry_offset = reader.ReadUInt();
-      ASSERT(entry_offset < constant_offset);  // DAG!
-      const auto& constant =
-          Instance::Handle(Z, EvaluateConstantExpression(entry_offset));
-      ASSERT(!constant.IsNull());
-
-      // Build type from the raw bytes (needs temporary translator).
-      TypeTranslator type_translator(&reader, active_class_, true);
-      const intptr_t number_of_type_arguments = reader.ReadUInt();
-      ASSERT(number_of_type_arguments > 0);
-      auto& type_arguments = TypeArguments::Handle(
-          Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
-      for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
-        type_arguments.SetTypeAt(j, type_translator.BuildType());
-      }
-      type_arguments = type_arguments.Canonicalize();
-      // Make a copy of the old closure, and set delayed type arguments.
-      Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.raw()));
-      Function& function = Function::Handle(Z, closure.function());
-      const auto& type_arguments2 =
-          TypeArguments::Handle(Z, closure.instantiator_type_arguments());
-      // The function type arguments are used for type parameters from enclosing
-      // closures. Though inner closures cannot be constants. We should
-      // therefore see `null here.
-      ASSERT(closure.function_type_arguments() == TypeArguments::null());
-      Context& context = Context::Handle(Z, closure.context());
-      instance = Closure::New(type_arguments2, Object::null_type_arguments(),
-                              type_arguments, function, context, Heap::kOld);
-      break;
-    }
-    case kTearOffConstant: {
-      const NameIndex index = reader.ReadCanonicalNameReference();
-      Function& function =
-          Function::Handle(Z, H.LookupStaticMethodByKernelProcedure(index));
-      function = function.ImplicitClosureFunction();
-      instance = function.ImplicitStaticClosure();
-      break;
-    }
-    case kTypeLiteralConstant: {
-      // Build type from the raw bytes (needs temporary translator).
-      TypeTranslator type_translator(&reader, active_class_, true);
-      instance = type_translator.BuildType().raw();
-      break;
-    }
-    default:
-      // Set literals (kSetConstant) are currently desugared in the frontend
-      // and will not reach the VM. See http://dartbug.com/35124 for some
-      // discussion. Map constants (kMapConstant ) are already lowered to
-      // InstanceConstant or ListConstant. We should never see unevaluated
-      // constants (kUnevaluatedConstant) in the constant table, they should
-      // have been fully evaluated before we get them.
-      H.ReportError(script_, TokenPosition::kNoSource,
-                    "Cannot lazily read constant: unexpected kernel tag (%" Pd
-                    ")",
-                    constant_tag);
-  }
-  return H.Canonicalize(instance);
-}
-
-void ConstantEvaluator::BailoutIfBackgroundCompilation() {
-  if (Compiler::IsBackgroundCompilation()) {
-    Compiler::AbortBackgroundCompilation(
-        DeoptId::kNone, "Cannot evaluate annotations in background compiler.");
-  }
-}
-
-bool ConstantEvaluator::IsBuildingFlowGraph() const {
-  return flow_graph_builder_ != nullptr;
-}
-
-bool ConstantEvaluator::IsAllowedToEvaluate() const {
-  return FLAG_precompiled_mode || !IsBuildingFlowGraph() ||
-         !flow_graph_builder_->optimizing_;
-}
-
-void ConstantEvaluator::EvaluateVariableGet(bool is_specialized) {
-  ASSERT(IsBuildingFlowGraph());
-  // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
-  // been executed already. It therefore must have a constant object associated
-  // with it.
-  const TokenPosition position = helper_->ReadPosition();  // read position.
-  const intptr_t variable_kernel_position =
-      helper_->ReadUInt();  // read kernel position.
-  if (!is_specialized) {
-    helper_->ReadUInt();              // read relative variable index.
-    helper_->SkipOptionalDartType();  // read promoted type.
-  }
-  LocalVariable* variable =
-      flow_graph_builder_->LookupVariable(variable_kernel_position);
-  if (!variable->IsConst()) {
-    H.ReportError(script_, position, "Not a constant expression.");
-  }
-  result_ = variable->ConstValue()->raw();
-}
-
-void ConstantEvaluator::EvaluateGetStringLength(intptr_t expression_offset,
-                                                TokenPosition position) {
-  EvaluateExpression(expression_offset);
-  if (result_.IsString()) {
-    const auto& str = String::Handle(Z, String::RawCast(result_.raw()));
-    result_ = Integer::New(str.Length(), H.allocation_space());
-  } else {
-    H.ReportError(
-        script_, position,
-        "Constant expressions can only call 'length' on string constants.");
-  }
-}
-
-void ConstantEvaluator::EvaluatePropertyGet() {
-  const TokenPosition position = helper_->ReadPosition();  // read position.
-  intptr_t expression_offset = helper_->ReaderOffset();
-  helper_->SkipExpression();                            // read receiver.
-  StringIndex name = helper_->ReadNameAsStringIndex();  // read name.
-  helper_->SkipCanonicalNameReference();  // read interface_target_reference.
-
-  if (H.StringEquals(name, "length")) {
-    EvaluateGetStringLength(expression_offset, position);
-  } else {
-    H.ReportError(
-        script_, position,
-        "Constant expressions can only call 'length' on string constants.");
-  }
-}
-
-void ConstantEvaluator::EvaluateDirectPropertyGet() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-  intptr_t expression_offset = helper_->ReaderOffset();
-  helper_->SkipExpression();  // read receiver.
-  NameIndex kernel_name =
-      helper_->ReadCanonicalNameReference();  // read target_reference.
-
-  // TODO(vegorov): add check based on the complete canonical name.
-  if (H.IsGetter(kernel_name) &&
-      H.StringEquals(H.CanonicalNameString(kernel_name), "length")) {
-    EvaluateGetStringLength(expression_offset, position);
-  } else {
-    H.ReportError(
-        script_, position,
-        "Constant expressions can only call 'length' on string constants.");
-  }
-}
-
-void ConstantEvaluator::EvaluateStaticGet() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-  NameIndex target =
-      helper_->ReadCanonicalNameReference();  // read target_reference.
-
-  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
-
-  if (H.IsField(target)) {
-    const auto& field = Field::Handle(Z, H.LookupFieldByKernelField(target));
-    if (!field.is_const()) {
-      H.ReportError(script_, position, "Not a constant field.");
-    }
-    if (field.StaticValue() == Object::transition_sentinel().raw()) {
-      if (IsBuildingFlowGraph()) {
-        flow_graph_builder_->InlineBailout(
-            "kernel::ConstantEvaluator::EvaluateStaticGet::Cyclic");
-      }
-      H.ReportError(script_, position, "Not a constant expression.");
-    } else if (field.StaticValue() == Object::sentinel().raw()) {
-      field.SetStaticValue(Object::transition_sentinel());
-      const auto& value = Object::Handle(Z, field.EvaluateInitializer());
-      if (value.IsError()) {
-        field.SetStaticValue(Object::null_instance());
-        H.ReportError(Error::Cast(value), script_, position,
-                      "Not a constant expression.");
-      }
-      Thread* thread = H.thread();
-      const Error& error =
-          Error::Handle(thread->zone(), thread->StealStickyError());
-      if (!error.IsNull()) {
-        field.SetStaticValue(Object::null_instance());
-        H.ReportError(error, script_, position, "Not a constant expression.");
-      }
-      ASSERT(value.IsNull() || value.IsInstance());
-      field.SetStaticValue(value.IsNull() ? Instance::null_instance()
-                                          : Instance::Cast(value));
-
-      result_ = field.StaticValue();
-      result_ = H.Canonicalize(result_);
-      field.SetStaticValue(result_, true);
-    } else {
-      result_ = field.StaticValue();
-    }
-  } else if (H.IsProcedure(target)) {
-    const auto& function =
-        Function::Handle(Z, H.LookupStaticMethodByKernelProcedure(target));
-
-    if (H.IsMethod(target)) {
-      const auto& closure_function =
-          Function::Handle(Z, function.ImplicitClosureFunction());
-      result_ = closure_function.ImplicitStaticClosure();
-      result_ = H.Canonicalize(result_);
-    } else if (H.IsGetter(target)) {
-      H.ReportError(script_, position, "Not a constant expression.");
-    } else {
-      H.ReportError(script_, position, "Not a constant expression.");
-    }
-  }
-}
-
-void ConstantEvaluator::EvaluateMethodInvocation() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-  // This method call wasn't cached, so receiver et al. isn't cached either.
-  const auto& receiver = Instance::Handle(
-      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.
-  Class& klass =
-      Class::Handle(Z, isolate_->class_table()->At(receiver.GetClassId()));
-  ASSERT(!klass.IsNull());
-
-  // Search the superclass chain for the selector.
-  const String& method_name = helper_->ReadNameAsMethodName();  // read name.
-  Function& function =
-      Function::Handle(Z, H.LookupDynamicFunction(klass, method_name));
-
-  // The frontend should guarantee that [MethodInvocation]s inside constant
-  // expressions are always valid.
-  ASSERT(!function.IsNull());
-
-  // Read arguments, run the method and canonicalize the result.
-  const Object& result = RunMethodCall(position, function, &receiver);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-
-  helper_->SkipCanonicalNameReference();  // read interface_target_reference.
-}
-
-void ConstantEvaluator::EvaluateDirectMethodInvocation() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-
-  const auto& receiver = Instance::Handle(
-      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.
-
-  NameIndex kernel_name =
-      helper_->ReadCanonicalNameReference();  // read target_reference.
-
-  const auto& function = Function::Handle(
-      Z, H.LookupMethodByMember(kernel_name, H.DartProcedureName(kernel_name)));
-
-  // Read arguments, run the method and canonicalize the result.
-  const Object& result = RunMethodCall(position, function, &receiver);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateSuperMethodInvocation() {
-  ASSERT(IsBuildingFlowGraph());
-  TokenPosition position = helper_->ReadPosition();  // read position.
-
-  const LocalVariable* receiver_variable =
-      flow_graph_builder_->parsed_function_->receiver_var();
-  ASSERT(receiver_variable->IsConst());
-  const Instance& receiver =
-      Instance::Handle(Z, receiver_variable->ConstValue()->raw());
-  ASSERT(!receiver.IsNull());
-
-  Class& klass = Class::Handle(Z, active_class_->klass->SuperClass());
-  ASSERT(!klass.IsNull());
-
-  const String& method_name = helper_->ReadNameAsMethodName();  // read name.
-  const auto& function =
-      Function::Handle(Z, H.LookupDynamicFunction(klass, method_name));
-
-  // The frontend should guarantee that [MethodInvocation]s inside constant
-  // expressions are always valid.
-  ASSERT(!function.IsNull());
-
-  // Read arguments, run the method and canonicalize the result.
-  const Object& result = RunMethodCall(position, function, &receiver);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-
-  helper_->SkipCanonicalNameReference();  // read interface_target_reference.
-}
-
-void ConstantEvaluator::EvaluateStaticInvocation() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-  NameIndex procedure_reference =
-      helper_->ReadCanonicalNameReference();  // read procedure reference.
-
-  const auto& function = Function::Handle(
-      Z, H.LookupStaticMethodByKernelProcedure(procedure_reference));
-  Class& klass = Class::Handle(Z, function.Owner());
-
-  intptr_t argument_count =
-      helper_->ReadUInt();  // read arguments part #1: arguments count.
-
-  // Build the type arguments vector (if necessary).
-  const TypeArguments* type_arguments =
-      TranslateTypeArguments(function, &klass);  // read argument types.
-
-  // read positional and named parameters.
-  const Object& result =
-      RunFunction(position, function, argument_count, NULL, type_arguments);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateConstructorInvocationInternal() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-
-  NameIndex target = helper_->ReadCanonicalNameReference();  // read target.
-  const auto& constructor =
-      Function::Handle(Z, H.LookupConstructorByKernelConstructor(target));
-  Class& klass = Class::Handle(Z, constructor.Owner());
-
-  intptr_t argument_count =
-      helper_->ReadUInt();  // read arguments part #1: arguments count.
-
-  // Build the type arguments vector (if necessary).
-  const TypeArguments* type_arguments =
-      TranslateTypeArguments(constructor, &klass);  // read argument types.
-
-  if (klass.NumTypeArguments() > 0 && !klass.IsGeneric()) {
-    auto& type = Type::Handle(Z, T.ReceiverType(klass).raw());
-    // TODO(27590): Can we move this code into [ReceiverType]?
-    type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type,
-                                         ClassFinalizer::kFinalize);
-    auto& canonicalized_type_arguments =
-        TypeArguments::Handle(Z, type.arguments());
-    canonicalized_type_arguments = canonicalized_type_arguments.Canonicalize();
-    type_arguments = &canonicalized_type_arguments;
-  }
-
-  // Prepare either the instance or the type argument vector for the constructor
-  // call.
-  Instance* receiver = NULL;
-  const TypeArguments* type_arguments_argument = NULL;
-  if (!constructor.IsFactory()) {
-    receiver = &Instance::Handle(Z, Instance::New(klass, Heap::kOld));
-    if (type_arguments != NULL) {
-      receiver->SetTypeArguments(*type_arguments);
-    }
-  } else {
-    type_arguments_argument = type_arguments;
-  }
-
-  // read positional and named parameters.
-  const Object& result = RunFunction(position, constructor, argument_count,
-                                     receiver, type_arguments_argument);
-
-  if (constructor.IsFactory()) {
-    // Factories return the new object.
-    result_ ^= result.raw();
-  } else {
-    ASSERT(!receiver->IsNull());
-    result_ = (*receiver).raw();
-  }
-  if (I->obfuscate() &&
-      (result_.clazz() == I->object_store()->symbol_class())) {
-    Obfuscator::ObfuscateSymbolInstance(H.thread(), result_);
-  }
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateNot() {
-  result_ = Bool::Get(!EvaluateBooleanExpressionHere()).raw();
-}
-
-void ConstantEvaluator::EvaluateLogicalExpression() {
-  bool left = EvaluateBooleanExpressionHere();  // read left.
-  LogicalOperator op = static_cast<LogicalOperator>(helper_->ReadByte());
-  if (op == kAnd) {
-    if (left) {
-      EvaluateBooleanExpressionHere();  // read right.
-    } else {
-      helper_->SkipExpression();  // read right.
-    }
-  } else {
-    ASSERT(op == kOr);
-    if (!left) {
-      EvaluateBooleanExpressionHere();  // read right.
-    } else {
-      helper_->SkipExpression();  // read right.
-    }
-  }
-}
-
-void ConstantEvaluator::EvaluateAsExpression() {
-  TokenPosition position = helper_->ReadPosition();
-  const uint8_t flags = helper_->ReadFlags();
-  const bool is_type_error = (flags & (1 << 0)) != 0;
-
-  // Check that this AsExpression was inserted by the front-end.
-  if (!is_type_error) {
-    H.ReportError(
-        script_, position,
-        "explicit as operator is not permitted in constant expression");
-  }
-
-  EvaluateExpression(helper_->ReaderOffset(), false);
-
-  const AbstractType& type = T.BuildType();
-  if (!type.IsInstantiated()) {
-    const auto& type_str = String::Handle(type.UserVisibleName());
-    H.ReportError(
-        script_, position,
-        "Not a constant expression: right hand side of an implicit "
-        "as-expression is expected to be an instantiated type, got %s",
-        type_str.ToCString());
-  }
-
-  const auto& instantiator_type_arguments = TypeArguments::Handle();
-  const auto& function_type_arguments = TypeArguments::Handle();
-  if (!result_.IsInstanceOf(type, instantiator_type_arguments,
-                            function_type_arguments)) {
-    const AbstractType& rtype =
-        AbstractType::Handle(result_.GetType(Heap::kNew));
-    const auto& result_str = String::Handle(rtype.UserVisibleName());
-    const auto& type_str = String::Handle(type.UserVisibleName());
-    H.ReportError(
-        script_, position,
-        "Not a constant expression: Type '%s' is not a subtype of type '%s'",
-        result_str.ToCString(), type_str.ToCString());
-  }
-}
-
-void ConstantEvaluator::EvaluateConditionalExpression() {
-  bool condition = EvaluateBooleanExpressionHere();
-  if (condition) {
-    EvaluateExpression(helper_->ReaderOffset(), false);  // read then.
-    helper_->SkipExpression();                           // read otherwise.
-  } else {
-    helper_->SkipExpression();                           // read then.
-    EvaluateExpression(helper_->ReaderOffset(), false);  // read otherwise.
-  }
-  helper_->SkipOptionalDartType();  // read unused static type.
-}
-
-void ConstantEvaluator::EvaluateStringConcatenation() {
-  TokenPosition position = helper_->ReadPosition();  // read position.
-  intptr_t length = helper_->ReadListLength();       // read list length.
-
-  bool all_string = true;
-  const Array& strings =
-      Array::Handle(Z, Array::New(length, H.allocation_space()));
-  for (intptr_t i = 0; i < length; ++i) {
-    EvaluateExpression(helper_->ReaderOffset(),
-                       false);  // read ith expression.
-    strings.SetAt(i, result_);
-    all_string = all_string && result_.IsString();
-  }
-  if (all_string) {
-    result_ = String::ConcatAll(strings, Heap::kOld);
-    result_ = H.Canonicalize(result_);
-  } else {
-    // Get string interpolation function.
-    const Class& cls =
-        Class::Handle(Z, Library::LookupCoreClass(Symbols::StringBase()));
-    ASSERT(!cls.IsNull());
-    const auto& func = Function::Handle(
-        Z, cls.LookupStaticFunction(
-               Library::PrivateCoreLibName(Symbols::Interpolate())));
-    ASSERT(!func.IsNull());
-
-    // Build argument array to pass to the interpolation function.
-    const auto& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld));
-    interpolate_arg.SetAt(0, strings);
-
-    // Run and canonicalize.
-    const Object& result =
-        RunFunction(position, func, interpolate_arg, Array::null_array());
-    result_ = H.Canonicalize(String::Cast(result));
-  }
-}
-
-void ConstantEvaluator::EvaluateSymbolLiteral() {
-  const Class& owner = *active_class_->klass;
-  const Library& lib = Library::Handle(Z, owner.library());
-  String& symbol_value = H.DartIdentifier(lib, helper_->ReadStringReference());
-  const Class& symbol_class =
-      Class::Handle(Z, I->object_store()->symbol_class());
-  ASSERT(!symbol_class.IsNull());
-  const auto& symbol_constructor = Function::Handle(
-      Z, symbol_class.LookupConstructor(Symbols::SymbolCtor()));
-  ASSERT(!symbol_constructor.IsNull());
-  result_ ^= EvaluateConstConstructorCall(
-      symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value);
-}
-
-void ConstantEvaluator::EvaluateTypeLiteral() {
-  const AbstractType& type = T.BuildType();
-  result_ = type.raw();
-}
-
-void ConstantEvaluator::EvaluateListLiteralInternal() {
-  helper_->ReadPosition();  // read position.
-  const TypeArguments& type_arguments = T.BuildTypeArguments(1);  // read type.
-  intptr_t length = helper_->ReadListLength();  // read list length.
-  const auto& const_list = Array::Handle(Z, Array::New(length, Heap::kOld));
-  const_list.SetTypeArguments(type_arguments);
-  Instance& expression = Instance::Handle(Z);
-  for (intptr_t i = 0; i < length; ++i) {
-    expression = EvaluateExpression(helper_->ReaderOffset(),
-                                    false);  // read ith expression.
-    const_list.SetAt(i, expression);
-  }
-  const_list.MakeImmutable();
-  result_ = H.Canonicalize(const_list);
-}
-
-void ConstantEvaluator::EvaluateMapLiteralInternal() {
-  helper_->ReadPosition();  // read position.
-  const TypeArguments& type_arguments =
-      T.BuildTypeArguments(2);  // read key type and value type.
-
-  intptr_t length = helper_->ReadListLength();  // read length of entries.
-
-  // This MapLiteral wasn't cached, so content isn't cached either.
-  Array& const_kv_array = Array::Handle(Z, Array::New(2 * length, Heap::kOld));
-  Instance& temp = Instance::Handle(Z);
-  for (intptr_t i = 0; i < length; ++i) {
-    temp = EvaluateExpression(helper_->ReaderOffset(), false);  // read key.
-    const_kv_array.SetAt(2 * i + 0, temp);
-    temp = EvaluateExpression(helper_->ReaderOffset(), false);  // read value.
-    const_kv_array.SetAt(2 * i + 1, temp);
-  }
-
-  const_kv_array.MakeImmutable();
-  const_kv_array ^= H.Canonicalize(const_kv_array);
-
-  const Class& map_class =
-      Class::Handle(Z, Library::LookupCoreClass(Symbols::ImmutableMap()));
-  ASSERT(!map_class.IsNull());
-  ASSERT(map_class.NumTypeArguments() == 2);
-
-  const Field& field =
-      Field::Handle(Z, map_class.LookupInstanceFieldAllowPrivate(
-                           H.DartSymbolObfuscate("_kvPairs")));
-  ASSERT(!field.IsNull());
-
-  // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`!
-  result_ = Instance::New(map_class, Heap::kOld);
-  ASSERT(!result_.IsNull());
-  result_.SetTypeArguments(type_arguments);
-  result_.SetField(field, const_kv_array);
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateLet() {
-  ASSERT(IsBuildingFlowGraph());
-  intptr_t kernel_position =
-      helper_->ReaderOffset() + helper_->data_program_offset_;
-
-  LocalVariable* local = flow_graph_builder_->LookupVariable(kernel_position);
-
-  // read variable declaration.
-  VariableDeclarationHelper helper(helper_);
-  helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
-  Tag tag = helper_->ReadTag();  // read (first part of) initializer.
-  if (tag == kNothing) {
-    local->SetConstValue(Instance::ZoneHandle(Z, Instance::null()));
-  } else {
-    local->SetConstValue(Instance::ZoneHandle(
-        Z, EvaluateExpression(helper_->ReaderOffset(),
-                              false)));  // read rest of initializer.
-  }
-
-  EvaluateExpression(helper_->ReaderOffset(), false);  // read body
-}
-
-void ConstantEvaluator::EvaluatePartialTearoffInstantiation() {
-  // This method call wasn't cached, so receiver et al. isn't cached either.
-  const auto& receiver = Instance::Handle(
-      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.
-  if (!receiver.IsClosure()) {
-    H.ReportError(script_, TokenPosition::kNoSource, "Expected closure.");
-  }
-  const Closure& old_closure = Closure::Cast(receiver);
-
-  // read type arguments.
-  intptr_t num_type_args = helper_->ReadListLength();
-  const TypeArguments* type_args = &T.BuildTypeArguments(num_type_args);
-  if (!type_args->IsNull() && !type_args->IsInstantiated()) {
-    H.ReportError(
-        script_, TokenPosition::kNoSource,
-        "Type arguments in partial instantiations must be instantiated and are "
-        "therefore not allowed to depend on type parameters.");
-  }
-
-  // Create new closure with the type arguments inserted, and other things
-  // copied over.
-  Closure& new_closure = Closure::Handle(
-      Z,
-      Closure::New(
-          TypeArguments::Handle(Z, old_closure.instantiator_type_arguments()),
-          TypeArguments::Handle(old_closure.function_type_arguments()),
-          *type_args, Function::Handle(Z, old_closure.function()),
-          Context::Handle(Z, old_closure.context()), Heap::kOld));
-  result_ = H.Canonicalize(new_closure);
-}
-
-void ConstantEvaluator::EvaluateBigIntLiteral() {
-  const String& value =
-      H.DartString(helper_->ReadStringReference());  // read string reference.
-  result_ = Integer::New(value, Heap::kOld);
-  if (result_.IsNull()) {
-    H.ReportError(script_, TokenPosition::kNoSource,
-                  "Integer literal %s is out of range", value.ToCString());
-  }
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateStringLiteral() {
-  result_ = H.DartSymbolPlain(helper_->ReadStringReference())
-                .raw();  // read string reference.
-}
-
-void ConstantEvaluator::EvaluateIntLiteral(uint8_t payload) {
-  int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
-  result_ = Integer::New(value, Heap::kOld);
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateIntLiteral(bool is_negative) {
-  int64_t value = is_negative ? -static_cast<int64_t>(helper_->ReadUInt())
-                              : helper_->ReadUInt();  // read value.
-  result_ = Integer::New(value, Heap::kOld);
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateDoubleLiteral() {
-  result_ = Double::New(helper_->ReadDouble(), Heap::kOld);  // read value.
-  result_ = H.Canonicalize(result_);
-}
-
-void ConstantEvaluator::EvaluateBoolLiteral(bool value) {
-  result_ = Bool::Get(value).raw();
-}
-
-void ConstantEvaluator::EvaluateNullLiteral() {
-  result_ = Instance::null();
-}
-
-// This depends on being about to read the list of positionals on arguments.
-const Object& ConstantEvaluator::RunFunction(TokenPosition position,
-                                             const Function& function,
-                                             intptr_t argument_count,
-                                             const Instance* receiver,
-                                             const TypeArguments* type_args) {
-  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
-  // we should never end up evaluating constants using the VM's constant
-  // evaluator.
-  if (FLAG_precompiled_mode) {
-    UNREACHABLE();
-  }
-
-  // We do not support generic methods yet.
-  ASSERT((receiver == NULL) || (type_args == NULL));
-  intptr_t extra_arguments =
-      (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);
-
-  // Build up arguments.
-  const auto& arguments = Array::Handle(
-      Z, Array::New(extra_arguments + argument_count, H.allocation_space()));
-  intptr_t pos = 0;
-  if (receiver != NULL) {
-    arguments.SetAt(pos++, *receiver);
-  }
-  if (type_args != NULL) {
-    arguments.SetAt(pos++, *type_args);
-  }
-
-  // List of positional.
-  intptr_t list_length = helper_->ReadListLength();  // read list length.
-  for (intptr_t i = 0; i < list_length; ++i) {
-    EvaluateExpression(helper_->ReaderOffset(),
-                       false);  // read ith expression.
-    arguments.SetAt(pos++, result_);
-  }
-
-  // List of named.
-  list_length = helper_->ReadListLength();  // read list length.
-  const Array& names =
-      Array::Handle(Z, Array::New(list_length, H.allocation_space()));
-  for (intptr_t i = 0; i < list_length; ++i) {
-    String& name = H.DartSymbolObfuscate(
-        helper_->ReadStringReference());  // read ith name index.
-    names.SetAt(i, name);
-    EvaluateExpression(helper_->ReaderOffset(),
-                       false);  // read ith expression.
-    arguments.SetAt(pos++, result_);
-  }
-
-  return RunFunction(position, function, arguments, names);
-}
-
-const Object& ConstantEvaluator::RunFunction(const TokenPosition position,
-                                             const Function& function,
-                                             const Array& arguments,
-                                             const Array& names) {
-  // We do not support generic methods yet.
-  const int kTypeArgsLen = 0;
-  const auto& args_descriptor = Array::Handle(
-      Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
-  const auto& result = Object::Handle(
-      Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
-  if (result.IsError()) {
-    H.ReportError(Error::Cast(result), script_, position,
-                  "error evaluating constant constructor");
-  }
-  return result;
-}
-
-const Object& ConstantEvaluator::RunMethodCall(const TokenPosition position,
-                                               const Function& function,
-                                               const Instance* receiver) {
-  intptr_t argument_count = helper_->ReadUInt();  // read arguments count.
-
-  // TODO(28109) Support generic methods in the VM or reify them away.
-  ASSERT(helper_->PeekListLength() == 0);
-  helper_->SkipListOfDartTypes();  // read list of types.
-
-  // Run the method.
-  return RunFunction(position, function, argument_count, receiver, NULL);
-}
-
-RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
-    const Class& type_class,
-    const TypeArguments& type_arguments,
-    const Function& constructor,
-    const Object& argument) {
-  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
-  // we should never end up evaluating constants using the VM's constant
-  // evaluator.
-  if (FLAG_precompiled_mode) {
-    UNREACHABLE();
-  }
-
-  // Factories have one extra argument: the type arguments.
-  // Constructors have 1 extra arguments: receiver.
-  const int kTypeArgsLen = 0;
-  const int kNumArgs = 1;
-  const int kNumExtraArgs = 1;
-  const int argument_count = kNumArgs + kNumExtraArgs;
-  const Array& arg_values =
-      Array::Handle(Z, Array::New(argument_count, Heap::kOld));
-  Instance& instance = Instance::Handle(Z);
-  if (!constructor.IsFactory()) {
-    instance = Instance::New(type_class, Heap::kOld);
-    if (!type_arguments.IsNull()) {
-      ASSERT(type_arguments.IsInstantiated());
-      instance.SetTypeArguments(
-          TypeArguments::Handle(Z, type_arguments.Canonicalize()));
-    }
-    arg_values.SetAt(0, instance);
-  } else {
-    // Prepend type_arguments to list of arguments to factory.
-    ASSERT(type_arguments.IsZoneHandle());
-    arg_values.SetAt(0, type_arguments);
-  }
-  arg_values.SetAt((0 + kNumExtraArgs), argument);
-  const Array& args_descriptor =
-      Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, argument_count,
-                                                Object::empty_array()));
-  const auto& result = Object::Handle(
-      Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
-  ASSERT(!result.IsError());
-  if (constructor.IsFactory()) {
-    // The factory method returns the allocated object.
-    instance ^= result.raw();
-  }
-  if (I->obfuscate() &&
-      (instance.clazz() == I->object_store()->symbol_class())) {
-    Obfuscator::ObfuscateSymbolInstance(H.thread(), instance);
-  }
-  return H.Canonicalize(instance);
-}
-
-const TypeArguments* ConstantEvaluator::TranslateTypeArguments(
-    const Function& target,
-    Class* target_klass) {
-  intptr_t type_count = helper_->ReadListLength();  // read type count.
-
-  const TypeArguments* type_arguments = NULL;
-  if (type_count > 0) {
-    type_arguments = &T.BuildInstantiatedTypeArguments(
-        *target_klass, type_count);  // read types.
-
-    if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
-      H.ReportError(script_, TokenPosition::kNoSource,
-                    "Type must be constant in const constructor.");
-    }
-  } else if (target.IsFactory() && type_arguments == NULL) {
-    // All factories take a type arguments vector as first argument (independent
-    // of whether the class is generic or not).
-    type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
-  }
-  return type_arguments;
-}
-
-bool ConstantEvaluator::EvaluateBooleanExpressionHere() {
-  EvaluateExpression(helper_->ReaderOffset(), false);
-  AssertBool();
-  return result_.raw() == Bool::True().raw();
-}
-
-bool ConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
-                                          Instance* value) {
-  if (!IsBuildingFlowGraph()) return false;
-
-  const Function& function = flow_graph_builder_->parsed_function_->function();
-  if ((function.kind() == RawFunction::kImplicitStaticGetter ||
-       function.kind() == RawFunction::kFieldInitializer) &&
-      !I->CanOptimizeImmediately()) {
-    // Don't cache constants in initializer expressions. They get
-    // evaluated only once.
-    return false;
-  }
-
-  bool is_present = false;
-  ASSERT(!script_.InVMIsolateHeap());
-  if (script_.compile_time_constants() == Array::null()) {
-    return false;
-  }
-  {
-    // Any access to constants arrays must be locked since mutator and
-    // background compiler can access the array at the same time.
-    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
-
-    KernelConstantsMap constants(script_.compile_time_constants());
-    *value ^= constants.GetOrNull(kernel_offset + helper_->data_program_offset_,
-                                  &is_present);
-    constants.Release();
-  }
-  return is_present;
-}
-
-void ConstantEvaluator::CacheConstantValue(intptr_t kernel_offset,
-                                           const Instance& value) {
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  if (!IsBuildingFlowGraph()) return;
-
-  const Function& function = flow_graph_builder_->parsed_function_->function();
-  if ((function.kind() == RawFunction::kImplicitStaticGetter ||
-       function.kind() == RawFunction::kFieldInitializer) &&
-      !I->CanOptimizeImmediately()) {
-    // Don't cache constants in initializer expressions. They get
-    // evaluated only once.
-    return;
-  }
-  const intptr_t kInitialConstMapSize = 16;
-  ASSERT(!script_.InVMIsolateHeap());
-  if (script_.compile_time_constants() == Array::null()) {
-    const auto& array = Array::Handle(
-        HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
-    script_.set_compile_time_constants(array);
-  }
-  {
-    // Any access to constants arrays must be locked since mutator and
-    // background compiler can access the array at the same time.
-    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
-
-    KernelConstantsMap constants(script_.compile_time_constants());
-    constants.InsertNewOrGetValue(kernel_offset + helper_->data_program_offset_,
-                                  value);
-    script_.set_compile_time_constants(constants.Release());
-  }
-}
-
-}  // namespace kernel
-}  // namespace dart
-
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.h b/runtime/vm/compiler/frontend/constant_evaluator.h
deleted file mode 100644
index 3e96dd9..0000000
--- a/runtime/vm/compiler/frontend/constant_evaluator.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_EVALUATOR_H_
-#define RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_EVALUATOR_H_
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-
-#include "vm/compiler/frontend/kernel_translation_helper.h"
-#include "vm/hash_table.h"
-#include "vm/object.h"
-
-namespace dart {
-namespace kernel {
-
-class FlowGraphBuilder;
-
-// There are several cases when we are compiling constant expressions:
-//
-//   * constant field initializers:
-//      const FieldName = <expr>;
-//
-//   * constant expressions:
-//      const [<expr>, ...]
-//      const {<expr> : <expr>, ...}
-//      const Constructor(<expr>, ...)
-//
-//   * constant default parameters:
-//      f(a, [b = <expr>])
-//      f(a, {b: <expr>})
-//
-//   * constant values to compare in a [SwitchCase]
-//      case <expr>:
-//
-// In all cases `<expr>` must be recursively evaluated and canonicalized at
-// compile-time.
-class ConstantEvaluator {
- public:
-  ConstantEvaluator(KernelReaderHelper* helper,
-                    TypeTranslator* type_translator,
-                    ActiveClass* active_class,
-                    FlowGraphBuilder* flow_graph_builder = nullptr);
-
-  virtual ~ConstantEvaluator() {}
-
-  bool IsCached(intptr_t offset);
-
-  RawInstance* EvaluateExpression(intptr_t offset, bool reset_position = true);
-  Instance& EvaluateListLiteral(intptr_t offset, bool reset_position = true);
-  Instance& EvaluateMapLiteral(intptr_t offset, bool reset_position = true);
-  Instance& EvaluateConstructorInvocation(intptr_t offset,
-                                          bool reset_position = true);
-  Instance& EvaluateStaticInvocation(intptr_t offset,
-                                     bool reset_position = true);
-  RawObject* EvaluateExpressionSafe(intptr_t offset);
-  RawObject* EvaluateAnnotations();
-
-  // Peeks to see if constant at the given offset will evaluate to
-  // instance of the given clazz.
-  bool IsInstanceConstant(intptr_t constant_offset, const Class& clazz);
-
-  // Evaluates a constant at the given offset (possibly by recursing
-  // into sub-constants).
-  RawInstance* EvaluateConstantExpression(intptr_t constant_offset);
-
- private:
-  RawInstance* EvaluateConstant(intptr_t constant_offset);
-
-  void BailoutIfBackgroundCompilation();
-
-  bool IsBuildingFlowGraph() const;
-  bool IsAllowedToEvaluate() const;
-  void EvaluateAsExpression();
-  void EvaluateVariableGet(bool is_specialized);
-  void EvaluatePropertyGet();
-  void EvaluateDirectPropertyGet();
-  void EvaluateStaticGet();
-  void EvaluateMethodInvocation();
-  void EvaluateDirectMethodInvocation();
-  void EvaluateSuperMethodInvocation();
-  void EvaluateStaticInvocation();
-  void EvaluateConstructorInvocationInternal();
-  void EvaluateNot();
-  void EvaluateLogicalExpression();
-  void EvaluateConditionalExpression();
-  void EvaluateStringConcatenation();
-  void EvaluateSymbolLiteral();
-  void EvaluateTypeLiteral();
-  void EvaluateListLiteralInternal();
-  void EvaluateMapLiteralInternal();
-  void EvaluateLet();
-  void EvaluatePartialTearoffInstantiation();
-  void EvaluateBigIntLiteral();
-  void EvaluateStringLiteral();
-  void EvaluateIntLiteral(uint8_t payload);
-  void EvaluateIntLiteral(bool is_negative);
-  void EvaluateDoubleLiteral();
-  void EvaluateBoolLiteral(bool value);
-  void EvaluateNullLiteral();
-
-  void EvaluateGetStringLength(intptr_t expression_offset,
-                               TokenPosition position);
-
-  const Object& RunFunction(const TokenPosition position,
-                            const Function& function,
-                            intptr_t argument_count,
-                            const Instance* receiver,
-                            const TypeArguments* type_args);
-
-  const Object& RunFunction(const TokenPosition position,
-                            const Function& function,
-                            const Array& arguments,
-                            const Array& names);
-
-  const Object& RunMethodCall(const TokenPosition position,
-                              const Function& function,
-                              const Instance* receiver);
-
-  RawObject* EvaluateConstConstructorCall(const Class& type_class,
-                                          const TypeArguments& type_arguments,
-                                          const Function& constructor,
-                                          const Object& argument);
-
-  const TypeArguments* TranslateTypeArguments(const Function& target,
-                                              Class* target_klass);
-
-  void AssertBool() {
-    if (!result_.IsBool()) {
-      translation_helper_.ReportError("Expected boolean expression.");
-    }
-  }
-
-  bool EvaluateBooleanExpressionHere();
-
-  bool GetCachedConstant(intptr_t kernel_offset, Instance* value);
-  void CacheConstantValue(intptr_t kernel_offset, const Instance& value);
-
-  KernelReaderHelper* helper_;
-  Isolate* isolate_;
-  Zone* zone_;
-  TranslationHelper& translation_helper_;
-  TypeTranslator& type_translator_;
-  ActiveClass* active_class_;
-  FlowGraphBuilder* flow_graph_builder_;
-  const Script& script_;
-  Instance& result_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConstantEvaluator);
-};
-
-class KernelConstMapKeyEqualsTraits : public AllStatic {
- public:
-  static const char* Name() { return "KernelConstMapKeyEqualsTraits"; }
-  static bool ReportStats() { return false; }
-
-  static bool IsMatch(const Object& a, const Object& b) {
-    const Smi& key1 = Smi::Cast(a);
-    const Smi& key2 = Smi::Cast(b);
-    return (key1.Value() == key2.Value());
-  }
-  static bool IsMatch(const intptr_t key1, const Object& b) {
-    return KeyAsSmi(key1) == Smi::Cast(b).raw();
-  }
-  static uword Hash(const Object& obj) {
-    const Smi& key = Smi::Cast(obj);
-    return HashValue(key.Value());
-  }
-  static uword Hash(const intptr_t key) {
-    return HashValue(Smi::Value(KeyAsSmi(key)));
-  }
-  static RawObject* NewKey(const intptr_t key) { return KeyAsSmi(key); }
-
- private:
-  static uword HashValue(intptr_t pos) { return pos % (Smi::kMaxValue - 13); }
-
-  static RawSmi* KeyAsSmi(const intptr_t key) {
-    ASSERT(key >= 0);
-    return Smi::New(key);
-  }
-};
-typedef UnorderedHashMap<KernelConstMapKeyEqualsTraits> KernelConstantsMap;
-
-}  // namespace kernel
-}  // namespace dart
-
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-#endif  // RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_EVALUATOR_H_
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
new file mode 100644
index 0000000..9646b59
--- /dev/null
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -0,0 +1,322 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/frontend/constant_reader.h"
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+namespace dart {
+namespace kernel {
+
+#define Z (zone_)
+#define H (translation_helper_)
+
+ConstantReader::ConstantReader(KernelReaderHelper* helper,
+                               ActiveClass* active_class)
+    : helper_(helper),
+      zone_(helper->zone_),
+      translation_helper_(helper->translation_helper_),
+      active_class_(active_class),
+      script_(helper->script()),
+      result_(Instance::Handle(zone_)) {}
+
+RawInstance* ConstantReader::ReadConstantExpression() {
+  Tag tag = helper_->ReadTag();  // read tag.
+  switch (tag) {
+    case kConstantExpression:
+      helper_->ReadPosition();
+      helper_->SkipDartType();
+      result_ = ReadConstant(helper_->ReadUInt());
+      break;
+    case kInvalidExpression: {
+      helper_->ReadPosition();  // Skip position.
+      const String& message = H.DartString(helper_->ReadStringReference());
+      // Invalid expression message has pointer to the source code, no need to
+      // report it twice.
+      H.ReportError(helper_->script(), TokenPosition::kNoSource, "%s",
+                    message.ToCString());
+      break;
+    }
+    default:
+      H.ReportError(script_, TokenPosition::kNoSource,
+                    "Not a constant expression: unexpected kernel tag %s (%d)",
+                    Reader::TagName(tag), tag);
+  }
+  return result_.raw();
+}
+
+RawObject* ConstantReader::ReadAnnotations() {
+  intptr_t list_length = helper_->ReadListLength();  // read list length.
+  const Array& metadata_values =
+      Array::Handle(Z, Array::New(list_length, H.allocation_space()));
+  Instance& value = Instance::Handle(Z);
+  for (intptr_t i = 0; i < list_length; ++i) {
+    // This will read the expression.
+    value = ReadConstantExpression();
+    metadata_values.SetAt(i, value);
+  }
+  return metadata_values.raw();
+}
+
+RawInstance* ConstantReader::ReadConstant(intptr_t constant_offset) {
+  ASSERT(!H.constants().IsNull());
+  ASSERT(!H.constants_table().IsNull());  // raw bytes
+
+  // For kernel-level cache (in contrast with script-level caching),
+  // we need to access the raw constants array inside the shared
+  // KernelProgramInfo directly, so that all scripts will see the
+  // results after new insertions. These accesses at kernel-level
+  // must be locked since mutator and background compiler can
+  // access the array at the same time.
+  {
+    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
+    KernelConstantsMap constant_map(H.info().constants());
+    result_ ^= constant_map.GetOrNull(constant_offset);
+    ASSERT(constant_map.Release().raw() == H.info().constants());
+  }
+
+  // On miss, evaluate, and insert value.
+  if (result_.IsNull()) {
+    result_ = ReadConstantInternal(constant_offset);
+    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
+    KernelConstantsMap constant_map(H.info().constants());
+    auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
+    ASSERT(insert == result_.raw());
+    H.info().set_constants(constant_map.Release());  // update!
+  }
+  return result_.raw();
+}
+
+bool ConstantReader::IsInstanceConstant(intptr_t constant_offset,
+                                        const Class& clazz) {
+  // Get reader directly into raw bytes of constant table.
+  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
+  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
+  reader.SetOffset(reader.ReaderOffset() + constant_offset);
+  // Peek for an instance of the given clazz.
+  if (reader.ReadByte() == kInstanceConstant) {
+    const NameIndex index = reader.ReadCanonicalNameReference();
+    return H.LookupClassByKernelClass(index) == clazz.raw();
+  }
+  return false;
+}
+
+RawInstance* ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
+  // Get reader directly into raw bytes of constant table.
+  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
+  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
+  reader.SetOffset(reader.ReaderOffset() + constant_offset);
+  // Construct constant from raw bytes.
+  Instance& instance = Instance::Handle(Z);
+  const intptr_t constant_tag = reader.ReadByte();
+  switch (constant_tag) {
+    case kNullConstant:
+      instance = Instance::null();
+      break;
+    case kBoolConstant:
+      instance = reader.ReadByte() == 1 ? Object::bool_true().raw()
+                                        : Object::bool_false().raw();
+      break;
+    case kIntConstant: {
+      uint8_t payload = 0;
+      Tag integer_tag = reader.ReadTag(&payload);  // read tag.
+      switch (integer_tag) {
+        case kBigIntLiteral: {
+          const String& value = H.DartString(reader.ReadStringReference());
+          instance = Integer::New(value, Heap::kOld);
+          break;
+        }
+        case kSpecializedIntLiteral: {
+          const int64_t value =
+              static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
+          instance = Integer::New(value, Heap::kOld);
+          break;
+        }
+        case kNegativeIntLiteral: {
+          const int64_t value = -static_cast<int64_t>(reader.ReadUInt());
+          instance = Integer::New(value, Heap::kOld);
+          break;
+        }
+        case kPositiveIntLiteral: {
+          const int64_t value = reader.ReadUInt();
+          instance = Integer::New(value, Heap::kOld);
+          break;
+        }
+        default:
+          H.ReportError(
+              script_, TokenPosition::kNoSource,
+              "Cannot lazily read integer: unexpected kernel tag %s (%d)",
+              Reader::TagName(integer_tag), integer_tag);
+      }
+      break;
+    }
+    case kDoubleConstant:
+      instance = Double::New(reader.ReadDouble(), Heap::kOld);
+      break;
+    case kStringConstant:
+      instance = H.DartSymbolPlain(reader.ReadStringReference()).raw();
+      break;
+    case kSymbolConstant: {
+      Library& library = Library::Handle(Z);
+      library = Library::InternalLibrary();
+      const auto& symbol_class =
+          Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
+      const auto& symbol_name_field = Field::Handle(
+          Z, symbol_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+      ASSERT(!symbol_name_field.IsNull());
+      const NameIndex index = reader.ReadCanonicalNameReference();
+      if (index == -1) {
+        library = Library::null();
+      } else {
+        library = H.LookupLibraryByKernelLibrary(index);
+      }
+      const String& symbol =
+          H.DartIdentifier(library, reader.ReadStringReference());
+      instance = Instance::New(symbol_class, Heap::kOld);
+      instance.SetField(symbol_name_field, symbol);
+      break;
+    }
+    case kListConstant: {
+      const auto& corelib = Library::Handle(Z, Library::CoreLibrary());
+      const auto& list_class =
+          Class::Handle(Z, corelib.LookupClassAllowPrivate(Symbols::_List()));
+      // Build type from the raw bytes (needs temporary translator).
+      TypeTranslator type_translator(&reader, active_class_, true);
+      auto& type_arguments =
+          TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
+      AbstractType& type = type_translator.BuildType();
+      type_arguments.SetTypeAt(0, type);
+      // Instantiate class.
+      type = Type::New(list_class, type_arguments, TokenPosition::kNoSource);
+      type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
+                                          ClassFinalizer::kCanonicalize);
+      type_arguments = type.arguments();
+      // Fill array with constant elements.
+      const intptr_t length = reader.ReadUInt();
+      const Array& array =
+          Array::Handle(Z, ImmutableArray::New(length, Heap::kOld));
+      array.SetTypeArguments(type_arguments);
+      Instance& constant = Instance::Handle(Z);
+      for (intptr_t j = 0; j < length; ++j) {
+        // Recurse into lazily evaluating all "sub" constants
+        // needed to evaluate the current constant.
+        const intptr_t entry_offset = reader.ReadUInt();
+        ASSERT(entry_offset < constant_offset);  // DAG!
+        constant = ReadConstant(entry_offset);
+        array.SetAt(j, constant);
+      }
+      instance = array.raw();
+      break;
+    }
+    case kInstanceConstant: {
+      const NameIndex index = reader.ReadCanonicalNameReference();
+      const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
+      if (!klass.is_declaration_loaded() && !klass.is_declared_in_bytecode()) {
+        FATAL1(
+            "Trying to evaluate an instance constant whose references class "
+            "%s is not loaded yet.",
+            klass.ToCString());
+      }
+      const auto& obj = Object::Handle(Z, klass.EnsureIsFinalized(H.thread()));
+      ASSERT(obj.IsNull());
+      instance = Instance::New(klass, Heap::kOld);
+      // Build type from the raw bytes (needs temporary translator).
+      TypeTranslator type_translator(&reader, active_class_, true);
+      const intptr_t number_of_type_arguments = reader.ReadUInt();
+      if (klass.NumTypeArguments() > 0) {
+        auto& type_arguments = TypeArguments::Handle(
+            Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
+        for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
+          type_arguments.SetTypeAt(j, type_translator.BuildType());
+        }
+        // Instantiate class.
+        auto& type = AbstractType::Handle(
+            Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
+        type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
+                                            ClassFinalizer::kCanonicalize);
+        type_arguments = type.arguments();
+        instance.SetTypeArguments(type_arguments);
+      } else {
+        ASSERT(number_of_type_arguments == 0);
+      }
+      // Set the fields.
+      const intptr_t number_of_fields = reader.ReadUInt();
+      Field& field = Field::Handle(Z);
+      Instance& constant = Instance::Handle(Z);
+      for (intptr_t j = 0; j < number_of_fields; ++j) {
+        field = H.LookupFieldByKernelField(reader.ReadCanonicalNameReference());
+        // Recurse into lazily evaluating all "sub" constants
+        // needed to evaluate the current constant.
+        const intptr_t entry_offset = reader.ReadUInt();
+        ASSERT(entry_offset < constant_offset);  // DAG!
+        constant = ReadConstant(entry_offset);
+        instance.SetField(field, constant);
+      }
+      break;
+    }
+    case kPartialInstantiationConstant: {
+      // Recurse into lazily evaluating the "sub" constant
+      // needed to evaluate the current constant.
+      const intptr_t entry_offset = reader.ReadUInt();
+      ASSERT(entry_offset < constant_offset);  // DAG!
+      const auto& constant = Instance::Handle(Z, ReadConstant(entry_offset));
+      ASSERT(!constant.IsNull());
+
+      // Build type from the raw bytes (needs temporary translator).
+      TypeTranslator type_translator(&reader, active_class_, true);
+      const intptr_t number_of_type_arguments = reader.ReadUInt();
+      ASSERT(number_of_type_arguments > 0);
+      auto& type_arguments = TypeArguments::Handle(
+          Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
+      for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
+        type_arguments.SetTypeAt(j, type_translator.BuildType());
+      }
+      type_arguments = type_arguments.Canonicalize();
+      // Make a copy of the old closure, and set delayed type arguments.
+      Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.raw()));
+      Function& function = Function::Handle(Z, closure.function());
+      const auto& type_arguments2 =
+          TypeArguments::Handle(Z, closure.instantiator_type_arguments());
+      // The function type arguments are used for type parameters from enclosing
+      // closures. Though inner closures cannot be constants. We should
+      // therefore see `null here.
+      ASSERT(closure.function_type_arguments() == TypeArguments::null());
+      Context& context = Context::Handle(Z, closure.context());
+      instance = Closure::New(type_arguments2, Object::null_type_arguments(),
+                              type_arguments, function, context, Heap::kOld);
+      break;
+    }
+    case kTearOffConstant: {
+      const NameIndex index = reader.ReadCanonicalNameReference();
+      Function& function =
+          Function::Handle(Z, H.LookupStaticMethodByKernelProcedure(index));
+      function = function.ImplicitClosureFunction();
+      instance = function.ImplicitStaticClosure();
+      break;
+    }
+    case kTypeLiteralConstant: {
+      // Build type from the raw bytes (needs temporary translator).
+      TypeTranslator type_translator(&reader, active_class_, true);
+      instance = type_translator.BuildType().raw();
+      break;
+    }
+    default:
+      // Set literals (kSetConstant) are currently desugared in the frontend
+      // and will not reach the VM. See http://dartbug.com/35124 for some
+      // discussion. Map constants (kMapConstant ) are already lowered to
+      // InstanceConstant or ListConstant. We should never see unevaluated
+      // constants (kUnevaluatedConstant) in the constant table, they should
+      // have been fully evaluated before we get them.
+      H.ReportError(script_, TokenPosition::kNoSource,
+                    "Cannot lazily read constant: unexpected kernel tag (%" Pd
+                    ")",
+                    constant_tag);
+  }
+  return H.Canonicalize(instance);
+}
+
+}  // namespace kernel
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/frontend/constant_reader.h b/runtime/vm/compiler/frontend/constant_reader.h
new file mode 100644
index 0000000..c5a7574
--- /dev/null
+++ b/runtime/vm/compiler/frontend/constant_reader.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_READER_H_
+#define RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_READER_H_
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/frontend/kernel_translation_helper.h"
+#include "vm/hash_table.h"
+#include "vm/object.h"
+
+namespace dart {
+namespace kernel {
+
+// Reads and caches constants from the kernel constant pool.
+class ConstantReader {
+ public:
+  ConstantReader(KernelReaderHelper* helper, ActiveClass* active_class);
+
+  virtual ~ConstantReader() {}
+
+  RawInstance* ReadConstantExpression();
+  RawObject* ReadAnnotations();
+
+  // Peeks to see if constant at the given offset will evaluate to
+  // instance of the given clazz.
+  bool IsInstanceConstant(intptr_t constant_offset, const Class& clazz);
+
+  // Reads a constant at the given offset (possibly by recursing
+  // into sub-constants).
+  RawInstance* ReadConstant(intptr_t constant_offset);
+
+ private:
+  RawInstance* ReadConstantInternal(intptr_t constant_offset);
+
+  KernelReaderHelper* helper_;
+  Zone* zone_;
+  TranslationHelper& translation_helper_;
+  ActiveClass* active_class_;
+  const Script& script_;
+  Instance& result_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConstantReader);
+};
+
+class KernelConstMapKeyEqualsTraits : public AllStatic {
+ public:
+  static const char* Name() { return "KernelConstMapKeyEqualsTraits"; }
+  static bool ReportStats() { return false; }
+
+  static bool IsMatch(const Object& a, const Object& b) {
+    const Smi& key1 = Smi::Cast(a);
+    const Smi& key2 = Smi::Cast(b);
+    return (key1.Value() == key2.Value());
+  }
+  static bool IsMatch(const intptr_t key1, const Object& b) {
+    return KeyAsSmi(key1) == Smi::Cast(b).raw();
+  }
+  static uword Hash(const Object& obj) {
+    const Smi& key = Smi::Cast(obj);
+    return HashValue(key.Value());
+  }
+  static uword Hash(const intptr_t key) {
+    return HashValue(Smi::Value(KeyAsSmi(key)));
+  }
+  static RawObject* NewKey(const intptr_t key) { return KeyAsSmi(key); }
+
+ private:
+  static uword HashValue(intptr_t pos) { return pos % (Smi::kMaxValue - 13); }
+
+  static RawSmi* KeyAsSmi(const intptr_t key) {
+    ASSERT(key >= 0);
+    return Smi::New(key);
+  }
+};
+typedef UnorderedHashMap<KernelConstMapKeyEqualsTraits> KernelConstantsMap;
+
+}  // namespace kernel
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_READER_H_
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index b093215..ca71934 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -52,10 +52,9 @@
   Fragment body(normal_entry);
   body += B->CheckStackOverflowInPrologue(field_helper.position_);
   if (field_helper.IsConst()) {
-    // this will (potentially) read the initializer, but reset the position.
-    body += Constant(Instance::ZoneHandle(
-        Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
-    SkipExpression();  // read the initializer.
+    // This will read the initializer.
+    body += Constant(
+        Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
   } else {
     body += BuildExpression();  // read initializer.
   }
@@ -78,8 +77,8 @@
 
   ASSERT(initializer_tag == kSomething);
 
-  Instance& value = Instance::Handle(
-      Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
+  Instance& value =
+      Instance::Handle(Z, constant_reader_.ReadConstantExpression());
   field.SetStaticValue(value);
 }
 
@@ -114,11 +113,9 @@
         helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
         Tag tag = ReadTag();  // read (first part of) initializer.
         if (tag == kSomething) {
-          // this will (potentially) read the initializer,
-          // but reset the position.
+          // This will read the initializer.
           default_value = &Instance::ZoneHandle(
-              Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
-          SkipExpression();  // read (actual) initializer.
+              Z, constant_reader_.ReadConstantExpression());
         } else {
           default_value = &Instance::ZoneHandle(Z, Instance::null());
         }
@@ -142,11 +139,9 @@
         helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
         Tag tag = ReadTag();  // read (first part of) initializer.
         if (tag == kSomething) {
-          // this will (potentially) read the initializer,
-          // but reset the position.
+          // This will read the initializer.
           default_value = &Instance::ZoneHandle(
-              Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
-          SkipExpression();  // read (actual) initializer.
+              Z, constant_reader_.ReadConstantExpression());
         } else {
           default_value = &Instance::ZoneHandle(Z, Instance::null());
         }
@@ -1207,13 +1202,9 @@
     case kDirectMethodInvocation:
       return BuildDirectMethodInvocation(position);
     case kStaticInvocation:
-      return BuildStaticInvocation(false, position);
-    case kConstStaticInvocation:
-      return BuildStaticInvocation(true, position);
+      return BuildStaticInvocation(position);
     case kConstructorInvocation:
-      return BuildConstructorInvocation(false, position);
-    case kConstConstructorInvocation:
-      return BuildConstructorInvocation(true, position);
+      return BuildConstructorInvocation(position);
     case kNot:
       return BuildNot(position);
     case kNullCheck:
@@ -1224,21 +1215,10 @@
       return BuildConditionalExpression(position);
     case kStringConcatenation:
       return BuildStringConcatenation(position);
-    case kListConcatenation:
-    case kSetConcatenation:
-    case kMapConcatenation:
-    case kInstanceCreation:
-    case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are removed by the constant evaluator.
-      UNREACHABLE();
-      break;
     case kIsExpression:
       return BuildIsExpression(position);
     case kAsExpression:
       return BuildAsExpression(position);
-    case kSymbolLiteral:
-      return BuildSymbolLiteral(position);
     case kTypeLiteral:
       return BuildTypeLiteral(position);
     case kThisExpression:
@@ -1248,19 +1228,14 @@
     case kThrow:
       return BuildThrow(position);
     case kListLiteral:
-      return BuildListLiteral(false, position);
-    case kConstListLiteral:
-      return BuildListLiteral(true, position);
+      return BuildListLiteral(position);
     case kSetLiteral:
-    case kConstSetLiteral:
       // Set literals are currently desugared in the frontend and will not
       // reach the VM. See http://dartbug.com/35124 for discussion.
       UNREACHABLE();
       break;
     case kMapLiteral:
-      return BuildMapLiteral(false, position);
-    case kConstMapLiteral:
-      return BuildMapLiteral(true, position);
+      return BuildMapLiteral(position);
     case kFunctionExpression:
       return BuildFunctionExpression();
     case kLet:
@@ -1287,14 +1262,28 @@
       return BuildNullLiteral(position);
     case kConstantExpression:
       return BuildConstantExpression(position, tag);
-    case kDeprecated_ConstantExpression:
-      return BuildConstantExpression(position, tag);
     case kInstantiation:
       return BuildPartialTearoffInstantiation(position);
     case kLoadLibrary:
     case kCheckLibraryIsLoaded:
       ReadUInt();  // skip library index
       return BuildFutureNullValue(position);
+    case kConstStaticInvocation:
+    case kConstConstructorInvocation:
+    case kConstListLiteral:
+    case kConstSetLiteral:
+    case kConstMapLiteral:
+    case kSymbolLiteral:
+      // Const invocations and const literals are removed by the
+      // constant evaluator.
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+    case kInstanceCreation:
+    case kFileUriExpression:
+      // Collection concatenation, instance creation operations and
+      // in-expression URI changes are internal to the front end and
+      // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
       UNREACHABLE();
@@ -1376,10 +1365,7 @@
 }
 
 Nullability KernelReaderHelper::ReadNullability() {
-  if (translation_helper_.info().kernel_binary_version() >= 28) {
-    return reader_.ReadNullability();
-  }
-  return kLegacy;
+  return reader_.ReadNullability();
 }
 
 Variance KernelReaderHelper::ReadVariance() {
@@ -2609,14 +2595,21 @@
     const Field& field =
         Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
     if (field.is_const()) {
-      return Constant(Instance::ZoneHandle(
-          Z, constant_evaluator_.EvaluateExpression(offset)));
+      // Since the CFE inlines all references to const variables and fields,
+      // it never emits a StaticGet of a const field.
+      // This situation only arises because of the static const fields in
+      // the ClassID class, which are generated internally in the VM
+      // during loading. See also Class::InjectCIDFields.
+      ASSERT(Class::Handle(field.Owner()).library() ==
+                 Library::InternalLibrary() &&
+             Class::Handle(field.Owner()).Name() == Symbols::ClassID().raw());
+      return Constant(Instance::ZoneHandle(Z, field.StaticValue()));
     } else {
       const Class& owner = Class::Handle(Z, field.Owner());
       const String& getter_name = H.DartGetterName(target);
       const Function& getter =
           Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name));
-      if (getter.IsNull() || !field.has_initializer()) {
+      if (getter.IsNull() || !field.has_nontrivial_initializer()) {
         Fragment instructions = Constant(field);
         return instructions + LoadStaticField();
       } else {
@@ -2632,8 +2625,11 @@
       return StaticCall(position, function, 0, Array::null_array(),
                         ICData::kStatic, &result_type);
     } else if (H.IsMethod(target)) {
-      return Constant(Instance::ZoneHandle(
-          Z, constant_evaluator_.EvaluateExpression(offset)));
+      const auto& closure_function =
+          Function::Handle(Z, function.ImplicitClosureFunction());
+      const auto& static_closure =
+          Instance::Handle(Z, closure_function.ImplicitStaticClosure());
+      return Constant(Instance::ZoneHandle(Z, H.Canonicalize(static_closure)));
     } else {
       UNIMPLEMENTED();
     }
@@ -3096,17 +3092,7 @@
   }
 }
 
-Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
-                                                          TokenPosition* p) {
-  if (is_const) {
-    const intptr_t offset = ReaderOffset() - 1;           // Include the tag.
-    (p != NULL) ? * p = ReadPosition() : ReadPosition();  // read position.
-
-    SetOffset(offset);
-    SkipExpression();  // read past this StaticInvocation.
-    return Constant(constant_evaluator_.EvaluateStaticInvocation(offset));
-  }
-
+Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
   TokenPosition position = ReadPosition();     // read position.
   if (p != NULL) *p = position;
@@ -3236,17 +3222,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
-    bool is_const,
     TokenPosition* p) {
-  if (is_const) {
-    intptr_t offset = ReaderOffset() - 1;                 // Include the tag.
-    (p != NULL) ? * p = ReadPosition() : ReadPosition();  // read position.
-
-    SetOffset(offset);
-    SkipExpression();  // read past this ConstructorInvocation.
-    return Constant(constant_evaluator_.EvaluateConstructorInvocation(offset));
-  }
-
   TokenPosition position = ReadPosition();  // read position.
   if (p != NULL) *p = position;
 
@@ -3579,16 +3555,6 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral(
-    TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
-
-  intptr_t offset = ReaderOffset() - 1;  // EvaluateExpression needs the tag.
-  SkipStringReference();                 // read index into string table.
-  return Constant(
-      Instance::ZoneHandle(Z, constant_evaluator_.EvaluateExpression(offset)));
-}
-
 Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
 
@@ -3651,17 +3617,7 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
-                                                     TokenPosition* p) {
-  if (is_const) {
-    intptr_t offset = ReaderOffset() - 1;                 // Include the tag.
-    (p != NULL) ? * p = ReadPosition() : ReadPosition();  // read position.
-
-    SetOffset(offset);
-    SkipExpression();  // read past the ListLiteral.
-    return Constant(constant_evaluator_.EvaluateListLiteral(offset));
-  }
-
+Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
   if (p != NULL) *p = position;
 
@@ -3704,17 +3660,7 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
-                                                    TokenPosition* p) {
-  if (is_const) {
-    intptr_t offset = ReaderOffset() - 1;  // Include the tag.
-    (p != NULL) ? * p = ReadPosition() : ReadPosition();
-
-    SetOffset(offset);
-    SkipExpression();  // Read past the MapLiteral.
-    return Constant(constant_evaluator_.EvaluateMapLiteral(offset));
-  }
-
+Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
   if (p != NULL) *p = position;
 
@@ -3883,8 +3829,8 @@
   }
   if (position != nullptr) *position = p;
   const intptr_t constant_offset = ReadUInt();
-  Fragment result = Constant(Object::ZoneHandle(
-      Z, constant_evaluator_.EvaluateConstantExpression(constant_offset)));
+  Fragment result = Constant(
+      Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_offset)));
   return result;
 }
 
@@ -4456,16 +4402,6 @@
     if (i == default_case) {
       ASSERT(i == (case_count - 1));
 
-      // Evaluate the conditions for the default [SwitchCase] just for the
-      // purpose of potentially triggering a compile-time error.
-
-      for (intptr_t j = 0; j < expression_count; ++j) {
-        ReadPosition();  // read jth position.
-        // this reads the expression, but doesn't skip past it.
-        constant_evaluator_.EvaluateExpression(ReaderOffset());
-        SkipExpression();  // read jth expression.
-      }
-
       if (block.HadJumper(i)) {
         // There are several branches to the body, so we will make a goto to
         // the join block (and prepend a join instruction to the real body).
@@ -4489,9 +4425,8 @@
         TargetEntryInstr* otherwise;
 
         TokenPosition position = ReadPosition();  // read jth position.
-        current_instructions += Constant(Instance::ZoneHandle(
-            Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
-        SkipExpression();  // read jth expression.
+        current_instructions += Constant(
+            Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
         current_instructions += PushArgument();
         current_instructions += LoadLocal(scopes()->switch_variable);
         current_instructions += PushArgument();
@@ -4941,12 +4876,11 @@
     instructions += NullConstant();
   } else {
     if (helper.IsConst()) {
-      const Instance& constant_value = Instance::ZoneHandle(
-          Z, constant_evaluator_.EvaluateExpression(
-                 ReaderOffset()));  // read initializer form current position.
+      // Read const initializer form current position.
+      const Instance& constant_value =
+          Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression());
       variable->SetConstValue(constant_value);
       instructions += Constant(constant_value);
-      SkipExpression();  // skip initializer.
     } else {
       // Initializer
       instructions += BuildExpression();  // read (actual) initializer.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 830ec2a..ba3c765 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -8,7 +8,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 #include "vm/compiler/frontend/bytecode_reader.h"
-#include "vm/compiler/frontend/constant_evaluator.h"
+#include "vm/compiler/frontend/constant_reader.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/frontend/scope_builder.h"
@@ -37,10 +37,7 @@
         flow_graph_builder_(flow_graph_builder),
         active_class_(&flow_graph_builder->active_class_),
         type_translator_(this, active_class_, /* finalize= */ true),
-        constant_evaluator_(this,
-                            &type_translator_,
-                            active_class_,
-                            flow_graph_builder),
+        constant_reader_(this, active_class_),
         bytecode_metadata_helper_(this, active_class_),
         direct_call_metadata_helper_(this),
         inferred_type_metadata_helper_(this),
@@ -299,8 +296,8 @@
   Fragment BuildMethodInvocation(TokenPosition* position);
   Fragment BuildDirectMethodInvocation(TokenPosition* position);
   Fragment BuildSuperMethodInvocation(TokenPosition* position);
-  Fragment BuildStaticInvocation(bool is_const, TokenPosition* position);
-  Fragment BuildConstructorInvocation(bool is_const, TokenPosition* position);
+  Fragment BuildStaticInvocation(TokenPosition* position);
+  Fragment BuildConstructorInvocation(TokenPosition* position);
   Fragment BuildNot(TokenPosition* position);
   Fragment BuildNullCheck(TokenPosition* position);
   Fragment BuildLogicalExpression(TokenPosition* position);
@@ -310,13 +307,12 @@
   Fragment BuildStringConcatenation(TokenPosition* position);
   Fragment BuildIsExpression(TokenPosition* position);
   Fragment BuildAsExpression(TokenPosition* position);
-  Fragment BuildSymbolLiteral(TokenPosition* position);
   Fragment BuildTypeLiteral(TokenPosition* position);
   Fragment BuildThisExpression(TokenPosition* position);
   Fragment BuildRethrow(TokenPosition* position);
   Fragment BuildThrow(TokenPosition* position);
-  Fragment BuildListLiteral(bool is_const, TokenPosition* position);
-  Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
+  Fragment BuildListLiteral(TokenPosition* position);
+  Fragment BuildMapLiteral(TokenPosition* position);
   Fragment BuildFunctionExpression();
   Fragment BuildLet(TokenPosition* position);
   Fragment BuildBlockExpression();
@@ -365,7 +361,7 @@
   FlowGraphBuilder* flow_graph_builder_;
   ActiveClass* const active_class_;
   TypeTranslator type_translator_;
-  ConstantEvaluator constant_evaluator_;
+  ConstantReader constant_reader_;
   BytecodeMetadataHelper bytecode_metadata_helper_;
   DirectCallMetadataHelper direct_call_metadata_helper_;
   InferredTypeMetadataHelper inferred_type_metadata_helper_;
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 871f1f8..bf79b16 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -303,9 +303,7 @@
       // read string reference (i.e. named_parameters[i].name).
       CalculateStringReferenceFingerprint();
       CalculateDartTypeFingerprint();  // read named_parameters[i].type.
-      if (translation_helper_.info().kernel_binary_version() >= 29) {
-        BuildHash(ReadFlags());  // read flags.
-      }
+      BuildHash(ReadFlags());          // read flags.
     }
   }
 
@@ -433,13 +431,11 @@
       CalculateArgumentsFingerprint();      // read arguments.
       return;
     case kStaticInvocation:
-    case kConstStaticInvocation:
       ReadPosition();                       // read position.
       CalculateCanonicalNameFingerprint();  // read target_reference.
       CalculateArgumentsFingerprint();      // read arguments.
       return;
     case kConstructorInvocation:
-    case kConstConstructorInvocation:
       ReadPosition();                       // read position.
       CalculateCanonicalNameFingerprint();  // read target_reference.
       CalculateArgumentsFingerprint();      // read arguments.
@@ -466,15 +462,6 @@
       ReadPosition();                           // read position.
       CalculateListOfExpressionsFingerprint();  // read list of expressions.
       return;
-    case kListConcatenation:
-    case kSetConcatenation:
-    case kMapConcatenation:
-    case kInstanceCreation:
-    case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are removed by the constant evaluator.
-      UNREACHABLE();
-      break;
     case kIsExpression:
       ReadPosition();                    // read position.
       CalculateExpressionFingerprint();  // read operand.
@@ -486,9 +473,6 @@
       CalculateExpressionFingerprint();  // read operand.
       CalculateDartTypeFingerprint();    // read type.
       return;
-    case kSymbolLiteral:
-      CalculateStringReferenceFingerprint();  // read index into string table.
-      return;
     case kTypeLiteral:
       CalculateDartTypeFingerprint();  // read type.
       return;
@@ -502,19 +486,16 @@
       CalculateExpressionFingerprint();  // read expression.
       return;
     case kListLiteral:
-    case kConstListLiteral:
       ReadPosition();                           // read position.
       CalculateDartTypeFingerprint();           // read type.
       CalculateListOfExpressionsFingerprint();  // read list of expressions.
       return;
     case kSetLiteral:
-    case kConstSetLiteral:
       // Set literals are currently desugared in the frontend and will not
       // reach the VM. See http://dartbug.com/35124 for discussion.
       UNREACHABLE();
       return;
-    case kMapLiteral:
-    case kConstMapLiteral: {
+    case kMapLiteral: {
       ReadPosition();                           // read position.
       CalculateDartTypeFingerprint();           // read type.
       CalculateDartTypeFingerprint();           // read value type.
@@ -573,13 +554,26 @@
       SkipDartType();
       SkipConstantReference();
       return;
-    case kDeprecated_ConstantExpression:
-      SkipConstantReference();
-      return;
     case kLoadLibrary:
     case kCheckLibraryIsLoaded:
       ReadUInt();  // skip library index
       return;
+    case kConstStaticInvocation:
+    case kConstConstructorInvocation:
+    case kConstListLiteral:
+    case kConstSetLiteral:
+    case kConstMapLiteral:
+    case kSymbolLiteral:
+      // Const invocations and const literals are removed by the
+      // constant evaluator.
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+    case kInstanceCreation:
+    case kFileUriExpression:
+      // Collection concatenation, instance creation operations and
+      // in-expression URI changes are internal to the front end and
+      // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
       UNREACHABLE();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 973f4e9..a3877ad 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -411,6 +411,188 @@
   }
 }
 
+Fragment FlowGraphBuilder::LoadLateInstanceField(const Field& field,
+                                                 LocalVariable* instance) {
+  Fragment instructions;
+  TargetEntryInstr *is_uninitialized, *is_initialized;
+  const TokenPosition position = field.token_pos();
+
+  // Check whether the field has been initialized already.
+  instructions += LoadLocal(instance);
+  instructions += LoadField(field);
+  LocalVariable* temp = MakeTemporary();
+  instructions += LoadLocal(temp);
+  instructions += Constant(Object::sentinel());
+  instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
+
+  JoinEntryInstr* join = BuildJoinEntry();
+
+  if (field.has_initializer()) {
+    // has_nontrivial_initializer is required for EnsureInitializerFunction. The
+    // trivial initializer case is treated as a normal field.
+    ASSERT(field.has_nontrivial_initializer());
+
+    // If the field isn't initialized, call the initializer and set the field.
+    Function& init_function =
+        Function::ZoneHandle(Z, field.EnsureInitializerFunction());
+    Fragment initialize(is_uninitialized);
+    initialize += LoadLocal(instance);  // For the store.
+    initialize += LoadLocal(instance);  // For the init call.
+    initialize += PushArgument();
+    initialize += StaticCall(position, init_function,
+                             /* argument_count = */ 1, ICData::kStatic);
+    initialize += StoreLocal(position, temp);
+    initialize += StoreInstanceFieldGuarded(
+        field, StoreInstanceFieldInstr::Kind::kInitializing);
+    initialize += Goto(join);
+  } else {
+    // The field has no initializer, so throw a LateInitializationError.
+    Fragment initialize(is_uninitialized);
+    initialize += ThrowLateInitializationError(
+        position, String::ZoneHandle(Z, field.name()));
+    initialize += Goto(join);
+  }
+
+  {
+    // Already initialized, so there's nothing to do.
+    Fragment already_initialized(is_initialized);
+    already_initialized += Goto(join);
+  }
+
+  // Now that the field has been initialized, load it.
+  instructions = Fragment(instructions.entry, join);
+
+  return instructions;
+}
+
+Fragment FlowGraphBuilder::LoadLateStaticField(const Field& field) {
+  Fragment instructions;
+
+  // Check whether the field has been initialized already.
+  TargetEntryInstr *is_uninitialized, *is_initialized;
+  const TokenPosition position = field.token_pos();
+  instructions += Constant(field);
+  instructions += LoadStaticField();
+  LocalVariable* temp = MakeTemporary();
+  instructions += LoadLocal(temp);
+  instructions += Constant(Object::sentinel());
+  instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
+
+  JoinEntryInstr* join = BuildJoinEntry();
+
+  if (field.has_initializer()) {
+    // has_nontrivial_initializer is required for EnsureInitializerFunction. The
+    // trivial initializer case is treated as a normal field.
+    ASSERT(field.has_nontrivial_initializer());
+
+    // If the field isn't initialized, call the initializer and set the field.
+    Function& init_function =
+        Function::ZoneHandle(Z, field.EnsureInitializerFunction());
+    Fragment initialize(is_uninitialized);
+    initialize += StaticCall(position, init_function,
+                             /* argument_count = */ 0, ICData::kStatic);
+    initialize += StoreLocal(position, temp);
+    initialize += StoreStaticField(position, field);
+    initialize += Goto(join);
+  } else {
+    // The field has no initializer, so throw a LateInitializationError.
+    Fragment initialize(is_uninitialized);
+    initialize += ThrowLateInitializationError(
+        position, String::ZoneHandle(Z, field.name()));
+    initialize += Goto(join);
+  }
+
+  {
+    // Already initialized, so there's nothing to do.
+    Fragment already_initialized(is_initialized);
+    already_initialized += Goto(join);
+  }
+
+  // Now that the field has been initialized, load it.
+  instructions = Fragment(instructions.entry, join);
+
+  return instructions;
+}
+
+Fragment FlowGraphBuilder::StoreLateInstanceField(const Field& field,
+                                                  LocalVariable* instance,
+                                                  LocalVariable* setter_value) {
+  // Implicit setters for non-final late fields are the same as non-late fields.
+  if (!field.is_final()) {
+    return StoreInstanceFieldGuarded(field,
+                                     StoreInstanceFieldInstr::Kind::kOther);
+  }
+
+  // If a late final field has an initializer, the setter always throws. This
+  // case is typically caught as a compile error, but there are ways to avoid
+  // that error, so we also need this runtime error.
+  const TokenPosition position = field.token_pos();
+  if (field.has_initializer()) {
+    Fragment instructions;
+    instructions += Drop();
+    instructions += Drop();
+    instructions += ThrowLateInitializationError(
+        position, String::ZoneHandle(Z, field.name()));
+    return instructions;
+  }
+
+  // Late final fields with no initializer can be written to once.
+  Fragment instructions;
+  TargetEntryInstr *is_uninitialized, *is_initialized;
+
+  // Check whether the field has been initialized already.
+  instructions += Drop();
+  instructions += LoadField(field);
+  instructions += Constant(Object::sentinel());
+  instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
+
+  JoinEntryInstr* join = BuildJoinEntry();
+
+  {
+    // If the field isn't initialized, set it to the new value.
+    Fragment initialize(is_uninitialized);
+    initialize += LoadLocal(instance);
+    initialize += LoadLocal(setter_value);
+    initialize +=
+        StoreInstanceFieldGuarded(field, StoreInstanceFieldInstr::Kind::kOther);
+    initialize += Goto(join);
+  }
+
+  {
+    // If the field is already initialized, throw a LateInitializationError.
+    Fragment already_initialized(is_initialized);
+    already_initialized += ThrowLateInitializationError(
+        position, String::ZoneHandle(Z, field.name()));
+    already_initialized += Goto(join);
+  }
+
+  return Fragment(instructions.entry, join);
+}
+
+Fragment FlowGraphBuilder::ThrowLateInitializationError(TokenPosition position,
+                                                        const String& name) {
+  const Class& klass = Class::ZoneHandle(
+      Z, Library::LookupCoreClass(Symbols::LateInitializationError()));
+  ASSERT(!klass.IsNull());
+
+  const Function& throw_new =
+      Function::ZoneHandle(Z, klass.LookupStaticFunctionAllowPrivate(
+                                  H.DartSymbolObfuscate("_throwNew")));
+  ASSERT(!throw_new.IsNull());
+
+  Fragment instructions;
+
+  // Call _LateInitializationError._throwNew.
+  instructions += Constant(name);
+  instructions += PushArgument();  // name
+
+  instructions += StaticCall(position, throw_new,
+                             /* argument_count = */ 1, ICData::kStatic);
+  instructions += Drop();
+
+  return instructions;
+}
+
 Fragment FlowGraphBuilder::InitInstanceField(const Field& field) {
   ASSERT(field.is_instance());
   ASSERT(field.needs_load_guard());
@@ -2466,6 +2648,9 @@
     field = function.accessor_field();
   }
 
+  const Class& owner = Class::ZoneHandle(Z, field.Owner());
+  const bool lib_is_nnbd = Library::ZoneHandle(Z, owner.library()).is_nnbd();
+
   graph_entry_ =
       new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
 
@@ -2490,8 +2675,13 @@
                               AssertAssignableInstr::kParameterCheck);
     }
     if (is_method) {
-      body += StoreInstanceFieldGuarded(field,
-                                        StoreInstanceFieldInstr::Kind::kOther);
+      if (field.is_late()) {
+        body += StoreLateInstanceField(
+            field, parsed_function_->ParameterVariable(0), setter_value);
+      } else {
+        body += StoreInstanceFieldGuarded(
+            field, StoreInstanceFieldInstr::Kind::kOther);
+      }
     } else {
       body += StoreStaticField(TokenPosition::kNoSource, field);
     }
@@ -2505,8 +2695,13 @@
       // TODO(rmacnak): Type check.
     }
 #endif
-    body += LoadLocal(parsed_function_->ParameterVariable(0));
-    body += LoadField(field);
+    if (field.is_late() && !field.has_trivial_initializer()) {
+      body +=
+          LoadLateInstanceField(field, parsed_function_->ParameterVariable(0));
+    } else {
+      body += LoadLocal(parsed_function_->ParameterVariable(0));
+      body += LoadField(field);
+    }
   } else if (field.is_const()) {
     // If the parser needs to know the value of an uninitialized constant field
     // it will set the value to the transition sentinel (used to detect circular
@@ -2519,11 +2714,18 @@
   } else {
     // The field always has an initializer because static fields without
     // initializers are initialized eagerly and do not have implicit getters.
-    ASSERT(field.has_initializer());
-    body += Constant(field);
-    body += InitStaticField(field);
-    body += Constant(field);
-    body += LoadStaticField();
+    if (lib_is_nnbd) {
+      // In NNBD mode, static fields act like late fields regardless of whether
+      // they're marked late. The only behavioural difference is in compile
+      // errors that are handled by the front end.
+      body += LoadLateStaticField(field);
+    } else {
+      ASSERT(field.has_nontrivial_initializer());
+      body += Constant(field);
+      body += InitStaticField(field);
+      body += Constant(field);
+      body += LoadStaticField();
+    }
   }
   body += Return(TokenPosition::kNoSource);
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index fc461c0..434106f 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -132,6 +132,11 @@
 
   Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment LoadLocal(LocalVariable* variable);
+  Fragment LoadLateInstanceField(const Field& field, LocalVariable* instance);
+  Fragment LoadLateStaticField(const Field& field);
+  Fragment StoreLateInstanceField(const Field& field,
+                                  LocalVariable* instance,
+                                  LocalVariable* setter_value);
   Fragment InitInstanceField(const Field& field);
   Fragment InitStaticField(const Field& field);
   Fragment NativeCall(const String* name, const Function* function);
@@ -155,6 +160,8 @@
   Fragment StringInterpolateSingle(TokenPosition position);
   Fragment ThrowTypeError();
   Fragment ThrowNoSuchMethodError();
+  Fragment ThrowLateInitializationError(TokenPosition position,
+                                        const String& name);
   Fragment BuildImplicitClosureCreation(const Function& target);
 
   Fragment EvaluateAssertion();
@@ -384,7 +391,6 @@
 
   friend class BreakableBlock;
   friend class CatchBlock;
-  friend class ConstantEvaluator;
   friend class ProgramState;
   friend class StreamingFlowGraphBuilder;
   friend class SwitchBlock;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index bad19e4..f02eb50 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1009,11 +1009,7 @@
       if (++next_read_ == field) return;
       FALL_THROUGH;
     case kFlags:
-      if (helper_->translation_helper_.info().kernel_binary_version() >= 29) {
-        flags_ = helper_->ReadUInt();
-      } else {
-        flags_ = helper_->ReadFlags();
-      }
+      flags_ = helper_->ReadUInt();
       if (++next_read_ == field) return;
       FALL_THROUGH;
     case kName:
@@ -1081,11 +1077,7 @@
       if (++next_read_ == field) return;
       FALL_THROUGH;
     case kFlags:
-      if (helper_->translation_helper_.info().kernel_binary_version() >= 29) {
-        flags_ = helper_->ReadUInt();
-      } else {
-        flags_ = helper_->ReadFlags();
-      }
+      flags_ = helper_->ReadUInt();
       if (++next_read_ == field) return;
       FALL_THROUGH;
     case kName:
@@ -1317,10 +1309,8 @@
       FALL_THROUGH;
     }
     case kLanguageVersion: {
-      if (binary_version_ >= 27) {
-        helper_->ReadUInt();  // Read major language version.
-        helper_->ReadUInt();  // Read minor language version.
-      }
+      helper_->ReadUInt();  // Read major language version.
+      helper_->ReadUInt();  // Read minor language version.
       if (++next_read_ == field) return;
       FALL_THROUGH;
     }
@@ -2043,9 +2033,7 @@
       // read string reference (i.e. named_parameters[i].name).
       SkipStringReference();
       SkipDartType();  // read named_parameters[i].type.
-      if (translation_helper_.info().kernel_binary_version() >= 29) {
-        SkipBytes(1);  // read flags
-      }
+      SkipBytes(1);    // read flags
     }
   }
 
@@ -2224,13 +2212,11 @@
       SkipArguments();               // read arguments.
       return;
     case kStaticInvocation:
-    case kConstStaticInvocation:
       ReadPosition();                // read position.
       SkipCanonicalNameReference();  // read procedure_reference.
       SkipArguments();               // read arguments.
       return;
     case kConstructorInvocation:
-    case kConstConstructorInvocation:
       ReadPosition();                // read position.
       SkipCanonicalNameReference();  // read target_reference.
       SkipArguments();               // read arguments.
@@ -2257,15 +2243,6 @@
       ReadPosition();           // read position.
       SkipListOfExpressions();  // read list of expressions.
       return;
-    case kListConcatenation:
-    case kSetConcatenation:
-    case kMapConcatenation:
-    case kInstanceCreation:
-    case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are removed by the constant evaluator.
-      UNREACHABLE();
-      break;
     case kIsExpression:
       ReadPosition();    // read position.
       SkipExpression();  // read operand.
@@ -2277,9 +2254,6 @@
       SkipExpression();  // read operand.
       SkipDartType();    // read type.
       return;
-    case kSymbolLiteral:
-      SkipStringReference();  // read index into string table.
-      return;
     case kTypeLiteral:
       SkipDartType();  // read type.
       return;
@@ -2293,19 +2267,16 @@
       SkipExpression();  // read expression.
       return;
     case kListLiteral:
-    case kConstListLiteral:
       ReadPosition();           // read position.
       SkipDartType();           // read type.
       SkipListOfExpressions();  // read list of expressions.
       return;
     case kSetLiteral:
-    case kConstSetLiteral:
       // Set literals are currently desugared in the frontend and will not
       // reach the VM. See http://dartbug.com/35124 for discussion.
       UNREACHABLE();
       return;
-    case kMapLiteral:
-    case kConstMapLiteral: {
+    case kMapLiteral: {
       ReadPosition();                           // read position.
       SkipDartType();                           // read key type.
       SkipDartType();                           // read value type.
@@ -2360,13 +2331,26 @@
       SkipDartType();  // read type.
       SkipConstantReference();
       return;
-    case kDeprecated_ConstantExpression:
-      SkipConstantReference();
-      return;
     case kLoadLibrary:
     case kCheckLibraryIsLoaded:
       ReadUInt();  // skip library index
       return;
+    case kConstStaticInvocation:
+    case kConstConstructorInvocation:
+    case kConstListLiteral:
+    case kConstSetLiteral:
+    case kConstMapLiteral:
+    case kSymbolLiteral:
+      // Const invocations and const literals are removed by the
+      // constant evaluator.
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+    case kInstanceCreation:
+    case kFileUriExpression:
+      // Collection concatenation, instance creation operations and
+      // in-expression URI changes are internal to the front end and
+      // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
       UNREACHABLE();
@@ -2929,10 +2913,8 @@
       // read string reference (i.e. named_parameters[i].name).
       String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
       BuildTypeInternal();  // read named_parameters[i].type.
-      if (translation_helper_.info().kernel_binary_version() >= 29) {
-        // TODO(markov): Store 'required' bit.
-        helper_->ReadFlags();  // read flags
-      }
+      // TODO(markov): Store 'required' bit.
+      helper_->ReadFlags();  // read flags
       parameter_types.SetAt(pos, result_);
       parameter_names.SetAt(pos, name);
     }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index de53d78..c17bd59 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1125,7 +1125,7 @@
   friend class BytecodeReaderHelper;
   friend class ClassHelper;
   friend class CallSiteAttributesMetadataHelper;
-  friend class ConstantEvaluator;
+  friend class ConstantReader;
   friend class ConstantHelper;
   friend class ConstructorHelper;
   friend class DirectCallMetadataHelper;
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 319b362..8e1302a 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -184,7 +184,7 @@
           Field& class_field = Field::Handle(Z);
           for (intptr_t i = 0; i < class_fields.Length(); ++i) {
             class_field ^= class_fields.At(i);
-            if (!class_field.is_static()) {
+            if (!class_field.is_static() && !class_field.is_late()) {
               ExternalTypedData& kernel_data =
                   ExternalTypedData::Handle(Z, class_field.KernelData());
               ASSERT(!kernel_data.IsNull());
@@ -469,7 +469,7 @@
     Field& class_field = Field::Handle(Z);
     for (intptr_t i = 0; i < class_fields.Length(); ++i) {
       class_field ^= class_fields.At(i);
-      if (!class_field.is_static()) {
+      if (!class_field.is_static() && !class_field.is_late()) {
         ExternalTypedData& kernel_data =
             ExternalTypedData::Handle(Z, class_field.KernelData());
         ASSERT(!kernel_data.IsNull());
@@ -750,13 +750,11 @@
       helper_.SkipCanonicalNameReference();
       return;
     case kStaticInvocation:
-    case kConstStaticInvocation:
       helper_.ReadPosition();                // read position.
       helper_.SkipCanonicalNameReference();  // read procedure_reference.
       VisitArguments();                      // read arguments.
       return;
     case kConstructorInvocation:
-    case kConstConstructorInvocation:
       helper_.ReadPosition();                // read position.
       helper_.SkipCanonicalNameReference();  // read target_reference.
       VisitArguments();                      // read arguments.
@@ -790,15 +788,6 @@
       }
       return;
     }
-    case kListConcatenation:
-    case kSetConcatenation:
-    case kMapConcatenation:
-    case kInstanceCreation:
-    case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are removed by the constant evaluator.
-      UNREACHABLE();
-      break;
     case kIsExpression:
       helper_.ReadPosition();  // read position.
       VisitExpression();       // read operand.
@@ -810,9 +799,6 @@
       VisitExpression();       // read operand.
       VisitDartType();         // read type.
       return;
-    case kSymbolLiteral:
-      helper_.SkipStringReference();  // read index into string table.
-      return;
     case kTypeLiteral:
       VisitDartType();  // read type.
       return;
@@ -826,8 +812,7 @@
       helper_.ReadPosition();  // read position.
       VisitExpression();       // read expression.
       return;
-    case kListLiteral:
-    case kConstListLiteral: {
+    case kListLiteral: {
       helper_.ReadPosition();                           // read position.
       VisitDartType();                                  // read type.
       intptr_t list_length = helper_.ReadListLength();  // read list length.
@@ -836,15 +821,13 @@
       }
       return;
     }
-    case kSetLiteral:
-    case kConstSetLiteral: {
+    case kSetLiteral: {
       // Set literals are currently desugared in the frontend and will not
       // reach the VM. See http://dartbug.com/35124 for discussion.
       UNREACHABLE();
       return;
     }
-    case kMapLiteral:
-    case kConstMapLiteral: {
+    case kMapLiteral: {
       helper_.ReadPosition();                           // read position.
       VisitDartType();                                  // read key type.
       VisitDartType();                                  // read value type.
@@ -917,10 +900,6 @@
       helper_.SkipDartType();
       helper_.SkipConstantReference();
       return;
-    case kDeprecated_ConstantExpression: {
-      helper_.SkipConstantReference();
-      return;
-    }
     case kInstantiation: {
       VisitExpression();
       const intptr_t list_length =
@@ -934,6 +913,22 @@
     case kCheckLibraryIsLoaded:
       helper_.ReadUInt();  // library index
       break;
+    case kConstStaticInvocation:
+    case kConstConstructorInvocation:
+    case kConstListLiteral:
+    case kConstSetLiteral:
+    case kConstMapLiteral:
+    case kSymbolLiteral:
+      // Const invocations and const literals are removed by the
+      // constant evaluator.
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+    case kInstanceCreation:
+    case kFileUriExpression:
+      // Collection concatenation, instance creation operations and
+      // in-expression URI changes are internal to the front end and
+      // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
       UNREACHABLE();
@@ -1369,9 +1364,7 @@
       // read string reference (i.e. named_parameters[i].name).
       helper_.SkipStringReference();
       VisitDartType();  // read named_parameters[i].type.
-      if (helper_.translation_helper_.info().kernel_binary_version() >= 29) {
-        helper_.ReadByte();  // read flags
-      }
+      helper_.ReadByte();  // read flags
     }
   }
 
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index a6f9de5..025d22d 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -625,8 +625,8 @@
   V(StoreFieldTOS_Wide,                    D, WIDE, lit, ___, ___)             \
   V(StoreIndexedTOS,                       0, ORDN, ___, ___, ___)             \
   V(Unused20,                              0, RESV, ___, ___, ___)             \
-  V(Unused40,                              0, RESV, ___, ___, ___)             \
-  V(Unused41,                              0, RESV, ___, ___, ___)             \
+  V(InitLateField,                         D, ORDN, lit, ___, ___)             \
+  V(InitLateField_Wide,                    D, WIDE, lit, ___, ___)             \
   V(StoreStaticTOS,                        D, ORDN, lit, ___, ___)             \
   V(StoreStaticTOS_Wide,                   D, WIDE, lit, ___, ___)             \
   V(Jump,                                  T, ORDN, tgt, ___, ___)             \
@@ -749,7 +749,7 @@
   // Maximum bytecode format version supported by VM.
   // The range of supported versions should include version produced by bytecode
   // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
-  static const intptr_t kMaxSupportedBytecodeFormatVersion = 25;
+  static const intptr_t kMaxSupportedBytecodeFormatVersion = 26;
 
   enum Opcode {
 #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 05fb029..a8a2f94 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -69,6 +69,7 @@
 Dart_FileWriteCallback Dart::file_write_callback_ = NULL;
 Dart_FileCloseCallback Dart::file_close_callback_ = NULL;
 Dart_EntropySource Dart::entropy_source_callback_ = NULL;
+bool Dart::non_nullable_flag_ = false;
 
 // Structure for managing read-only global handles allocation used for
 // creating global read-only handles that are pre created and initialized
@@ -222,6 +223,9 @@
     ASSERT(Flags::Initialized());
     const bool is_vm_isolate = true;
 
+    // Cache value of "non-nullable" experimental flag.
+    set_non_nullable_flag(KernelIsolate::GetExperimentalFlag("non-nullable"));
+
     // Setup default flags for the VM isolate.
     Dart_IsolateFlags api_flags;
     Isolate::FlagsInitialize(&api_flags);
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 3fd9376..3399ca5 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -123,6 +123,8 @@
   static Dart_EntropySource entropy_source_callback() {
     return entropy_source_callback_;
   }
+  static void set_non_nullable_flag(bool value) { non_nullable_flag_ = value; }
+  static bool non_nullable_flag() { return non_nullable_flag_; }
 
  private:
   static void WaitForIsolateShutdown();
@@ -141,6 +143,7 @@
   static Dart_FileWriteCallback file_write_callback_;
   static Dart_FileCloseCallback file_close_callback_;
   static Dart_EntropySource entropy_source_callback_;
+  static bool non_nullable_flag_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d66238a..7db09c1 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1605,7 +1605,7 @@
   CHECK_ISOLATE(T->isolate());
   API_TIMELINE_BEGIN_END(T);
   TransitionNativeToVM transition(T);
-  T->isolate()->NotifyIdle(deadline);
+  T->isolate()->idle_time_handler()->NotifyIdle(deadline);
 }
 
 DART_EXPORT void Dart_NotifyLowMemory() {
@@ -6200,12 +6200,18 @@
     dwarf = new (Z) Dwarf(Z, nullptr, elf);
   }
 
+  // Note that the BSS section must come first because it cannot be placed in
+  // between any two non-writable segments, due to a bug in Jelly Bean's ELF
+  // loader. See also Elf::WriteProgramTable().
+  const intptr_t bss_base =
+      elf->AddBSSData("_kDartBSSData", sizeof(compiler::target::uword));
+
   BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
                                   ApiReallocate, /* initial_size= */ 2 * MB,
-                                  elf, dwarf);
-  BlobImageWriter isolate_image_writer(T, &isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       /* initial_size= */ 2 * MB, elf, dwarf);
+                                  bss_base, elf, dwarf);
+  BlobImageWriter isolate_image_writer(
+      T, &isolate_snapshot_instructions_buffer, ApiReallocate,
+      /* initial_size= */ 2 * MB, bss_base, elf, dwarf);
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                             &isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index e49bd50..392705a 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -3452,7 +3452,7 @@
           // the breakpoint in.
           continue;
         }
-        if (!field.has_initializer()) {
+        if (!field.has_nontrivial_initializer()) {
           continue;
         }
         start = field.token_pos();
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 5be327b..7f57a5d 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -644,6 +644,13 @@
 
     ASSERT(kNumImplicitSegments == 3);
     const intptr_t start = stream_->position();
+
+    // The Android dynamic linker in Jelly Bean incorrectly assumes that all
+    // non-writable segments are continguous. We put BSS first, so we must make
+    // this segment writable so it does not mark the BSS as read-only.
+    //
+    // The bug is here:
+    //   https://github.com/aosp-mirror/platform_bionic/blob/94963af28e445384e19775a838a29e6a71708179/linker/linker.c#L1991-L2001
 #if defined(TARGET_ARCH_IS_32_BIT)
     WriteWord(elf::PT_LOAD);
     WriteOff(0);   // File offset.
@@ -651,11 +658,11 @@
     WriteAddr(0);  // Physical address, not used.
     WriteWord(program_table_file_offset_ + program_table_file_size_);
     WriteWord(program_table_file_offset_ + program_table_file_size_);
-    WriteWord(elf::PF_R);
+    WriteWord(elf::PF_R | elf::PF_W);
     WriteWord(kPageSize);
 #else
     WriteWord(elf::PT_LOAD);
-    WriteWord(elf::PF_R);
+    WriteWord(elf::PF_R | elf::PF_W);
     WriteOff(0);   // File offset.
     WriteAddr(0);  // Virtual address.
     WriteAddr(0);  // Physical address, not used.
diff --git a/runtime/vm/gdb_helpers.cc b/runtime/vm/gdb_helpers.cc
index a8a1a60..6cb98f0 100644
--- a/runtime/vm/gdb_helpers.cc
+++ b/runtime/vm/gdb_helpers.cc
@@ -36,14 +36,7 @@
 // in the middle of a GC or interested in stub frames.
 DART_EXPORT
 void _printStackTrace() {
-  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
-                            Thread::Current(),
-                            StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* frame = frames.NextFrame();
-  while (frame != nullptr) {
-    OS::PrintErr("%s\n", frame->ToCString());
-    frame = frames.NextFrame();
-  }
+  StackFrame::DumpCurrentTrace();
 }
 
 // Like _printDartStackTrace, but works when stopped in generated code.
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index e5ef799..d70d64e 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -37,10 +37,11 @@
 
 // The default old gen heap size in MB, where 0 == unlimited.
 // 32-bit: OS limit is 2 or 3 GB
-// 64-bit: OS limit is 2^16 page table entries * 256 KB HeapPages = 16 GB
+// 64-bit: Linux's limit is
+//   sysctl vm.max_map_count (default 2^16) * 512 KB HeapPages = 32 GB
 // Set the VM limit below the OS limit to increase the likelihood of failing
 // gracefully with a Dart OutOfMemory exception instead of SIGABORT.
-const intptr_t kDefaultMaxOldGenHeapSize = (kWordSize <= 4) ? 1536 : 15360;
+const intptr_t kDefaultMaxOldGenHeapSize = (kWordSize <= 4) ? 1536 : 30720;
 
 #define kPosInfinity bit_cast<double>(DART_UINT64_C(0x7ff0000000000000))
 #define kNegInfinity bit_cast<double>(DART_UINT64_C(0xfff0000000000000))
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index b9b4824..92472c8 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -26,8 +26,7 @@
 class ForwardingPage;
 class GCMarker;
 
-// TODO(iposva): Determine heap sizes and tune the page size accordingly.
-static const intptr_t kPageSize = 256 * KB;
+static const intptr_t kPageSize = 512 * KB;
 static const intptr_t kPageSizeInWords = kPageSize / kWordSize;
 static const intptr_t kPageMask = ~(kPageSize - 1);
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index f043096..c1217a2 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -833,12 +833,14 @@
                                  uint8_t** instructions_blob_buffer,
                                  ReAlloc alloc,
                                  intptr_t initial_size,
+                                 intptr_t bss_base,
                                  Elf* elf,
                                  Dwarf* dwarf)
     : ImageWriter(thread->heap()),
       instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
       elf_(elf),
-      dwarf_(dwarf) {
+      dwarf_(dwarf),
+      bss_base_(bss_base) {
 #ifndef DART_PRECOMPILER
   RELEASE_ASSERT(elf_ == nullptr);
   RELEASE_ASSERT(dwarf_ == nullptr);
@@ -859,14 +861,6 @@
   if (elf_ != nullptr) {
     segment_base = elf_->NextMemoryOffset();
   }
-
-  // Calculate the start of the BSS section based on the known size of the
-  // text section and page alignment.
-  intptr_t bss_base = 0;
-  if (elf_ != nullptr) {
-    bss_base =
-        Utils::RoundUp(segment_base + instructions_length, Elf::kPageSize);
-  }
 #endif
 
   // This header provides the gap to make the instructions snapshot look like a
@@ -874,7 +868,7 @@
   instructions_blob_stream_.WriteTargetWord(instructions_length);
 #if defined(DART_PRECOMPILER)
   instructions_blob_stream_.WriteTargetWord(
-      elf_ != nullptr ? bss_base - segment_base : 0);
+      elf_ != nullptr ? bss_base_ - segment_base : 0);
 #else
   instructions_blob_stream_.WriteTargetWord(0);  // No relocations.
 #endif
@@ -1008,8 +1002,8 @@
         instructions_blob_stream_.SetPosition(payload_stream_start +
                                               reloc_offset);
 
-        const uword offset =
-            bss_base - (segment_base + payload_stream_start + reloc_offset) +
+        const compiler::target::word offset =
+            bss_base_ - (segment_base + payload_stream_start + reloc_offset) +
             addend;
         instructions_blob_stream_.WriteTargetWord(offset);
       }
@@ -1035,10 +1029,6 @@
         elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
                       instructions_blob_stream_.bytes_written());
     ASSERT(segment_base == segment_base2);
-
-    const intptr_t real_bss_base =
-        elf_->AddBSSData("_kDartVMBSSData", sizeof(compiler::target::uword));
-    ASSERT(bss_base == real_bss_base);
   }
 #endif
 }
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 7835778..6221311 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -355,6 +355,7 @@
                   uint8_t** instructions_blob_buffer,
                   ReAlloc alloc,
                   intptr_t initial_size,
+                  intptr_t bss_base = 0,
                   Elf* elf = nullptr,
                   Dwarf* dwarf = nullptr);
 
@@ -368,8 +369,9 @@
   intptr_t WriteByteSequence(uword start, uword end);
 
   WriteStream instructions_blob_stream_;
-  Elf* elf_;
-  Dwarf* dwarf_;
+  Elf* const elf_;
+  Dwarf* const dwarf_;
+  const intptr_t bss_base_;
 
   DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
 };
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 3f82a4a..aedda0b 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -1971,8 +1971,8 @@
       RawObject** call_top = SP + 1;
 
       InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
-      RawString* target_name = RAW_CAST(String, LOAD_CONSTANT(kidx));
-      argdesc_ = RAW_CAST(Array, LOAD_CONSTANT(kidx + 1));
+      RawString* target_name = String::RawCast(LOAD_CONSTANT(kidx));
+      argdesc_ = Array::RawCast(LOAD_CONSTANT(kidx + 1));
       if (!InstanceCall(thread, target_name, call_base, call_top, &pc, &FP,
                         &SP)) {
         HANDLE_EXCEPTION;
@@ -2239,6 +2239,20 @@
   }
 
   {
+    BYTECODE(InitLateField, D);
+    RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
+    RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+    intptr_t offset_in_words = Smi::Value(field->ptr()->value_.offset_);
+
+    instance->StorePointer(
+        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+        Object::RawCast(Object::sentinel().raw()), thread);
+
+    SP -= 1;  // Drop instance.
+    DISPATCH();
+  }
+
+  {
     BYTECODE(StoreStaticTOS, D);
     RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
     RawInstance* value = static_cast<RawInstance*>(*SP--);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index a39f06d..f1ea56d 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -138,6 +138,71 @@
   }
 }
 
+void IdleTimeHandler::InitializeWithHeap(Heap* heap) {
+  MutexLocker ml(&mutex_);
+  ASSERT(heap_ == nullptr && heap != nullptr);
+  heap_ = heap;
+}
+
+bool IdleTimeHandler::ShouldCheckForIdle() {
+  MutexLocker ml(&mutex_);
+  return idle_start_time_ > 0 && FLAG_idle_timeout_micros != 0 &&
+         disabled_counter_ == 0;
+}
+
+void IdleTimeHandler::UpdateStartIdleTime() {
+  MutexLocker ml(&mutex_);
+  if (disabled_counter_ == 0) {
+    idle_start_time_ = OS::GetCurrentMonotonicMicros();
+  }
+}
+
+bool IdleTimeHandler::ShouldNotifyIdle(int64_t* expiry) {
+  const int64_t now = OS::GetCurrentMonotonicMicros();
+
+  MutexLocker ml(&mutex_);
+  if (idle_start_time_ > 0 && disabled_counter_ == 0) {
+    const int64_t expiry_time = idle_start_time_ + FLAG_idle_timeout_micros;
+    if (expiry_time < now) {
+      idle_start_time_ = 0;
+      return true;
+    }
+  }
+
+  *expiry = now + FLAG_idle_timeout_micros;
+  return false;
+}
+
+void IdleTimeHandler::NotifyIdle(int64_t deadline) {
+  MutexLocker ml(&mutex_, /*no_safepoint_scope=*/false);
+  if (heap_ != nullptr) {
+    heap_->NotifyIdle(deadline);
+  }
+  idle_start_time_ = 0;
+}
+
+void IdleTimeHandler::NotifyIdleUsingDefaultDeadline() {
+  const int64_t now = OS::GetCurrentMonotonicMicros();
+  NotifyIdle(now + FLAG_idle_timeout_micros);
+}
+
+DisableIdleTimerScope::DisableIdleTimerScope(IdleTimeHandler* handler)
+    : handler_(handler) {
+  if (handler_ != nullptr) {
+    MutexLocker ml(&handler_->mutex_);
+    ++handler_->disabled_counter_;
+    handler_->idle_start_time_ = 0;
+  }
+}
+
+DisableIdleTimerScope::~DisableIdleTimerScope() {
+  if (handler_ != nullptr) {
+    MutexLocker ml(&handler_->mutex_);
+    --handler_->disabled_counter_;
+    ASSERT(handler_->disabled_counter_ >= 0);
+  }
+}
+
 IsolateGroup::IsolateGroup(std::unique_ptr<IsolateGroupSource> source,
                            void* embedder_data)
     : embedder_data_(embedder_data),
@@ -1961,10 +2026,6 @@
                          reinterpret_cast<uword>(this));
 }
 
-void Isolate::NotifyIdle(int64_t deadline) {
-  heap()->NotifyIdle(deadline);
-}
-
 void Isolate::AddClosureFunction(const Function& function) const {
   ASSERT(!Compiler::IsBackgroundCompilation());
   GrowableObjectArray& closures =
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 99a58a0..9c83e6b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -213,6 +213,50 @@
   intptr_t script_kernel_size;
 };
 
+// Tracks idle time and notifies heap when idle time expired.
+class IdleTimeHandler : public ValueObject {
+ public:
+  IdleTimeHandler() {}
+
+  // Initializes the idle time handler with the given [heap], to which
+  // idle notifications will be sent.
+  void InitializeWithHeap(Heap* heap);
+
+  // Returns whether the caller should check for idle timeouts.
+  bool ShouldCheckForIdle();
+
+  // Declares that the idle time should be reset to now.
+  void UpdateStartIdleTime();
+
+  // Returns whether idle time expired and [NotifyIdle] should be called.
+  bool ShouldNotifyIdle(int64_t* expiry);
+
+  // Notifies the heap that now is a good time to do compactions and indicates
+  // we have time for the GC until [deadline].
+  void NotifyIdle(int64_t deadline);
+
+  // Calls [NotifyIdle] with the default deadline.
+  void NotifyIdleUsingDefaultDeadline();
+
+ private:
+  friend class DisableIdleTimerScope;
+
+  Mutex mutex_;
+  Heap* heap_ = nullptr;
+  intptr_t disabled_counter_ = 0;
+  int64_t idle_start_time_ = 0;
+};
+
+// Disables firing of the idle timer while this object is alive.
+class DisableIdleTimerScope : public ValueObject {
+ public:
+  explicit DisableIdleTimerScope(IdleTimeHandler* handler);
+  ~DisableIdleTimerScope();
+
+ private:
+  IdleTimeHandler* handler_;
+};
+
 // Represents an isolate group and is shared among all isolates within a group.
 class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
  public:
@@ -440,8 +484,13 @@
 
   void SendInternalLibMessage(LibMsgId msg_id, uint64_t capability);
 
+  IdleTimeHandler* idle_time_handler() { return &idle_time_handler_; }
+
   Heap* heap() const { return heap_; }
-  void set_heap(Heap* value) { heap_ = value; }
+  void set_heap(Heap* value) {
+    idle_time_handler_.InitializeWithHeap(value);
+    heap_ = value;
+  }
 
   ObjectStore* object_store() const { return object_store_; }
   void set_object_store(ObjectStore* value) { object_store_ = value; }
@@ -512,8 +561,6 @@
 #endif
   }
 
-  void NotifyIdle(int64_t deadline);
-
   bool compaction_in_progress() const {
     return CompactionInProgressBit::decode(isolate_flags_);
   }
@@ -1082,6 +1129,7 @@
   MarkingStack* deferred_marking_stack_ = nullptr;
   Heap* heap_ = nullptr;
   IsolateGroup* isolate_group_ = nullptr;
+  IdleTimeHandler idle_time_handler_;
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   NativeCallbackTrampolines native_callback_trampolines_;
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 8e2dbec..cb89d2c 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -6,7 +6,7 @@
 
 #include "vm/bit_vector.h"
 #include "vm/compiler/frontend/bytecode_reader.h"
-#include "vm/compiler/frontend/constant_evaluator.h"
+#include "vm/compiler/frontend/constant_reader.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/longjump.h"
@@ -373,7 +373,8 @@
             if (temp_field.is_declared_in_bytecode()) {
               token_positions.Add(temp_field.token_pos().value());
               token_positions.Add(temp_field.end_token_pos().value());
-              if (temp_field.is_static() && temp_field.has_initializer()) {
+              if (temp_field.is_static() &&
+                  temp_field.has_nontrivial_initializer()) {
                 temp_function = temp_field.EnsureInitializerFunction();
                 CollectBytecodeFunctionTokenPositions(temp_function,
                                                       &token_positions);
@@ -454,7 +455,7 @@
         if (field.is_declared_in_bytecode()) {
           token_positions.Add(field.token_pos().value());
           token_positions.Add(field.end_token_pos().value());
-          if (field.is_static() && field.has_initializer()) {
+          if (field.is_static() && field.has_nontrivial_initializer()) {
             temp_function = field.EnsureInitializerFunction();
             CollectBytecodeFunctionTokenPositions(temp_function,
                                                   &token_positions);
@@ -488,8 +489,7 @@
                            script,
                            data,
                            data_program_offset),
-        type_translator_(this, active_class, /* finalize= */ true),
-        constant_evaluator_(this, &type_translator_, active_class, nullptr) {}
+        constant_reader_(this, active_class) {}
 
   RawObject* EvaluateMetadata(intptr_t kernel_offset,
                               bool is_annotations_offset) {
@@ -518,12 +518,11 @@
       }
     }
 
-    return constant_evaluator_.EvaluateAnnotations();
+    return constant_reader_.ReadAnnotations();
   }
 
  private:
-  TypeTranslator type_translator_;
-  ConstantEvaluator constant_evaluator_;
+  ConstantReader constant_reader_;
 
   DISALLOW_COPY_AND_ASSIGN(MetadataEvaluator);
 };
@@ -568,14 +567,12 @@
                            script,
                            data,
                            data_program_offset),
-        type_translator_(this, active_class, /* finalize= */ true),
-        constant_evaluator_(this, &type_translator_, active_class, nullptr) {}
+        constant_reader_(this, active_class) {}
 
   RawObject* BuildParameterDescriptor(const Function& function);
 
  private:
-  TypeTranslator type_translator_;
-  ConstantEvaluator constant_evaluator_;
+  ConstantReader constant_reader_;
 
   DISALLOW_COPY_AND_ASSIGN(ParameterDescriptorBuilder);
 };
@@ -611,25 +608,25 @@
 
     Tag tag = ReadTag();  // read (first part of) initializer.
     if ((tag == kSomething) && !function.is_abstract()) {
-      // this will (potentially) read the initializer, but reset the position.
+      // This will read the initializer.
       Instance& constant = Instance::ZoneHandle(
-          zone_, constant_evaluator_.EvaluateExpression(ReaderOffset()));
+          zone_, constant_reader_.ReadConstantExpression());
       param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                              constant);
     } else {
+      if (tag == kSomething) {
+        SkipExpression();  // Skip initializer.
+      }
       param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                              Object::null_instance());
     }
-    if (tag == kSomething) {
-      SkipExpression();  // read (actual) initializer.
-    }
 
     if (FLAG_enable_mirrors && (helper.annotation_count_ > 0)) {
       AlternativeReadingScope alt(&reader_, param_kernel_offset);
       VariableDeclarationHelper helper(this);
       helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
       Object& metadata =
-          Object::ZoneHandle(zone_, constant_evaluator_.EvaluateAnnotations());
+          Object::ZoneHandle(zone_, constant_reader_.ReadAnnotations());
       param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
                              metadata);
     } else {
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 6bf5371..d739365 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -19,7 +19,7 @@
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
 
 // Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 18;
+static const uint32_t kMinSupportedKernelFormatVersion = 29;
 static const uint32_t kMaxSupportedKernelFormatVersion = 36;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
@@ -128,7 +128,6 @@
   V(SimpleInterfaceType, 96)                                                   \
   V(SimpleFunctionType, 97)                                                    \
   V(ConstantExpression, 106)                                                   \
-  V(Deprecated_ConstantExpression, 107)                                        \
   V(SpecializedVariableGet, 128)                                               \
   V(SpecializedVariableSet, 136)                                               \
   V(SpecializedIntLiteral, 144)
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 28d4ffe..3b955ff 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -8,7 +8,7 @@
 
 #include <memory>
 
-#include "vm/compiler/frontend/constant_evaluator.h"
+#include "vm/compiler/frontend/constant_reader.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/dart_api_impl.h"
 #include "vm/flags.h"
@@ -157,9 +157,7 @@
   class_index_offset_ = procedure_index_offset_ - 4 - (class_count_ + 1) * 4;
 
   source_references_offset_ = -1;
-  if (binary_version >= 25) {
-    source_references_offset_ = reader_.ReadUInt32At(class_index_offset_ - 4);
-  }
+  source_references_offset_ = reader_.ReadUInt32At(class_index_offset_ - 4);
 }
 
 ClassIndex::ClassIndex(const uint8_t* buffer,
@@ -502,8 +500,7 @@
   if (length == 0) return;
 
   // Prepare lazy constant reading.
-  ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
-                                       &active_class_);
+  ConstantReader constant_reader(&helper_, &active_class_);
 
   // Obtain `dart:_internal::ExternalName.name`.
   EnsureExternalClassIsLookedUp();
@@ -526,20 +523,17 @@
     const intptr_t annotation_count = helper_.ReadListLength();
     for (intptr_t j = 0; j < annotation_count; ++j) {
       const intptr_t tag = helper_.PeekTag();
-      if (tag == kConstantExpression || tag == kDeprecated_ConstantExpression) {
+      if (tag == kConstantExpression) {
         helper_.ReadByte();  // Skip the tag.
+        helper_.ReadPosition();  // Skip fileOffset.
+        helper_.SkipDartType();  // Skip type.
 
         // We have a candidate. Let's look if it's an instance of the
         // ExternalName class.
-        if (tag == kConstantExpression) {
-          helper_.ReadPosition();  // Skip fileOffset.
-          helper_.SkipDartType();  // Skip type.
-        }
         const intptr_t constant_table_offset = helper_.ReadUInt();
-        if (constant_evaluator.IsInstanceConstant(constant_table_offset,
-                                                  external_name_class_)) {
-          constant = constant_evaluator.EvaluateConstantExpression(
-              constant_table_offset);
+        if (constant_reader.IsInstanceConstant(constant_table_offset,
+                                               external_name_class_)) {
+          constant = constant_reader.ReadConstant(constant_table_offset);
           ASSERT(constant.clazz() == external_name_class_.raw());
           // We found the annotation, let's flag the function as native and
           // set the native name!
@@ -623,8 +617,7 @@
   }
 
   // Prepare lazy constant reading.
-  ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
-                                       &active_class_);
+  ConstantReader constant_reader(&helper_, &active_class_);
 
   // Obtain `dart:_internal::ExternalName.name`.
   EnsureExternalClassIsLookedUp();
@@ -661,21 +654,17 @@
         uri_path = String::null();
 
         const intptr_t tag = helper_.PeekTag();
-        if (tag == kConstantExpression ||
-            tag == kDeprecated_ConstantExpression) {
+        if (tag == kConstantExpression) {
           helper_.ReadByte();  // Skip the tag.
+          helper_.ReadPosition();  // Skip fileOffset.
+          helper_.SkipDartType();  // Skip type.
 
           // We have a candidate. Let's look if it's an instance of the
           // ExternalName class.
-          if (tag == kConstantExpression) {
-            helper_.ReadPosition();  // Skip fileOffset.
-            helper_.SkipDartType();  // Skip type.
-          }
           const intptr_t constant_table_offset = helper_.ReadUInt();
-          if (constant_evaluator.IsInstanceConstant(constant_table_offset,
-                                                    external_name_class_)) {
-            constant = constant_evaluator.EvaluateConstantExpression(
-                constant_table_offset);
+          if (constant_reader.IsInstanceConstant(constant_table_offset,
+                                                 external_name_class_)) {
+            constant = constant_reader.ReadConstant(constant_table_offset);
             ASSERT(constant.clazz() == external_name_class_.raw());
             uri_path ^= constant.GetField(external_name_field_);
           }
@@ -963,11 +952,11 @@
     const bool has_simple_initializer =
         converter.IsSimple(helper_.ReaderOffset() + 1);
     if (!has_simple_initializer || !converter.SimpleValue().IsNull()) {
-      field.set_has_initializer(true);
+      field.set_has_nontrivial_initializer(true);
       return;
     }
   }
-  field.set_has_initializer(false);
+  field.set_has_nontrivial_initializer(false);
 }
 
 RawLibrary* KernelLoader::LoadLibrary(intptr_t index) {
@@ -1101,17 +1090,15 @@
   }
 
   if (register_class) {
-    if (library_index.HasSourceReferences()) {
-      helper_.SetOffset(library_index.SourceReferencesOffset());
-      intptr_t count = helper_.ReadUInt();
-      const GrowableObjectArray& owned_scripts =
-          GrowableObjectArray::Handle(library.owned_scripts());
-      Script& script = Script::Handle(Z);
-      for (intptr_t i = 0; i < count; i++) {
-        intptr_t uri_index = helper_.ReadUInt();
-        script = ScriptAt(uri_index);
-        owned_scripts.Add(script);
-      }
+    helper_.SetOffset(library_index.SourceReferencesOffset());
+    intptr_t count = helper_.ReadUInt();
+    const GrowableObjectArray& owned_scripts =
+        GrowableObjectArray::Handle(library.owned_scripts());
+    Script& script = Script::Handle(Z);
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t uri_index = helper_.ReadUInt();
+      script = ScriptAt(uri_index);
+      owned_scripts.Add(script);
     }
   }
   if (!library.Loaded()) library.SetLoaded();
@@ -1785,8 +1772,7 @@
       if (DetectPragmaCtor()) {
         *has_pragma_annotation = true;
       }
-    } else if (tag == kConstantExpression ||
-               tag == kDeprecated_ConstantExpression) {
+    } else if (tag == kConstantExpression) {
       const Array& constant_table_array =
           Array::Handle(kernel_program_info_.constants());
       if (constant_table_array.IsNull()) {
@@ -1807,11 +1793,8 @@
         // and avoid the "potential natives" list.
 
         helper_.ReadByte();  // Skip the tag.
-
-        if (tag == kConstantExpression) {
-          helper_.ReadPosition();  // Skip fileOffset.
-          helper_.SkipDartType();  // Skip type.
-        }
+        helper_.ReadPosition();  // Skip fileOffset.
+        helper_.SkipDartType();  // Skip type.
         const intptr_t offset_in_constant_table = helper_.ReadUInt();
 
         AlternativeReadingScopeWithNewData scope(
@@ -1836,8 +1819,7 @@
         const dart::Class& toplevel_class =
             Class::Handle(Z, library.toplevel_class());
         ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
-        ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
-                                             &active_class_);
+        ConstantReader constant_reader(&helper_, &active_class_);
 
         helper_.ReadByte();  // Skip the tag.
 
@@ -1854,14 +1836,13 @@
         const intptr_t constant_table_offset = helper_.ReadUInt();
         // We have a candidate. Let's look if it's an instance of the
         // ExternalName or Pragma class.
-        if (constant_evaluator.IsInstanceConstant(constant_table_offset,
-                                                  external_name_class_)) {
-          constant = constant_evaluator.EvaluateConstantExpression(
-              constant_table_offset);
+        if (constant_reader.IsInstanceConstant(constant_table_offset,
+                                               external_name_class_)) {
+          constant = constant_reader.ReadConstant(constant_table_offset);
           ASSERT(constant.clazz() == external_name_class_.raw());
           *native_name ^= constant.GetField(external_name_field_);
-        } else if (constant_evaluator.IsInstanceConstant(constant_table_offset,
-                                                         pragma_class_)) {
+        } else if (constant_reader.IsInstanceConstant(constant_table_offset,
+                                                      pragma_class_)) {
           *has_pragma_annotation = true;
         }
       }
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index cf01099..a6f3c75 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -107,11 +107,6 @@
     return -1;
   }
 
-  bool HasSourceReferences() {
-    if (binary_version_ < 25) return false;
-    return true;
-  }
-
   intptr_t SourceReferencesOffset() { return source_references_offset_; }
 
  private:
@@ -283,10 +278,8 @@
     // Start reading library.
     // Note that this needs to be keep in sync with LibraryHelper.
     reader.ReadFlags();
-    if (program_->binary_version() >= 27) {
-      reader.ReadUInt();  // Read major language version.
-      reader.ReadUInt();  // Read minor language version.
-    }
+    reader.ReadUInt();  // Read major language version.
+    reader.ReadUInt();  // Read minor language version.
     return reader.ReadCanonicalNameReference();
   }
 
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index d945b97..4b37bc0 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -70,7 +70,6 @@
       task_running_(false),
       delete_me_(false),
       pool_(NULL),
-      idle_start_time_(0),
       start_callback_(NULL),
       end_callback_(NULL),
       callback_data_(0) {
@@ -202,6 +201,9 @@
   StartIsolateScope start_isolate(isolate());
   ml->Enter();
 
+  auto idle_time_handler =
+      isolate() != nullptr ? isolate()->idle_time_handler() : nullptr;
+
   MessageStatus max_status = kOK;
   Message::Priority min_priority =
       ((allow_normal_messages && !paused()) ? Message::kNormalPriority
@@ -224,7 +226,11 @@
     ml->Exit();
     Message::Priority saved_priority = message->priority();
     Dart_Port saved_dest_port = message->dest_port();
-    MessageStatus status = HandleMessage(std::move(message));
+    MessageStatus status = kOK;
+    {
+      DisableIdleTimerScope disable_idle_timer(idle_time_handler);
+      status = HandleMessage(std::move(message));
+    }
     if (status > max_status) {
       max_status = status;
     }
@@ -248,7 +254,9 @@
     // using Observatory doesn't trigger additional idle tasks.
     if ((FLAG_idle_timeout_micros != 0) &&
         (saved_priority == Message::kNormalPriority)) {
-      idle_start_time_ = OS::GetCurrentMonotonicMicros();
+      if (idle_time_handler != nullptr) {
+        idle_time_handler->UpdateStartIdleTime();
+      }
     }
 
     // Some callers want to process only one normal message and then quit. At
@@ -514,44 +522,40 @@
 }
 
 bool MessageHandler::CheckIfIdleLocked(MonitorLocker* ml) {
-  if ((isolate() == NULL) || (idle_start_time_ == 0) ||
-      (FLAG_idle_timeout_micros == 0)) {
+  if (isolate() == nullptr ||
+      !isolate()->idle_time_handler()->ShouldCheckForIdle()) {
     // No idle task to schedule.
     return false;
   }
-  const int64_t now = OS::GetCurrentMonotonicMicros();
-  const int64_t idle_expirary = idle_start_time_ + FLAG_idle_timeout_micros;
-  if (idle_expirary > now) {
-    // We wait here for the scheduled idle time to expire or
-    // new messages or OOB messages to arrive.
-    paused_for_messages_ = true;
-    ml->WaitMicros(idle_expirary - now);
-    paused_for_messages_ = false;
-    // We want to loop back in order to handle the new messages
-    // or run the idle task.
+  int64_t idle_expirary = 0;
+  if (isolate()->idle_time_handler()->ShouldNotifyIdle(&idle_expirary)) {
+    // We've been without a message long enough to hope we can do some
+    // cleanup before the next message arrives.
+    RunIdleTaskLocked(ml);
+    // We may have received new messages while running idle task, so return
+    // true so that the handle messages loop is run again.
     return true;
   }
-  // The idle task can be scheduled immediately.
-  RunIdleTaskLocked(ml);
-  // We may have received new messages while running idle task, so return
-  // true so that the handle messages loop is run again.
+
+  // We wait here for the scheduled idle time to expire or
+  // new messages or OOB messages to arrive.
+  paused_for_messages_ = true;
+  ml->WaitMicros(idle_expirary - OS::GetCurrentMonotonicMicros());
+  paused_for_messages_ = false;
+  // We want to loop back in order to handle the new messages
+  // or run the idle task.
   return true;
 }
 
 void MessageHandler::RunIdleTaskLocked(MonitorLocker* ml) {
-  // We've been without a message long enough to hope we can do some
-  // cleanup before the next message arrives.
-  const int64_t now = OS::GetCurrentMonotonicMicros();
-  const int64_t deadline = now + FLAG_idle_duration_micros;
   // Idle tasks may take a while: don't block other isolates sending
   // us messages.
   ml->Exit();
   {
     StartIsolateScope start_isolate(isolate());
-    isolate()->NotifyIdle(deadline);
+    isolate()->idle_time_handler()->NotifyIdleUsingDefaultDeadline();
   }
   ml->Enter();
-  idle_start_time_ = 0;
 }
 
 void MessageHandler::ClosePort(Dart_Port port) {
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 46a7c19..133f8bf 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -260,7 +260,6 @@
   bool task_running_;
   bool delete_me_;
   ThreadPool* pool_;
-  int64_t idle_start_time_;
   StartCallback start_callback_;
   EndCallback end_callback_;
   CallbackData callback_data_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 6087194..faf1184 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -8233,7 +8233,7 @@
     return true;
   }
 
-  if (KernelIsolate::GetExperimentalFlag("non-nullable")) {
+  if (Dart::non_nullable_flag()) {
     // The non-nullable experiment changes the fingerprints, and we only track
     // one fingerprint set.
     return true;
@@ -8698,6 +8698,7 @@
   result.set_owner(owner);
   result.set_token_pos(token_pos);
   result.set_end_token_pos(end_token_pos);
+  result.set_has_nontrivial_initializer(false);
   result.set_has_initializer(false);
   result.set_is_unboxing_candidate(!is_final);
   result.set_initializer_changed_after_initialization(false);
@@ -8950,7 +8951,7 @@
 }
 
 RawFunction* Field::EnsureInitializerFunction() const {
-  ASSERT(has_initializer());
+  ASSERT(has_nontrivial_initializer());
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Function& initializer = Function::Handle(zone, InitializerFunction());
@@ -8979,7 +8980,7 @@
   ASSERT(is_instance());
   ASSERT(instance.GetField(*this) == Object::sentinel().raw());
   Object& value = Object::Handle();
-  if (has_initializer()) {
+  if (has_nontrivial_initializer()) {
     const Function& initializer = Function::Handle(EnsureInitializerFunction());
     const Array& args = Array::Handle(Array::New(1));
     args.SetAt(0, instance);
@@ -10684,14 +10685,9 @@
   // We compute the list of loaded scripts lazily. The result is
   // cached in loaded_scripts_.
   if (loaded_scripts() == Array::null()) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-    // TODO(jensj): Once minimum kernel support is >= 25 this can be cleaned up.
+    // TODO(jensj): This can be cleaned up.
     // It really should just return the content of `owned_scripts`, and there
     // should be no need to do the O(n) call to `AddScriptIfUnique` per script.
-    static_assert(
-        kernel::kMinSupportedKernelFormatVersion < 25,
-        "Once minimum kernel support is >= 25 this can be cleaned up.");
-#endif
 
     // Iterate over the library dictionary and collect all scripts.
     const GrowableObjectArray& scripts =
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index f64b4b0..4f9f92b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3616,6 +3616,17 @@
 
   RawString* InitializingExpression() const;
 
+  bool has_nontrivial_initializer() const {
+    return HasNontrivialInitializerBit::decode(raw_ptr()->kind_bits_);
+  }
+  // Called by parser after allocating field.
+  void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
+    ASSERT(IsOriginal());
+    ASSERT(Thread::Current()->IsMutatorThread());
+    set_kind_bits(HasNontrivialInitializerBit::update(
+        has_nontrivial_initializer, raw_ptr()->kind_bits_));
+  }
+
   bool has_initializer() const {
     return HasInitializerBit::decode(raw_ptr()->kind_bits_);
   }
@@ -3627,6 +3638,10 @@
         HasInitializerBit::update(has_initializer, raw_ptr()->kind_bits_));
   }
 
+  bool has_trivial_initializer() const {
+    return has_initializer() && !has_nontrivial_initializer();
+  }
+
   StaticTypeExactnessState static_type_exactness_state() const {
     return StaticTypeExactnessState::Decode(
         raw_ptr()->static_type_exactness_state_);
@@ -3820,7 +3835,7 @@
     kConstBit = 0,
     kStaticBit,
     kFinalBit,
-    kHasInitializerBit,
+    kHasNontrivialInitializerBit,
     kUnboxingCandidateBit,
     kReflectableBit,
     kDoubleInitializedBit,
@@ -3831,12 +3846,13 @@
     kIsLateBit,
     kIsExtensionMemberBit,
     kNeedsLoadGuardBit,
+    kHasInitializerBit,
   };
   class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
   class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
   class FinalBit : public BitField<uint16_t, bool, kFinalBit, 1> {};
-  class HasInitializerBit
-      : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
+  class HasNontrivialInitializerBit
+      : public BitField<uint16_t, bool, kHasNontrivialInitializerBit, 1> {};
   class UnboxingCandidateBit
       : public BitField<uint16_t, bool, kUnboxingCandidateBit, 1> {};
   class ReflectableBit : public BitField<uint16_t, bool, kReflectableBit, 1> {};
@@ -3856,6 +3872,8 @@
       : public BitField<uint16_t, bool, kIsExtensionMemberBit, 1> {};
   class NeedsLoadGuardBit
       : public BitField<uint16_t, bool, kNeedsLoadGuardBit, 1> {};
+  class HasInitializerBit
+      : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
 
   // Update guarded cid and guarded length for this field. Returns true, if
   // deoptimization of dependent code is required.
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 9b4e734..a86665c 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -461,29 +461,7 @@
   sample->Clear();
 }
 
-static void DumpStackFrame(intptr_t frame_index,
-                           uword pc,
-                           uword fp,
-                           bool try_symbolize_dart_frames) {
-  Thread* thread = Thread::Current();
-  if ((thread != NULL) && !thread->IsAtSafepoint() &&
-      try_symbolize_dart_frames) {
-    Isolate* isolate = thread->isolate();
-    if ((isolate != NULL) && isolate->is_runnable()) {
-      // Only attempt to symbolize Dart frames if we can safely iterate the
-      // current isolate's heap.
-      Code& code = Code::Handle(Code::LookupCodeInVmIsolate(pc));
-      if (code.IsNull()) {
-        code = Code::LookupCode(pc);  // In current isolate.
-      }
-      if (!code.IsNull()) {
-        OS::PrintErr("  pc 0x%" Pp " fp 0x%" Pp " %s\n", pc, fp,
-                     code.QualifiedName());
-        return;
-      }
-    }
-  }
-
+static void DumpStackFrame(intptr_t frame_index, uword pc, uword fp) {
   uintptr_t start = 0;
   char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start);
   if (native_symbol_name != NULL) {
@@ -511,16 +489,14 @@
   ProfilerStackWalker(Dart_Port port_id,
                       Sample* head_sample,
                       SampleBuffer* sample_buffer,
-                      intptr_t skip_count = 0,
-                      bool try_symbolize_dart_frames = true)
+                      intptr_t skip_count = 0)
       : port_id_(port_id),
         sample_(head_sample),
         sample_buffer_(sample_buffer),
         skip_count_(skip_count),
         frames_skipped_(0),
         frame_index_(0),
-        total_frames_(0),
-        try_symbolize_dart_frames_(try_symbolize_dart_frames) {
+        total_frames_(0) {
     if (sample_ == NULL) {
       ASSERT(sample_buffer_ == NULL);
     } else {
@@ -536,7 +512,7 @@
     }
 
     if (sample_ == NULL) {
-      DumpStackFrame(frame_index_, pc, fp, try_symbolize_dart_frames_);
+      DumpStackFrame(frame_index_, pc, fp);
       frame_index_++;
       total_frames_++;
       return true;
@@ -571,7 +547,6 @@
   intptr_t frames_skipped_;
   intptr_t frame_index_;
   intptr_t total_frames_;
-  const bool try_symbolize_dart_frames_;
 };
 
 // Executing Dart code, walk the stack.
@@ -768,13 +743,8 @@
                             uword pc,
                             uword fp,
                             uword sp,
-                            intptr_t skip_count = 0,
-                            bool try_symbolize_dart_frames = true)
-      : ProfilerStackWalker(port_id,
-                            sample,
-                            sample_buffer,
-                            skip_count,
-                            try_symbolize_dart_frames),
+                            intptr_t skip_count = 0)
+      : ProfilerStackWalker(port_id, sample, sample_buffer, skip_count),
         counters_(counters),
         stack_upper_(stack_upper),
         original_pc_(pc),
@@ -1190,13 +1160,19 @@
     return;
   }
 
-  ProfilerNativeStackWalker native_stack_walker(
-      &counters_, ILLEGAL_PORT, NULL, NULL, stack_lower, stack_upper, pc, fp,
-      sp,
-      /*skip_count=*/0,
-      /*try_symbolize_dart_frames=*/!for_crash);
+  ProfilerNativeStackWalker native_stack_walker(&counters_, ILLEGAL_PORT, NULL,
+                                                NULL, stack_lower, stack_upper,
+                                                pc, fp, sp,
+                                                /*skip_count=*/0);
   native_stack_walker.walk();
   OS::PrintErr("-- End of DumpStackTrace\n");
+
+  if (thread->execution_state() == Thread::kThreadInNative) {
+    TransitionNativeToVM transition(thread);
+    StackFrame::DumpCurrentTrace();
+  } else if (thread->execution_state() == Thread::kThreadInVM) {
+    StackFrame::DumpCurrentTrace();
+  }
 }
 
 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 2ebcd9e..fd2e3eb 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -88,8 +88,9 @@
 
   // Set all non object fields.
   type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
-  type.set_type_state(reader->Read<int8_t>());
-  type.set_nullability(static_cast<Nullability>(reader->Read<int8_t>()));
+  const uint8_t combined = reader->Read<uint8_t>();
+  type.set_type_state(combined >> 4);
+  type.set_nullability(static_cast<Nullability>(combined & 0xf));
 
   // Read the code object for the type testing stub and set its entrypoint.
   reader->EnqueueTypePostprocessing(type);
@@ -152,8 +153,10 @@
 
   // Write out all the non object pointer fields.
   writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
-  writer->Write<int8_t>(ptr()->type_state_);
-  writer->Write<int8_t>(ptr()->nullability_);
+  const uint8_t combined = (ptr()->type_state_ << 4) | ptr()->nullability_;
+  ASSERT(ptr()->type_state_ == (combined >> 4));
+  ASSERT(ptr()->nullability_ == (combined & 0xf));
+  writer->Write<uint8_t>(combined);
 
   // Write out all the object pointer fields.
   ASSERT(ptr()->type_class_id_ != Object::null());
@@ -224,9 +227,9 @@
   type_parameter.set_token_pos(
       TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
   type_parameter.set_index(reader->Read<int16_t>());
-  type_parameter.set_flags(reader->Read<uint8_t>());
-  type_parameter.set_nullability(
-      static_cast<Nullability>(reader->Read<int8_t>()));
+  const uint8_t combined = reader->Read<uint8_t>();
+  type_parameter.set_flags(combined >> 4);
+  type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
 
   // Read the code object for the type testing stub and set its entrypoint.
   reader->EnqueueTypePostprocessing(type_parameter);
@@ -267,8 +270,10 @@
   // Write out all the non object pointer fields.
   writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
   writer->Write<int16_t>(ptr()->index_);
-  writer->Write<uint8_t>(ptr()->flags_);
-  writer->Write<int8_t>(ptr()->nullability_);
+  const uint8_t combined = (ptr()->flags_ << 4) | ptr()->nullability_;
+  ASSERT(ptr()->flags_ == (combined >> 4));
+  ASSERT(ptr()->nullability_ == (combined & 0xf));
+  writer->Write<uint8_t>(combined);
 
   // Write out all the object pointer fields.
   SnapshotWriterVisitor visitor(writer, kAsReference);
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 260e99f..b2ad52a 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -532,6 +532,17 @@
   return (LookupDartCode() != Code::null());
 }
 
+void StackFrame::DumpCurrentTrace() {
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
+                            Thread::Current(),
+                            StackFrameIterator::kNoCrossThreadIteration);
+  StackFrame* frame = frames.NextFrame();
+  while (frame != nullptr) {
+    OS::PrintErr("%s\n", frame->ToCString());
+    frame = frames.NextFrame();
+  }
+}
+
 void StackFrameIterator::SetupLastExitFrameData() {
   ASSERT(thread_ != NULL);
   uword exit_marker = thread_->top_exit_frame_info();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 69368fe..72699ae 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -130,6 +130,8 @@
   // Returns token_pos of the pc(), or -1 if none exists.
   TokenPosition GetTokenPos() const;
 
+  static void DumpCurrentTrace();
+
  protected:
   explicit StackFrame(Thread* thread)
       : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 10c22d1..e9aa508 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -65,6 +65,7 @@
   V(Current, "current")                                                        \
   V(CurrentContextVar, ":current_context_var")                                 \
   V(CyclicInitializationError, "CyclicInitializationError")                    \
+  V(LateInitializationError, "_LateInitializationError")                       \
   V(DartCollection, "dart:collection")                                         \
   V(DartCore, "dart:core")                                                     \
   V(DartDeveloper, "dart:developer")                                           \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index c79be7b..2afc376 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -507,6 +507,7 @@
 RawError* Thread::HandleInterrupts() {
   uword interrupt_bits = GetAndClearInterrupts();
   if ((interrupt_bits & kVMInterrupt) != 0) {
+    CheckForSafepoint();
     if (isolate()->store_buffer()->Overflowed()) {
       if (FLAG_verbose_gc) {
         OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
diff --git a/samples/ffi/sqlite/README.md b/samples/ffi/sqlite/README.md
index 85a26dd..4f7c8eb 100644
--- a/samples/ffi/sqlite/README.md
+++ b/samples/ffi/sqlite/README.md
@@ -37,5 +37,5 @@
 ## Tutorial
 
 A tutorial walking through the code is available in [docs/sqlite-tutorial.md](docs/sqlite-tutorial.md).
-For information on how to use this package within a Flutter app, see [docs/android.md].
+For information on how to use this package within a Flutter app, see [docs/android.md](docs/android.md).
 (Note: iOS is not yet supported).
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 3101029..e637088 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -20,9 +20,12 @@
   # Build a SDK with less stuff. It excludes dart2js, ddc, and web libraries.
   dart_platform_sdk = true
 
+  # Whether to include dart2native in the "create_sdk" target.
+  include_dart2native = false
+
   # Path to stripped dart binaries relative to build output directory.
   dart_stripped_binary = "dart"
-  dartaotruntime_stripped_binary = "dartaotruntime"
+  dart_precompiled_runtime_stripped_binary = "dart_precompiled_runtime"
   gen_snapshot_stripped_binary = "gen_snapshot"
 }
 
@@ -35,11 +38,11 @@
 # ......dartaotruntime or dartaotruntime.exe (executable)
 # ......dartdoc
 # ......dartfmt
-# ......dart2native
+# ......dart2native (if `include_dart2native` and not on ia32)
 # ......dart2js
 # ......dartanalyzer
 # ......dartdevc
-# ......utils/gen_snapshot or utils/gen_snapshot.exe (executable)
+# ......utils/gen_snapshot or utils/gen_snapshot.exe (if `include_dart2native` and not on ia32)
 # ......pub
 # ......snapshots/
 # ........analysis_server.dart.snapshot
@@ -48,7 +51,8 @@
 # ........dartdoc.dart.snapshot
 # ........dartfmt.dart.snapshot
 # ........dartdevc.dart.snapshot
-# ........gen_kernel.dart.snapshot
+# ........gen_kernel.dart.snapshot (if `include_dart2native` and not on ia32)
+# ........dart2native.dart.snapshot (if `include_dart2native` and not on ia32)
 # ........kernel_worker.dart.snapshot
 # ........pub.dart.snapshot
 # ......resources/
@@ -117,10 +121,6 @@
     "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
   ],
   [
-    "dart2native",
-    "../utils/dart2native:generate_dart2native_snapshot",
-  ],
-  [
     "dartdoc",
     "../utils/dartdoc",
   ],
@@ -133,6 +133,12 @@
     "../utils/pub",
   ],
 ]
+if (include_dart2native && dart_target_arch != "ia32") {
+  _platform_sdk_snapshots += [ [
+        "dart2native",
+        "../utils/dart2native:generate_dart2native_snapshot",
+      ] ]
+}
 if (create_kernel_service_snapshot) {
   _platform_sdk_snapshots += [ [
         "kernel-service",
@@ -156,10 +162,6 @@
     "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
   ],
   [
-    "dart2native",
-    "../utils/dart2native:generate_dart2native_snapshot",
-  ],
-  [
     "dartdevc",
     "../utils/dartdevc",
   ],
@@ -180,6 +182,12 @@
     "../utils/pub",
   ],
 ]
+if (include_dart2native && dart_target_arch != "ia32") {
+  _full_sdk_snapshots += [ [
+        "dart2native",
+        "../utils/dart2native:generate_dart2native_snapshot",
+      ] ]
+}
 if (create_kernel_service_snapshot) {
   _full_sdk_snapshots += [ [
         "kernel-service",
@@ -314,17 +322,49 @@
       dest = "$root_out_dir/dart-sdk/bin/model"
       ignore_patterns = "{}"
     },
-    {
-      target = "copy_libtensorflowlite_c"
-      visibility = [ ":create_common_sdk" ]
-      deps = [
-        ":copy_libraries",
-      ]
-      source = "../third_party/pkg/tflite_native/lib/src/blobs"
-      dest = "$root_out_dir/dart-sdk/bin/snapshots"
-      ignore_patterns = "{}"
-    },
   ]
+  if (is_linux) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.dll,*mac64.so"
+      },
+    ]
+  }
+  if (is_mac) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.dll,*linux64.so"
+      },
+    ]
+  }
+  if (is_win) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.so"
+      },
+    ]
+  }
 }
 
 # This generates targets for everything in copy_tree_specs. The targets have the
@@ -394,25 +434,25 @@
 
 copy("copy_dartaotruntime") {
   deps = [
-    "../runtime/bin:dartaotruntime",
+    "../runtime/bin:dart_precompiled_runtime",
   ]
   dartaotruntime_out =
-      get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
+      get_label_info("../runtime/bin:dart_precompiled_runtime", "root_out_dir")
   if (is_win) {
     sources = [
-      "$dartaotruntime_out/dartaotruntime.exe",
+      "$dartaotruntime_out/dart_precompiled_runtime.exe",
+    ]
+    outputs = [
+      "$root_out_dir/dart-sdk/bin/dartaotruntime.exe",
     ]
   } else {
     sources = [
-      "$dartaotruntime_out/$dartaotruntime_stripped_binary",
+      "$dartaotruntime_out/$dart_precompiled_runtime_stripped_binary",
+    ]
+    outputs = [
+      "$root_out_dir/dart-sdk/bin/dartaotruntime",
     ]
   }
-  if (is_win) {
-    sources += [ "$dartaotruntime_out/dartaotruntime.lib" ]
-  }
-  outputs = [
-    "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
-  ]
 }
 
 copy("copy_gen_snapshot") {
@@ -437,6 +477,7 @@
 
 copy("copy_dart2native") {
   deps = [
+    ":copy_dartaotruntime",
     ":copy_gen_kernel_snapshot",
     ":copy_gen_snapshot",
   ]
@@ -987,7 +1028,6 @@
     ":copy_analysis_summaries",
     ":copy_api_readme",
     ":copy_dart",
-    ":copy_dart2native",
     ":copy_dartdoc_files",
     ":copy_headers",
     ":copy_libraries_dart",
@@ -999,6 +1039,13 @@
     ":write_revision_file",
     ":write_version_file",
   ]
+
+  # We do not support AOT on ia32 and should therefore not add the
+  # dart2native script (since there is no AOT compiler/runtime available)
+  if (include_dart2native && dart_target_arch != "ia32") {
+    public_deps += [ ":copy_dart2native" ]
+  }
+
   if (is_win) {
     public_deps += [ ":copy_7zip" ]
   }
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index 0a5e478..d452315 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -104,6 +104,7 @@
   }
 
   void noFolding(String name) {
+    name = _validateField(name);
     if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>();
     _noFoldingHeaders.add(name);
   }
diff --git a/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
index 4b9fdb0..d0377bb 100644
--- a/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
@@ -11,6 +11,8 @@
 
 import 'dart:_foreign_helper' show JS;
 import 'dart:collection' show HashMap;
+import 'dart:async' show Completer;
+import 'dart:_js_helper' show convertDartClosureToJS;
 
 /// WARNING: performance of this method is much worse than other uitil
 /// methods in this library. Only use this method as a last resort.
@@ -124,3 +126,23 @@
   //         []..addAll(arguments.map(_convertToJS)));
   //     return _wrapToDart(jsObj);
 }
+
+/// Converts a JavaScript Promise to a Dart [Future].
+///
+/// ```dart
+/// @JS()
+/// external Promise<num> get threePromise; // Resolves to 3
+///
+/// final Future<num> threeFuture = promiseToFuture(threePromise);
+///
+/// final three = await threeFuture; // == 3
+/// ```
+Future<T> promiseToFuture<T>(jsPromise) {
+  final completer = Completer<T>();
+
+  final success = convertDartClosureToJS((r) => completer.complete(r), 1);
+  final error = convertDartClosureToJS((e) => completer.completeError(e), 1);
+
+  JS('', '#.then(#, #)', jsPromise, success, error);
+  return completer.future;
+}
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 43e0f08..a52e489 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -20,7 +20,7 @@
         quoteStringForRegExp,
         undefined;
 import 'dart:_runtime' as dart;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JSExportName;
 import 'dart:_native_typed_data' show NativeUint8List;
 import 'dart:collection' show UnmodifiableMapView;
 import 'dart:convert' show Encoding, utf8;
@@ -63,12 +63,39 @@
 
   @patch
   Type get runtimeType => dart.wrapType(dart.getReifiedType(this));
+
+  // Everything is an Object.
+  @JSExportName('is')
+  static bool _is_Object(Object o) => true;
+
+  @JSExportName('as')
+  static Object _as_Object(Object o) => o;
+
+  @JSExportName('_check')
+  static Object _check_Object(Object o) => o;
 }
 
 @patch
 class Null {
   @patch
   int get hashCode => super.hashCode;
+
+  @JSExportName('is')
+  static bool _is_Null(Object o) => o == null;
+
+  @JSExportName('as')
+  static Object _as_Null(Object o) {
+    // Avoid extra function call to core.Null.is() by manually inlining.
+    if (o == null) return o;
+    return dart.cast(o, dart.unwrapType(Null), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_Null(Object o) {
+    // Avoid extra function call to core.Null.is() by manually inlining.
+    if (o == null) return o;
+    return dart.cast(o, dart.unwrapType(Null), true);
+  }
 }
 
 // Patch for Function implementation.
@@ -97,6 +124,24 @@
     });
     return result;
   }
+
+  @JSExportName('is')
+  static bool _is_Function(Object o) =>
+      JS<bool>('!', 'typeof $o == "function"');
+
+  @JSExportName('as')
+  static Object _as_Function(Object o) {
+    // Avoid extra function call to core.Function.is() by manually inlining.
+    if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(Function), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_Function(Object o) {
+    // Avoid extra function call to core.Function.is() by manually inlining.
+    if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(Function), true);
+  }
 }
 
 // TODO(jmesserly): switch to WeakMap
@@ -157,6 +202,31 @@
     throw UnsupportedError(
         'int.fromEnvironment can only be used as a const constructor');
   }
+
+  @JSExportName('is')
+  static bool _is_int(Object o) {
+    return JS<bool>('!', 'typeof $o == "number" && Math.floor($o) == $o');
+  }
+
+  @JSExportName('as')
+  static Object _as_int(Object o) {
+    // Avoid extra function call to core.int.is() by manually inlining.
+    if (JS<bool>('!', '(typeof $o == "number" && Math.floor($o) == $o)') ||
+        o == null) {
+      return o;
+    }
+    return dart.cast(o, dart.unwrapType(int), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_int(Object o) {
+    // Avoid extra function call to core.int.is() by manually inlining.
+    if (JS<bool>('!', '(typeof $o == "number" && Math.floor($o) == $o)') ||
+        o == null) {
+      return o;
+    }
+    return dart.cast(o, dart.unwrapType(int), true);
+  }
 }
 
 @patch
@@ -171,6 +241,47 @@
   static double tryParse(String source) {
     return Primitives.parseDouble(source, _kNull);
   }
+
+  @JSExportName('is')
+  static bool _is_double(o) {
+    return JS<bool>('!', 'typeof $o == "number"');
+  }
+
+  @JSExportName('as')
+  static Object _as_double(o) {
+    // Avoid extra function call to core.double.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(double), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_double(o) {
+    // Avoid extra function call to core.double.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(double), true);
+  }
+}
+
+@patch
+abstract class num implements Comparable<num> {
+  @JSExportName('is')
+  static bool _is_num(o) {
+    return JS<bool>('!', 'typeof $o == "number"');
+  }
+
+  @JSExportName('as')
+  static Object _as_num(o) {
+    // Avoid extra function call to core.num.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(num), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_num(o) {
+    // Avoid extra function call to core.num.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(num), true);
+  }
 }
 
 @patch
@@ -528,6 +639,25 @@
     }
     return Primitives.stringFromCharCodes(list);
   }
+
+  @JSExportName('is')
+  static bool _is_String(Object o) {
+    return JS<bool>('!', 'typeof $o == "string"');
+  }
+
+  @JSExportName('as')
+  static Object _as_String(Object o) {
+    // Avoid extra function call to core.String.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "string"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(String), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_String(Object o) {
+    // Avoid extra function call to core.String.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "string"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(String), true);
+  }
 }
 
 @patch
@@ -541,6 +671,24 @@
 
   @patch
   int get hashCode => super.hashCode;
+
+  @JSExportName('is')
+  static bool _is_bool(Object o) =>
+      JS<bool>('!', '$o === true || $o === false');
+
+  @JSExportName('as')
+  static Object _as_bool(Object o) {
+    // Avoid extra function call to core.bool.is() by manually inlining.
+    if (JS<bool>("!", '$o === true || $o === false') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(bool), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_bool(Object o) {
+    // Avoid extra function call to core.bool.is() by manually inlining.
+    if (JS<bool>("!", '$o === true || $o === false') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(bool), true);
+  }
 }
 
 @patch
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index b0300d5..5a8d3b9 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -22,7 +22,13 @@
 import 'dart:_js_names' show unmangleGlobalNameIfPreservedAnyways;
 
 import 'dart:_js_embedded_names'
-    show JsBuiltin, JsGetName, RtiUniverseFieldNames, RTI_UNIVERSE, TYPES;
+    show
+        JsBuiltin,
+        JsGetName,
+        RtiUniverseFieldNames,
+        CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME,
+        RTI_UNIVERSE,
+        TYPES;
 
 import 'dart:_recipe_syntax';
 
@@ -103,6 +109,18 @@
     rti._precomputed1 = precomputed;
   }
 
+  // Data value used by some tests.
+  @pragma('dart2js:noElision')
+  Object _specializedTestResource;
+
+  static Object _getSpecializedTestResource(Rti rti) {
+    return rti._specializedTestResource;
+  }
+
+  static void _setSpecializedTestResource(Rti rti, Object value) {
+    rti._specializedTestResource = value;
+  }
+
   // The Type object corresponding to this Rti.
   Object _cachedRuntimeType;
   static _Type _getCachedRuntimeType(Rti rti) =>
@@ -543,10 +561,14 @@
   return result;
 }
 
+bool _isDartObject(object) => _Utils.instanceOf(object,
+    JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartObjectConstructor));
+
 bool _isClosure(object) => _Utils.instanceOf(object,
     JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartClosureConstructor));
 
-/// Returns the structural function [Rti] of [closure].
+/// Returns the structural function [Rti] of [closure], or `null`.
+/// [closure] must be a subclass of [Closure].
 /// Called from generated code.
 Rti closureFunctionType(closure) {
   var signatureName = JS_GET_NAME(JsGetName.SIGNATURE_NAME);
@@ -560,19 +582,6 @@
   return null;
 }
 
-// Subclasses of Closure are synthetic classes. The synthetic classes all
-// extend a 'normal' class (Closure, BoundClosure, StaticClosure), so make
-// them appear to be the superclass.
-// TODO(sra): Can this be done less expensively, e.g. by putting $ti on the
-// prototype of Closure/BoundClosure/StaticClosure classes?
-Rti _closureInterfaceType(closure) {
-  var rti = JS('', r'#[#]', closure, JS_GET_NAME(JsGetName.RTI_NAME));
-  return rti != null
-      ? _castToRti(rti)
-      : _instanceTypeFromConstructor(
-          JS('', '#.__proto__.__proto__.constructor', closure));
-}
-
 /// Returns the Rti type of [object]. Closures have both an interface type
 /// (Closures implement `Function`) and a structural function type. Uses
 /// [testRti] to choose the appropriate type.
@@ -592,23 +601,18 @@
 }
 
 /// Returns the Rti type of [object].
+/// This is the general entry for obtaining the interface type of any value.
 /// Called from generated code.
 Rti instanceType(object) {
-  if (_isClosure(object)) return _closureInterfaceType(object);
-  return _nonClosureInstanceType(object);
-}
+  // TODO(sra): Add interceptor-based specializations of this method. Inject a
+  // _getRti method into (Dart)Object, JSArray, and Interceptor. Then calls to
+  // this method can be generated as `getInterceptor(o)._getRti(o)`, allowing
+  // interceptor optimizations to select the specialization. If the only use of
+  // `getInterceptor` is for calling `_getRti`, then `instanceType` can be
+  // called, similar to a one-shot interceptor call. This would improve type
+  // lookup in ListMixin code as the interceptor is JavaScript 'this'.
 
-Rti _nonClosureInstanceType(object) {
-  // TODO(sra): Add specializations of this method. One possible way is to
-  // arrange that the interceptor has a _getType method that is injected into
-  // DartObject, Interceptor and JSArray. Then this method can be replaced-by
-  // `getInterceptor(o)._getType(o)`, allowing interceptor optimizations to
-  // select the specialization.
-
-  if (_Utils.instanceOf(
-      object,
-      JS_BUILTIN(
-          'depends:none;effects:none;', JsBuiltin.dartObjectConstructor))) {
+  if (_isDartObject(object)) {
     return _instanceType(object);
   }
 
@@ -617,7 +621,7 @@
   }
 
   var interceptor = getInterceptor(object);
-  return _instanceTypeFromConstructor(JS('', '#.constructor', interceptor));
+  return _instanceTypeFromConstructor(interceptor);
 }
 
 /// Returns the Rti type of JavaScript Array [object].
@@ -636,9 +640,7 @@
 /// Called from generated code.
 Rti _instanceType(object) {
   var rti = JS('', r'#[#]', object, JS_GET_NAME(JsGetName.RTI_NAME));
-  return rti != null
-      ? _castToRti(rti)
-      : _instanceTypeFromConstructor(JS('', '#.constructor', object));
+  return rti != null ? _castToRti(rti) : _instanceTypeFromConstructor(object);
 }
 
 String instanceTypeName(object) {
@@ -646,10 +648,32 @@
   return _rtiToString(rti, null);
 }
 
-Rti _instanceTypeFromConstructor(constructor) {
-  // TODO(sra): Cache Rti on constructor.
-  return _Universe.findErasedType(
-      _theUniverse(), JS('String', '#.name', constructor));
+Rti _instanceTypeFromConstructor(instance) {
+  var constructor = JS('', '#.constructor', instance);
+  var probe = JS('', r'#[#]', constructor, CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME);
+  if (probe != null) return _castToRti(probe);
+  return _instanceTypeFromConstructorMiss(instance, constructor);
+}
+
+@pragma('dart2js:noInline')
+Rti _instanceTypeFromConstructorMiss(instance, constructor) {
+  // Subclasses of Closure are synthetic classes. The synthetic classes all
+  // extend a 'normal' class (Closure, BoundClosure, StaticClosure), so make
+  // them appear to be the superclass. Instantiations have a `$ti` field so
+  // don't reach here.
+  //
+  // TODO(39214): This will need fixing if we ever use instances of
+  // StaticClosure for static tear-offs.
+  //
+  // TODO(sra): Can this test be avoided, e.g. by putting $ti on the
+  // prototype of Closure/BoundClosure/StaticClosure classes?
+  var effectiveConstructor = _isClosure(instance)
+      ? JS('', '#.__proto__.__proto__.constructor', instance)
+      : constructor;
+  Rti rti = _Universe.findErasedType(
+      _theUniverse(), JS('String', '#.name', effectiveConstructor));
+  JS('', r'#[#] = #', constructor, CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME, rti);
+  return rti;
 }
 
 /// Returns the structural function type of [object], or `null` if the object is
@@ -672,7 +696,7 @@
 }
 
 Type getRuntimeType(object) {
-  Rti rti = _instanceFunctionType(object) ?? _nonClosureInstanceType(object);
+  Rti rti = _instanceFunctionType(object) ?? instanceType(object);
   return createRuntimeType(rti);
 }
 
@@ -750,6 +774,16 @@
       isFn = RAW_DART_FUNCTION_REF(_isString);
     } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
       isFn = RAW_DART_FUNCTION_REF(_isBool);
+    } else {
+      String name = Rti._getInterfaceName(testRti);
+      var arguments = Rti._getInterfaceTypeArguments(testRti);
+      if (JS(
+          'bool', '#.every(#)', arguments, RAW_DART_FUNCTION_REF(isTopType))) {
+        String propertyName =
+            '${JS_GET_NAME(JsGetName.OPERATOR_IS_PREFIX)}${name}';
+        Rti._setSpecializedTestResource(testRti, propertyName);
+        isFn = RAW_DART_FUNCTION_REF(_isTestViaProperty);
+      }
     }
   }
 
@@ -767,6 +801,24 @@
 }
 
 /// Called from generated code.
+bool _isTestViaProperty(object) {
+  // This static method is installed on an Rti object as a JavaScript instance
+  // method. The Rti object is 'this'.
+  Rti testRti = _castToRti(JS('', 'this'));
+  var tag = Rti._getSpecializedTestResource(testRti);
+
+  // This test is redundant with getInterceptor below, but getInterceptor does
+  // the tests in the wrong order for most tags, so it is usually faster to have
+  // this check.
+  if (_isDartObject(object)) {
+    return JS('bool', '!!#[#]', object, tag);
+  }
+
+  var interceptor = getInterceptor(object);
+  return JS('bool', '!!#[#]', interceptor, tag);
+}
+
+/// Called from generated code.
 _generalAsCheckImplementation(object) {
   if (object == null) return object;
   // This static method is installed on an Rti object as a JavaScript instance
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index 66cba17..8456b8b 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -47,6 +47,10 @@
 /// the static function's unique (potentially minified) name.
 const STATIC_FUNCTION_NAME_PROPERTY_NAME = r'$static_name';
 
+/// The name of a property on the constructor function of Dart Object
+/// and interceptor types, used for caching Rti types.
+const CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME = r'$ccache';
+
 /// The name of the embedded global for metadata.
 ///
 /// Use [JsBuiltin.getMetadata] instead of directly accessing this embedded
diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
index 1e61ce6..a8cb80c 100644
--- a/sdk/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/errors_patch.dart
@@ -588,3 +588,17 @@
 
   toString() => "Error: field '$_name' is already initialized.";
 }
+
+class _LateInitializationError extends Error
+    implements LateInitializationError {
+  _LateInitializationError(this._name);
+
+  @pragma("vm:entry-point")
+  static void _throwNew(String name) {
+    throw _LateInitializationError(name);
+  }
+
+  String toString() => "LateInitializationError: $_name";
+
+  final String _name;
+}
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 53f3d35..298083d 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -586,3 +586,8 @@
       ? "Reading static variable during its initialization"
       : "Reading static variable '$variableName' during its initialization";
 }
+
+/**
+ * Error thrown when a late field is set or get when it shouldn't be.
+ */
+class LateInitializationError extends Error {}
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index a47ebdf..f072a7c 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -5,8 +5,7 @@
 /**
  * Foreign Function Interface for interoperability with the C programming language.
  *
- * **NOTE**: Dart:FFI is in technical preview. The overall feature is incomplete,
- * may contain issues, and breaking API changes are still expected.
+ * **NOTE**: Dart:FFI is in beta, and breaking API changes might still happen.
  *
  * For further details, please see: https://dart.dev/server/c-interop
  *
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index 625bb31..21ab9ae 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -98,14 +98,6 @@
 bool isJavaScriptPromise(value) =>
     JS('bool', r'typeof Promise != "undefined" && # instanceof Promise', value);
 
-Future<T> promiseToFuture<T>(promise) {
-  var completer = new Completer<T>();
-  var then = convertDartClosureToJS((r) => completer.complete(r), 1);
-  var error = convertDartClosureToJS((e) => completer.completeError(e), 1);
-  JS('', '#.then(#, #)', promise, then, error);
-  return completer.future;
-}
-
 const String _serializedScriptValue = 'num|String|bool|'
     'JSExtendableArray|=Object|'
     'Blob|File|NativeByteBuffer|NativeTypedData|MessagePort'
diff --git a/sdk/lib/html/html_common/html_common_dart2js.dart b/sdk/lib/html/html_common/html_common_dart2js.dart
index de8d89e..3df2ccf 100644
--- a/sdk/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk/lib/html/html_common/html_common_dart2js.dart
@@ -15,6 +15,9 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_interceptors' show Interceptor, JSExtendableArray, JSObject;
 
+import 'dart:js_util' show promiseToFuture;
+export 'dart:js_util' show promiseToFuture;
+
 import 'dart:_metadata';
 export 'dart:_metadata';
 
diff --git a/sdk/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
index 6b605fb..2e731fb 100644
--- a/sdk/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
@@ -13,6 +13,8 @@
 
 import 'dart:_foreign_helper' show JS;
 import 'dart:collection' show HashMap;
+import 'dart:async' show Completer;
+import 'dart:_js_helper' show convertDartClosureToJS;
 
 /// WARNING: performance of this method is much worse than other util
 /// methods in this library. Only use this method as a last resort.
@@ -126,3 +128,23 @@
   //         []..addAll(arguments.map(_convertToJS)));
   //     return _wrapToDart(jsObj);
 }
+
+/// Converts a JavaScript Promise to a Dart [Future].
+///
+/// ```dart
+/// @JS()
+/// external Promise<num> get threePromise; // Resolves to 3
+///
+/// final Future<num> threeFuture = promiseToFuture(threePromise);
+///
+/// final three = await threeFuture; // == 3
+/// ```
+Future<T> promiseToFuture<T>(jsPromise) {
+  final completer = Completer<T>();
+
+  final success = convertDartClosureToJS((r) => completer.complete(r), 1);
+  final error = convertDartClosureToJS((e) => completer.completeError(e), 1);
+
+  JS('', '#.then(#, #)', jsPromise, success, error);
+  return completer.future;
+}
diff --git a/sdk_nnbd/BUILD.gn b/sdk_nnbd/BUILD.gn
index e352733..e637088 100644
--- a/sdk_nnbd/BUILD.gn
+++ b/sdk_nnbd/BUILD.gn
@@ -20,9 +20,12 @@
   # Build a SDK with less stuff. It excludes dart2js, ddc, and web libraries.
   dart_platform_sdk = true
 
+  # Whether to include dart2native in the "create_sdk" target.
+  include_dart2native = false
+
   # Path to stripped dart binaries relative to build output directory.
   dart_stripped_binary = "dart"
-  dartaotruntime_stripped_binary = "dartaotruntime"
+  dart_precompiled_runtime_stripped_binary = "dart_precompiled_runtime"
   gen_snapshot_stripped_binary = "gen_snapshot"
 }
 
@@ -35,11 +38,11 @@
 # ......dartaotruntime or dartaotruntime.exe (executable)
 # ......dartdoc
 # ......dartfmt
-# ......dart2native
+# ......dart2native (if `include_dart2native` and not on ia32)
 # ......dart2js
 # ......dartanalyzer
 # ......dartdevc
-# ......utils/gen_snapshot or utils/gen_snapshot.exe (executable)
+# ......utils/gen_snapshot or utils/gen_snapshot.exe (if `include_dart2native` and not on ia32)
 # ......pub
 # ......snapshots/
 # ........analysis_server.dart.snapshot
@@ -48,7 +51,8 @@
 # ........dartdoc.dart.snapshot
 # ........dartfmt.dart.snapshot
 # ........dartdevc.dart.snapshot
-# ........gen_kernel.dart.snapshot
+# ........gen_kernel.dart.snapshot (if `include_dart2native` and not on ia32)
+# ........dart2native.dart.snapshot (if `include_dart2native` and not on ia32)
 # ........kernel_worker.dart.snapshot
 # ........pub.dart.snapshot
 # ......resources/
@@ -68,13 +72,13 @@
 # ....lib/
 # ......libraries.json
 # ......_internal/
-#.........strong.sum
-#.........dart2js_platform.dill
-#.........dart2js_server_platform.dill
-#.........dart2js_platform_strong.dill
-#.........dart2js_server_platform_strong.dill
-#.........vm_platform_strong.dill
-#.........dev_compiler/
+# ........strong.sum
+# ........dart2js_platform.dill
+# ........dart2js_server_platform.dill
+# ........dart2js_platform_strong.dill
+# ........dart2js_server_platform_strong.dill
+# ........vm_platform_strong.dill
+# ........dev_compiler/
 # ......async/
 # ......collection/
 # ......convert/
@@ -117,10 +121,6 @@
     "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
   ],
   [
-    "dart2native",
-    "../utils/dart2native:generate_dart2native_snapshot",
-  ],
-  [
     "dartdoc",
     "../utils/dartdoc",
   ],
@@ -133,6 +133,12 @@
     "../utils/pub",
   ],
 ]
+if (include_dart2native && dart_target_arch != "ia32") {
+  _platform_sdk_snapshots += [ [
+        "dart2native",
+        "../utils/dart2native:generate_dart2native_snapshot",
+      ] ]
+}
 if (create_kernel_service_snapshot) {
   _platform_sdk_snapshots += [ [
         "kernel-service",
@@ -156,10 +162,6 @@
     "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
   ],
   [
-    "dart2native",
-    "../utils/dart2native:generate_dart2native_snapshot",
-  ],
-  [
     "dartdevc",
     "../utils/dartdevc",
   ],
@@ -180,6 +182,12 @@
     "../utils/pub",
   ],
 ]
+if (include_dart2native && dart_target_arch != "ia32") {
+  _full_sdk_snapshots += [ [
+        "dart2native",
+        "../utils/dart2native:generate_dart2native_snapshot",
+      ] ]
+}
 if (create_kernel_service_snapshot) {
   _full_sdk_snapshots += [ [
         "kernel-service",
@@ -314,17 +322,49 @@
       dest = "$root_out_dir/dart-sdk/bin/model"
       ignore_patterns = "{}"
     },
-    {
-      target = "copy_libtensorflowlite_c"
-      visibility = [ ":create_common_sdk" ]
-      deps = [
-        ":copy_libraries",
-      ]
-      source = "../third_party/pkg/tflite_native/lib/src/blobs"
-      dest = "$root_out_dir/dart-sdk/bin/snapshots"
-      ignore_patterns = "{}"
-    },
   ]
+  if (is_linux) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.dll,*mac64.so"
+      },
+    ]
+  }
+  if (is_mac) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.dll,*linux64.so"
+      },
+    ]
+  }
+  if (is_win) {
+    copy_tree_specs += [
+      {
+        target = "copy_libtensorflowlite_c"
+        visibility = [ ":create_common_sdk" ]
+        deps = [
+          ":copy_libraries",
+        ]
+        source = "../third_party/pkg/tflite_native/lib/src/blobs"
+        dest = "$root_out_dir/dart-sdk/bin/snapshots"
+        ignore_patterns = "*.so"
+      },
+    ]
+  }
 }
 
 # This generates targets for everything in copy_tree_specs. The targets have the
@@ -394,25 +434,25 @@
 
 copy("copy_dartaotruntime") {
   deps = [
-    "../runtime/bin:dartaotruntime",
+    "../runtime/bin:dart_precompiled_runtime",
   ]
   dartaotruntime_out =
-      get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
+      get_label_info("../runtime/bin:dart_precompiled_runtime", "root_out_dir")
   if (is_win) {
     sources = [
-      "$dartaotruntime_out/dartaotruntime.exe",
+      "$dartaotruntime_out/dart_precompiled_runtime.exe",
+    ]
+    outputs = [
+      "$root_out_dir/dart-sdk/bin/dartaotruntime.exe",
     ]
   } else {
     sources = [
-      "$dartaotruntime_out/$dartaotruntime_stripped_binary",
+      "$dartaotruntime_out/$dart_precompiled_runtime_stripped_binary",
+    ]
+    outputs = [
+      "$root_out_dir/dart-sdk/bin/dartaotruntime",
     ]
   }
-  if (is_win) {
-    sources += [ "$dartaotruntime_out/dartaotruntime.lib" ]
-  }
-  outputs = [
-    "$root_out_dir/dart-sdk/bin/{{source_file_part}}",
-  ]
 }
 
 copy("copy_gen_snapshot") {
@@ -437,6 +477,7 @@
 
 copy("copy_dart2native") {
   deps = [
+    ":copy_dartaotruntime",
     ":copy_gen_kernel_snapshot",
     ":copy_gen_snapshot",
   ]
@@ -987,7 +1028,6 @@
     ":copy_analysis_summaries",
     ":copy_api_readme",
     ":copy_dart",
-    ":copy_dart2native",
     ":copy_dartdoc_files",
     ":copy_headers",
     ":copy_libraries_dart",
@@ -999,6 +1039,13 @@
     ":write_revision_file",
     ":write_version_file",
   ]
+
+  # We do not support AOT on ia32 and should therefore not add the
+  # dart2native script (since there is no AOT compiler/runtime available)
+  if (include_dart2native && dart_target_arch != "ia32") {
+    public_deps += [ ":copy_dart2native" ]
+  }
+
   if (is_win) {
     public_deps += [ ":copy_7zip" ]
   }
diff --git a/sdk_nnbd/lib/_http/http_headers.dart b/sdk_nnbd/lib/_http/http_headers.dart
index f383790..f2d9da8 100644
--- a/sdk_nnbd/lib/_http/http_headers.dart
+++ b/sdk_nnbd/lib/_http/http_headers.dart
@@ -106,6 +106,7 @@
   }
 
   void noFolding(String name) {
+    name = _validateField(name);
     if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>();
     _noFoldingHeaders.add(name);
   }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
index 66f8c29..1cccbaa 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
@@ -13,6 +13,8 @@
 
 import 'dart:_foreign_helper' show JS;
 import 'dart:collection' show HashMap;
+import 'dart:async' show Completer;
+import 'dart:_js_helper' show convertDartClosureToJS;
 
 /// WARNING: performance of this method is much worse than other uitil
 /// methods in this library. Only use this method as a last resort.
@@ -126,3 +128,23 @@
   //         []..addAll(arguments.map(_convertToJS)));
   //     return _wrapToDart(jsObj);
 }
+
+/// Converts a JavaScript Promise to a Dart [Future].
+///
+/// ```dart
+/// @JS()
+/// external Promise<num> get threePromise; // Resolves to 3
+///
+/// final Future<num> threeFuture = promiseToFuture(threePromise);
+///
+/// final three = await threeFuture; // == 3
+/// ```
+Future<T> promiseToFuture<T>(jsPromise) {
+  final completer = Completer<T>();
+
+  final success = convertDartClosureToJS((r) => completer.complete(r), 1);
+  final error = convertDartClosureToJS((e) => completer.completeError(e), 1);
+
+  JS('', '#.then(#, #)', jsPromise, success, error);
+  return completer.future;
+}
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
index 88d2407..894aef4 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Patch file for the dart:async library.
 
 import 'dart:_js_helper' show notNull, patch, ReifyFunctionTypes;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 4829140..48e9236 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -20,7 +20,7 @@
         quoteStringForRegExp,
         undefined;
 import 'dart:_runtime' as dart;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JSExportName;
 import 'dart:_native_typed_data' show NativeUint8List;
 import 'dart:collection' show UnmodifiableMapView;
 import 'dart:convert' show Encoding, utf8;
@@ -63,12 +63,39 @@
 
   @patch
   Type get runtimeType => dart.wrapType(dart.getReifiedType(this));
+
+  // Everything is an Object.
+  @JSExportName('is')
+  static bool _is_Object(Object o) => true;
+
+  @JSExportName('as')
+  static Object _as_Object(Object o) => o;
+
+  @JSExportName('_check')
+  static Object _check_Object(Object o) => o;
 }
 
 @patch
 class Null {
   @patch
   int get hashCode => super.hashCode;
+
+  @JSExportName('is')
+  static bool _is_Null(Object o) => o == null;
+
+  @JSExportName('as')
+  static Object _as_Null(Object o) {
+    // Avoid extra function call to core.Null.is() by manually inlining.
+    if (o == null) return o;
+    return dart.cast(o, dart.unwrapType(Null), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_Null(Object o) {
+    // Avoid extra function call to core.Null.is() by manually inlining.
+    if (o == null) return o;
+    return dart.cast(o, dart.unwrapType(Null), true);
+  }
 }
 
 // Patch for Function implementation.
@@ -97,6 +124,24 @@
     });
     return result;
   }
+
+  @JSExportName('is')
+  static bool _is_Function(Object o) =>
+      JS<bool>('!', 'typeof $o == "function"');
+
+  @JSExportName('as')
+  static Object _as_Function(Object o) {
+    // Avoid extra function call to core.Function.is() by manually inlining.
+    if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(Function), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_Function(Object o) {
+    // Avoid extra function call to core.Function.is() by manually inlining.
+    if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(Function), true);
+  }
 }
 
 // TODO(jmesserly): switch to WeakMap
@@ -157,6 +202,31 @@
     throw UnsupportedError(
         'int.fromEnvironment can only be used as a const constructor');
   }
+
+  @JSExportName('is')
+  static bool _is_int(Object o) {
+    return JS<bool>('!', 'typeof $o == "number" && Math.floor($o) == $o');
+  }
+
+  @JSExportName('as')
+  static Object _as_int(Object o) {
+    // Avoid extra function call to core.int.is() by manually inlining.
+    if (JS<bool>('!', '(typeof $o == "number" && Math.floor($o) == $o)') ||
+        o == null) {
+      return o;
+    }
+    return dart.cast(o, dart.unwrapType(int), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_int(Object o) {
+    // Avoid extra function call to core.int.is() by manually inlining.
+    if (JS<bool>('!', '(typeof $o == "number" && Math.floor($o) == $o)') ||
+        o == null) {
+      return o;
+    }
+    return dart.cast(o, dart.unwrapType(int), true);
+  }
 }
 
 @patch
@@ -171,6 +241,47 @@
   static double? tryParse(String source) {
     return Primitives.parseDouble(source, _kNull);
   }
+
+  @JSExportName('is')
+  static bool _is_double(o) {
+    return JS<bool>('!', 'typeof $o == "number"');
+  }
+
+  @JSExportName('as')
+  static Object _as_double(o) {
+    // Avoid extra function call to core.double.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(double), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_double(o) {
+    // Avoid extra function call to core.double.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(double), true);
+  }
+}
+
+@patch
+abstract class num implements Comparable<num> {
+  @JSExportName('is')
+  static bool _is_num(o) {
+    return JS<bool>('!', 'typeof $o == "number"');
+  }
+
+  @JSExportName('as')
+  static Object _as_num(o) {
+    // Avoid extra function call to core.num.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(num), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_num(o) {
+    // Avoid extra function call to core.num.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "number"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(num), true);
+  }
 }
 
 @patch
@@ -532,6 +643,25 @@
     }
     return Primitives.stringFromCharCodes(list);
   }
+
+  @JSExportName('is')
+  static bool _is_String(Object o) {
+    return JS<bool>('!', 'typeof $o == "string"');
+  }
+
+  @JSExportName('as')
+  static Object _as_String(Object o) {
+    // Avoid extra function call to core.String.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "string"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(String), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_String(Object o) {
+    // Avoid extra function call to core.String.is() by manually inlining.
+    if (JS<bool>('!', 'typeof $o == "string"') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(String), true);
+  }
 }
 
 @patch
@@ -545,6 +675,24 @@
 
   @patch
   int get hashCode => super.hashCode;
+
+  @JSExportName('is')
+  static bool _is_bool(Object o) =>
+      JS<bool>('!', '$o === true || $o === false');
+
+  @JSExportName('as')
+  static Object _as_bool(Object o) {
+    // Avoid extra function call to core.bool.is() by manually inlining.
+    if (JS<bool>("!", '$o === true || $o === false') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(bool), false);
+  }
+
+  @JSExportName('_check')
+  static Object _check_bool(Object o) {
+    // Avoid extra function call to core.bool.is() by manually inlining.
+    if (JS<bool>("!", '$o === true || $o === false') || o == null) return o;
+    return dart.cast(o, dart.unwrapType(bool), true);
+  }
 }
 
 @patch
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart
index 7f5e4fe..a60609f 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart
@@ -13,7 +13,7 @@
 
 @patch
 @ForceInline()
-bool debugger({bool when = true, String message}) {
+bool debugger({bool when = true, String? message}) {
   if (when) {
     JS('', 'debugger');
   }
@@ -21,7 +21,7 @@
 }
 
 @patch
-Object inspect(Object object) {
+Object? inspect(Object? object) {
   // Note: this log level does not show up by default in Chrome.
   // This is used for communication with the debugger service.
   JS('', 'console.debug("dart.developer.inspect", #)', object);
@@ -30,13 +30,13 @@
 
 @patch
 void log(String message,
-    {DateTime time,
-    int sequenceNumber,
+    {DateTime? time,
+    int? sequenceNumber,
     int level = 0,
     String name = '',
-    Zone zone,
-    Object error,
-    StackTrace stackTrace}) {
+    Zone? zone,
+    Object? error,
+    StackTrace? stackTrace}) {
   Object items =
       JS('!', '{ message: #, name: #, level: # }', message, name, level);
   if (time != null) JS('', '#.time = #', items, time);
@@ -50,10 +50,10 @@
   JS('', 'console.debug("dart.developer.log", #)', items);
 }
 
-final _extensions = Map<String, ServiceExtensionHandler>();
+final _extensions = <String, ServiceExtensionHandler>{};
 
 @patch
-ServiceExtensionHandler _lookupExtension(String method) {
+ServiceExtensionHandler? _lookupExtension(String method) {
   return _extensions[method];
 }
 
@@ -79,7 +79,7 @@
   return JS('', 'new #.Promise(#)', dart.global_,
       (Function(Object) resolve, Function(Object) reject) async {
     try {
-      var method = _lookupExtension(methodName);
+      var method = _lookupExtension(methodName)!;
       var parameters = (json.decode(encodedJson) as Map).cast<String, String>();
       var result = await method(methodName, parameters);
       resolve(result._toString());
@@ -164,7 +164,7 @@
 }
 
 @patch
-String _getIsolateIDFromSendPort(SendPort sendPort) {
+String? _getIsolateIDFromSendPort(SendPort sendPort) {
   return null;
 }
 
@@ -178,7 +178,7 @@
 }
 
 class _FakeUserTag implements UserTag {
-  static Map _instances = {};
+  static final _instances = <String, _FakeUserTag>{};
 
   _FakeUserTag.real(this.label);
 
@@ -193,10 +193,7 @@
       throw UnsupportedError(
           'UserTag instance limit (${UserTag.MAX_USER_TAGS}) reached.');
     }
-    // Create a new instance and add it to the instance map.
-    var instance = _FakeUserTag.real(label);
-    _instances[label] = instance;
-    return instance;
+    return _instances[label] = _FakeUserTag.real(label);
   }
 
   final String label;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index e642b5c..5e850bb 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 import 'dart:core' hide Symbol;
 import 'dart:core' as core show Symbol;
 import 'dart:_js_primitives' show printString;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 1bda4e3..9b9e648 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -24,7 +24,13 @@
 import 'dart:_js_names' show unmangleGlobalNameIfPreservedAnyways;
 
 import 'dart:_js_embedded_names'
-    show JsBuiltin, JsGetName, RtiUniverseFieldNames, RTI_UNIVERSE, TYPES;
+    show
+        JsBuiltin,
+        JsGetName,
+        RtiUniverseFieldNames,
+        CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME,
+        RTI_UNIVERSE,
+        TYPES;
 
 import 'dart:_recipe_syntax';
 
@@ -105,6 +111,18 @@
     rti._precomputed1 = precomputed;
   }
 
+  // Data value used by some tests.
+  @pragma('dart2js:noElision')
+  Object _specializedTestResource;
+
+  static Object _getSpecializedTestResource(Rti rti) {
+    return rti._specializedTestResource;
+  }
+
+  static void _setSpecializedTestResource(Rti rti, Object value) {
+    rti._specializedTestResource = value;
+  }
+
   // The Type object corresponding to this Rti.
   Object _cachedRuntimeType;
   static _Type _getCachedRuntimeType(Rti rti) =>
@@ -545,10 +563,14 @@
   return result;
 }
 
+bool _isDartObject(object) => _Utils.instanceOf(object,
+    JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartObjectConstructor));
+
 bool _isClosure(object) => _Utils.instanceOf(object,
     JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartClosureConstructor));
 
-/// Returns the structural function [Rti] of [closure].
+/// Returns the structural function [Rti] of [closure], or `null`.
+/// [closure] must be a subclass of [Closure].
 /// Called from generated code.
 Rti closureFunctionType(closure) {
   var signatureName = JS_GET_NAME(JsGetName.SIGNATURE_NAME);
@@ -562,19 +584,6 @@
   return null;
 }
 
-// Subclasses of Closure are synthetic classes. The synthetic classes all
-// extend a 'normal' class (Closure, BoundClosure, StaticClosure), so make
-// them appear to be the superclass.
-// TODO(sra): Can this be done less expensively, e.g. by putting $ti on the
-// prototype of Closure/BoundClosure/StaticClosure classes?
-Rti _closureInterfaceType(closure) {
-  var rti = JS('', r'#[#]', closure, JS_GET_NAME(JsGetName.RTI_NAME));
-  return rti != null
-      ? _castToRti(rti)
-      : _instanceTypeFromConstructor(
-          JS('', '#.__proto__.__proto__.constructor', closure));
-}
-
 /// Returns the Rti type of [object]. Closures have both an interface type
 /// (Closures implement `Function`) and a structural function type. Uses
 /// [testRti] to choose the appropriate type.
@@ -594,23 +603,18 @@
 }
 
 /// Returns the Rti type of [object].
+/// This is the general entry for obtaining the interface type of any value.
 /// Called from generated code.
 Rti instanceType(object) {
-  if (_isClosure(object)) return _closureInterfaceType(object);
-  return _nonClosureInstanceType(object);
-}
+  // TODO(sra): Add interceptor-based specializations of this method. Inject a
+  // _getRti method into (Dart)Object, JSArray, and Interceptor. Then calls to
+  // this method can be generated as `getInterceptor(o)._getRti(o)`, allowing
+  // interceptor optimizations to select the specialization. If the only use of
+  // `getInterceptor` is for calling `_getRti`, then `instanceType` can be
+  // called, similar to a one-shot interceptor call. This would improve type
+  // lookup in ListMixin code as the interceptor is JavaScript 'this'.
 
-Rti _nonClosureInstanceType(object) {
-  // TODO(sra): Add specializations of this method. One possible way is to
-  // arrange that the interceptor has a _getType method that is injected into
-  // DartObject, Interceptor and JSArray. Then this method can be replaced-by
-  // `getInterceptor(o)._getType(o)`, allowing interceptor optimizations to
-  // select the specialization.
-
-  if (_Utils.instanceOf(
-      object,
-      JS_BUILTIN(
-          'depends:none;effects:none;', JsBuiltin.dartObjectConstructor))) {
+  if (_isDartObject(object)) {
     return _instanceType(object);
   }
 
@@ -619,7 +623,7 @@
   }
 
   var interceptor = getInterceptor(object);
-  return _instanceTypeFromConstructor(JS('', '#.constructor', interceptor));
+  return _instanceTypeFromConstructor(interceptor);
 }
 
 /// Returns the Rti type of JavaScript Array [object].
@@ -638,9 +642,7 @@
 /// Called from generated code.
 Rti _instanceType(object) {
   var rti = JS('', r'#[#]', object, JS_GET_NAME(JsGetName.RTI_NAME));
-  return rti != null
-      ? _castToRti(rti)
-      : _instanceTypeFromConstructor(JS('', '#.constructor', object));
+  return rti != null ? _castToRti(rti) : _instanceTypeFromConstructor(object);
 }
 
 String instanceTypeName(object) {
@@ -648,10 +650,32 @@
   return _rtiToString(rti, null);
 }
 
-Rti _instanceTypeFromConstructor(constructor) {
-  // TODO(sra): Cache Rti on constructor.
-  return _Universe.findErasedType(
-      _theUniverse(), JS('String', '#.name', constructor));
+Rti _instanceTypeFromConstructor(instance) {
+  var constructor = JS('', '#.constructor', instance);
+  var probe = JS('', r'#[#]', constructor, CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME);
+  if (probe != null) return _castToRti(probe);
+  return _instanceTypeFromConstructorMiss(instance, constructor);
+}
+
+@pragma('dart2js:noInline')
+Rti _instanceTypeFromConstructorMiss(instance, constructor) {
+  // Subclasses of Closure are synthetic classes. The synthetic classes all
+  // extend a 'normal' class (Closure, BoundClosure, StaticClosure), so make
+  // them appear to be the superclass. Instantiations have a `$ti` field so
+  // don't reach here.
+  //
+  // TODO(39214): This will need fixing if we ever use instances of
+  // StaticClosure for static tear-offs.
+  //
+  // TODO(sra): Can this test be avoided, e.g. by putting $ti on the
+  // prototype of Closure/BoundClosure/StaticClosure classes?
+  var effectiveConstructor = _isClosure(instance)
+      ? JS('', '#.__proto__.__proto__.constructor', instance)
+      : constructor;
+  Rti rti = _Universe.findErasedType(
+      _theUniverse(), JS('String', '#.name', effectiveConstructor));
+  JS('', r'#[#] = #', constructor, CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME, rti);
+  return rti;
 }
 
 /// Returns the structural function type of [object], or `null` if the object is
@@ -674,7 +698,7 @@
 }
 
 Type getRuntimeType(object) {
-  Rti rti = _instanceFunctionType(object) ?? _nonClosureInstanceType(object);
+  Rti rti = _instanceFunctionType(object) ?? instanceType(object);
   return createRuntimeType(rti);
 }
 
@@ -752,6 +776,16 @@
       isFn = RAW_DART_FUNCTION_REF(_isString);
     } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
       isFn = RAW_DART_FUNCTION_REF(_isBool);
+    } else {
+      String name = Rti._getInterfaceName(testRti);
+      var arguments = Rti._getInterfaceTypeArguments(testRti);
+      if (JS(
+          'bool', '#.every(#)', arguments, RAW_DART_FUNCTION_REF(isTopType))) {
+        String propertyName =
+            '${JS_GET_NAME(JsGetName.OPERATOR_IS_PREFIX)}${name}';
+        Rti._setSpecializedTestResource(testRti, propertyName);
+        isFn = RAW_DART_FUNCTION_REF(_isTestViaProperty);
+      }
     }
   }
 
@@ -769,6 +803,24 @@
 }
 
 /// Called from generated code.
+bool _isTestViaProperty(object) {
+  // This static method is installed on an Rti object as a JavaScript instance
+  // method. The Rti object is 'this'.
+  Rti testRti = _castToRti(JS('', 'this'));
+  var tag = Rti._getSpecializedTestResource(testRti);
+
+  // This test is redundant with getInterceptor below, but getInterceptor does
+  // the tests in the wrong order for most tags, so it is usually faster to have
+  // this check.
+  if (_isDartObject(object)) {
+    return JS('bool', '!!#[#]', object, tag);
+  }
+
+  var interceptor = getInterceptor(object);
+  return JS('bool', '!!#[#]', interceptor, tag);
+}
+
+/// Called from generated code.
 _generalAsCheckImplementation(object) {
   if (object == null) return object;
   // This static method is installed on an Rti object as a JavaScript instance
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index 4628ac9..99435c0 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -49,6 +49,10 @@
 /// the static function's unique (potentially minified) name.
 const STATIC_FUNCTION_NAME_PROPERTY_NAME = r'$static_name';
 
+/// The name of a property on the constructor function of Dart Object
+/// and interceptor types, used for caching Rti types.
+const CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME = r'$ccache';
+
 /// The name of the embedded global for metadata.
 ///
 /// Use [JsBuiltin.getMetadata] instead of directly accessing this embedded
diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
index 628419c..5d7ee8c 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
@@ -590,3 +590,17 @@
 
   toString() => "Error: field '$_name' is already initialized.";
 }
+
+class _LateInitializationError extends Error
+    implements LateInitializationError {
+  _LateInitializationError(this._name);
+
+  @pragma("vm:entry-point")
+  static void _throwNew(String name) {
+    throw _LateInitializationError(name);
+  }
+
+  String toString() => "LateInitializationError: $_name";
+
+  final String _name;
+}
diff --git a/sdk_nnbd/lib/async/async.dart b/sdk_nnbd/lib/async/async.dart
index b4bec24..75d1c60 100644
--- a/sdk_nnbd/lib/async/async.dart
+++ b/sdk_nnbd/lib/async/async.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 /**
  * Support for asynchronous programming,
  * with classes such as Future and Stream.
@@ -95,7 +93,7 @@
  */
 library dart.async;
 
-import "dart:collection" show HashMap, IterableBase;
+import "dart:collection" show HashMap;
 import "dart:_internal"
     show
         CastStream,
diff --git a/sdk_nnbd/lib/async/async_error.dart b/sdk_nnbd/lib/async/async_error.dart
index 5edac63..17abfed 100644
--- a/sdk_nnbd/lib/async/async_error.dart
+++ b/sdk_nnbd/lib/async/async_error.dart
@@ -2,20 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 _invokeErrorHandler(
-    Function errorHandler, Object error, StackTrace stackTrace) {
-  if (errorHandler is ZoneBinaryCallback<dynamic, Null, Null>) {
+    Function errorHandler, Object error, StackTrace? stackTrace) {
+  var handler = errorHandler; // Rename to avoid promotion.
+  if (handler is ZoneBinaryCallback<dynamic, Never, Never>) {
     // Dynamic invocation because we don't know the actual type of the
     // first argument or the error object, but we should successfully call
     // the handler if they match up.
-    // TODO(lrn): Should we? Why not the same below for the unary case?
-    return (errorHandler as dynamic)(error, stackTrace);
+    return errorHandler(error, stackTrace);
   } else {
-    ZoneUnaryCallback unaryErrorHandler = errorHandler;
-    return unaryErrorHandler(error);
+    return errorHandler(error);
   }
 }
diff --git a/sdk_nnbd/lib/async/broadcast_stream_controller.dart b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
index c5358f2..ec0bae3 100644
--- a/sdk_nnbd/lib/async/broadcast_stream_controller.dart
+++ b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 class _BroadcastStream<T> extends _ControllerStream<T> {
@@ -22,11 +20,12 @@
   // does not assume that it's use of the state integer is the only use.
   int _eventState = 0; // Initialized to help dart2js type inference.
 
-  _BroadcastSubscription<T> _next;
-  _BroadcastSubscription<T> _previous;
+  _BroadcastSubscription<T>? _next;
+  _BroadcastSubscription<T>? _previous;
 
   _BroadcastSubscription(_StreamControllerLifecycle<T> controller,
-      void onData(T data), Function onError, void onDone(), bool cancelOnError)
+      void onData(T data)?, Function? onError, void onDone()?,
+      bool cancelOnError)
       : super(controller, onData, onError, onDone, cancelOnError) {
     _next = _previous = this;
   }
@@ -66,18 +65,18 @@
   static const int _STATE_CLOSED = 4;
   static const int _STATE_ADDSTREAM = 8;
 
-  ControllerCallback onListen;
-  ControllerCancelCallback onCancel;
+  void Function()? onListen;
+  FutureOr<void> Function()? onCancel;
 
   // State of the controller.
   int _state;
 
   // Double-linked list of active listeners.
-  _BroadcastSubscription<T> _firstSubscription;
-  _BroadcastSubscription<T> _lastSubscription;
+  _BroadcastSubscription<T>? _firstSubscription;
+  _BroadcastSubscription<T>? _lastSubscription;
 
   // Extra state used during an [addStream] call.
-  _AddStreamState<T> _addStreamState;
+  _AddStreamState<T>? _addStreamState;
 
   /**
    * Future returned by [close] and [done].
@@ -92,27 +91,27 @@
    * Any attempt to listen after calling [close] will throw, so there won't
    * be any further listeners.
    */
-  _Future _doneFuture;
+  _Future<void>? _doneFuture;
 
   _BroadcastStreamController(this.onListen, this.onCancel)
       : _state = _STATE_INITIAL;
 
-  ControllerCallback get onPause {
+  void Function() get onPause {
     throw new UnsupportedError(
         "Broadcast stream controllers do not support pause callbacks");
   }
 
-  void set onPause(void onPauseHandler()) {
+  void set onPause(void onPauseHandler()?) {
     throw new UnsupportedError(
         "Broadcast stream controllers do not support pause callbacks");
   }
 
-  ControllerCallback get onResume {
+  void Function() get onResume {
     throw new UnsupportedError(
         "Broadcast stream controllers do not support pause callbacks");
   }
 
-  void set onResume(void onResumeHandler()) {
+  void set onResume(void onResumeHandler()?) {
     throw new UnsupportedError(
         "Broadcast stream controllers do not support pause callbacks");
   }
@@ -153,10 +152,7 @@
 
   bool get _mayAddEvent => (_state < _STATE_CLOSED);
 
-  _Future _ensureDoneFuture() {
-    if (_doneFuture != null) return _doneFuture;
-    return _doneFuture = new _Future();
-  }
+  _Future<void> _ensureDoneFuture() => _doneFuture ??= _Future<void>();
 
   // Linked list helpers
 
@@ -167,7 +163,7 @@
     assert(identical(subscription._next, subscription));
     subscription._eventState = (_state & _STATE_EVENT_ID);
     // Insert in linked list as last subscription.
-    _BroadcastSubscription<T> oldLast = _lastSubscription;
+    _BroadcastSubscription<T>? oldLast = _lastSubscription;
     _lastSubscription = subscription;
     subscription._next = null;
     subscription._previous = oldLast;
@@ -181,8 +177,8 @@
   void _removeListener(_BroadcastSubscription<T> subscription) {
     assert(identical(subscription._controller, this));
     assert(!identical(subscription._next, subscription));
-    _BroadcastSubscription<T> previous = subscription._previous;
-    _BroadcastSubscription<T> next = subscription._next;
+    _BroadcastSubscription<T>? previous = subscription._previous;
+    _BroadcastSubscription<T>? next = subscription._next;
     if (previous == null) {
       // This was the first subscription.
       _firstSubscription = next;
@@ -201,13 +197,12 @@
 
   // _StreamControllerLifecycle interface.
 
-  StreamSubscription<T> _subscribe(void onData(T data), Function onError,
-      void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
+      void onDone()?, bool cancelOnError) {
     if (isClosed) {
-      onDone ??= _nullDoneHandler;
       return new _DoneStreamSubscription<T>(onDone);
     }
-    StreamSubscription<T> subscription = new _BroadcastSubscription<T>(
+    var subscription = new _BroadcastSubscription<T>(
         this, onData, onError, onDone, cancelOnError);
     _addListener(subscription);
     if (identical(_firstSubscription, _lastSubscription)) {
@@ -217,8 +212,8 @@
     return subscription;
   }
 
-  Future _recordCancel(StreamSubscription<T> sub) {
-    _BroadcastSubscription<T> subscription = sub;
+  Future<void>? _recordCancel(StreamSubscription<T> sub) {
+    _BroadcastSubscription<T> subscription = sub as _BroadcastSubscription<T>;
     // If already removed by the stream, don't remove it again.
     if (identical(subscription._next, subscription)) return null;
     if (subscription._isFiring) {
@@ -252,12 +247,11 @@
     _sendData(data);
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+  void addError(Object error, [StackTrace? stackTrace]) {
     if (!_mayAddEvent) throw _addEventError();
-    AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+    AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
-      error = _nonNullError(replacement.error);
+      error = replacement.error;
       stackTrace = replacement.stackTrace;
     }
     _sendError(error, stackTrace);
@@ -266,7 +260,7 @@
   Future close() {
     if (isClosed) {
       assert(_doneFuture != null);
-      return _doneFuture;
+      return _doneFuture!;
     }
     if (!_mayAddEvent) throw _addEventError();
     _state |= _STATE_CLOSED;
@@ -275,13 +269,15 @@
     return doneFuture;
   }
 
-  Future get done => _ensureDoneFuture();
+  Future<void> get done => _ensureDoneFuture();
 
-  Future addStream(Stream<T> stream, {bool cancelOnError}) {
+  Future addStream(Stream<T> stream, {bool? cancelOnError}) {
     if (!_mayAddEvent) throw _addEventError();
     _state |= _STATE_ADDSTREAM;
-    _addStreamState = new _AddStreamState(this, stream, cancelOnError ?? false);
-    return _addStreamState.addStreamFuture;
+    var addStreamState =
+        new _AddStreamState(this, stream, cancelOnError ?? false);
+    _addStreamState = addStreamState;
+    return addStreamState.addStreamFuture;
   }
 
   // _EventSink interface, called from AddStreamState.
@@ -289,13 +285,13 @@
     _sendData(data);
   }
 
-  void _addError(Object error, StackTrace stackTrace) {
+  void _addError(Object error, StackTrace? stackTrace) {
     _sendError(error, stackTrace);
   }
 
   void _close() {
     assert(_isAddingStream);
-    _AddStreamState addState = _addStreamState;
+    _AddStreamState addState = _addStreamState!;
     _addStreamState = null;
     _state &= ~_STATE_ADDSTREAM;
     addState.complete();
@@ -319,13 +315,13 @@
     // Any listeners added while firing this event will expect the next event,
     // not this one, and won't get notified.
     _state ^= _STATE_EVENT_ID | _STATE_FIRING;
-    _BroadcastSubscription<T> subscription = _firstSubscription;
+    _BroadcastSubscription<T>? subscription = _firstSubscription;
     while (subscription != null) {
       if (subscription._expectsEvent(id)) {
         subscription._eventState |= _BroadcastSubscription._STATE_FIRING;
         action(subscription);
         subscription._toggleEventId();
-        _BroadcastSubscription<T> next = subscription._next;
+        _BroadcastSubscription<T>? next = subscription._next;
         if (subscription._removeAfterFiring) {
           _removeListener(subscription);
         }
@@ -344,9 +340,12 @@
 
   void _callOnCancel() {
     assert(_isEmpty);
-    if (isClosed && _doneFuture._mayComplete) {
+    if (isClosed) {
       // When closed, _doneFuture is not null.
-      _doneFuture._asyncComplete(null);
+      var doneFuture = _doneFuture!;
+      if (doneFuture._mayComplete) {
+        doneFuture._asyncComplete(null);
+      }
     }
     _runGuarded(onCancel);
   }
@@ -354,7 +353,7 @@
 
 class _SyncBroadcastStreamController<T> extends _BroadcastStreamController<T>
     implements SynchronousStreamController<T> {
-  _SyncBroadcastStreamController(void onListen(), void onCancel())
+  _SyncBroadcastStreamController(void onListen()?, void onCancel()?)
       : super(onListen, onCancel);
 
   // EventDispatch interface.
@@ -373,8 +372,7 @@
     if (_isEmpty) return;
     if (_hasOneListener) {
       _state |= _BroadcastStreamController._STATE_FIRING;
-      _BroadcastSubscription<T> subscription = _firstSubscription;
-      subscription._add(data);
+      (_firstSubscription as _BroadcastSubscription<T>)._add(data);
       _state &= ~_BroadcastStreamController._STATE_FIRING;
       if (_isEmpty) {
         _callOnCancel();
@@ -386,7 +384,7 @@
     });
   }
 
-  void _sendError(Object error, StackTrace stackTrace) {
+  void _sendError(Object error, StackTrace? stackTrace) {
     if (_isEmpty) return;
     _forEachListener((_BufferingStreamSubscription<T> subscription) {
       subscription._addError(error, stackTrace);
@@ -399,29 +397,28 @@
         subscription._close();
       });
     } else {
-      assert(_doneFuture != null);
-      assert(_doneFuture._mayComplete);
-      _doneFuture._asyncComplete(null);
+      assert(_doneFuture != null && _doneFuture!._mayComplete);
+      _doneFuture!._asyncComplete(null);
     }
   }
 }
 
 class _AsyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
-  _AsyncBroadcastStreamController(void onListen(), void onCancel())
+  _AsyncBroadcastStreamController(void onListen()?, void onCancel()?)
       : super(onListen, onCancel);
 
   // EventDispatch interface.
 
   void _sendData(T data) {
-    for (_BroadcastSubscription<T> subscription = _firstSubscription;
+    for (var subscription = _firstSubscription;
         subscription != null;
         subscription = subscription._next) {
       subscription._addPending(new _DelayedData<T>(data));
     }
   }
 
-  void _sendError(Object error, StackTrace stackTrace) {
-    for (_BroadcastSubscription<T> subscription = _firstSubscription;
+  void _sendError(Object error, StackTrace? stackTrace) {
+    for (var subscription = _firstSubscription;
         subscription != null;
         subscription = subscription._next) {
       subscription._addPending(new _DelayedError(error, stackTrace));
@@ -430,15 +427,14 @@
 
   void _sendDone() {
     if (!_isEmpty) {
-      for (_BroadcastSubscription<T> subscription = _firstSubscription;
+      for (var subscription = _firstSubscription;
           subscription != null;
           subscription = subscription._next) {
         subscription._addPending(const _DelayedDone());
       }
     } else {
-      assert(_doneFuture != null);
-      assert(_doneFuture._mayComplete);
-      _doneFuture._asyncComplete(null);
+      assert(_doneFuture != null && _doneFuture!._mayComplete);
+      _doneFuture!._asyncComplete(null);
     }
   }
 }
@@ -456,16 +452,18 @@
  */
 class _AsBroadcastStreamController<T> extends _SyncBroadcastStreamController<T>
     implements _EventDispatch<T> {
-  _StreamImplEvents<T> _pending;
+  _StreamImplEvents<T>? _pending;
 
-  _AsBroadcastStreamController(void onListen(), void onCancel())
+  _AsBroadcastStreamController(void onListen()?, void onCancel()?)
       : super(onListen, onCancel);
 
-  bool get _hasPending => _pending != null && !_pending.isEmpty;
+  bool get _hasPending {
+    var pending = _pending;
+    return pending != null && !pending.isEmpty;
+  }
 
   void _addPendingEvent(_DelayedEvent event) {
-    _pending ??= new _StreamImplEvents<T>();
-    _pending.add(event);
+    (_pending ??= new _StreamImplEvents<T>()).add(event);
   }
 
   void add(T data) {
@@ -474,20 +472,24 @@
       return;
     }
     super.add(data);
-    while (_hasPending) {
-      _pending.handleNext(this);
-    }
+    _flushPending();
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     if (!isClosed && _isFiring) {
       _addPendingEvent(new _DelayedError(error, stackTrace));
       return;
     }
     if (!_mayAddEvent) throw _addEventError();
     _sendError(error, stackTrace);
-    while (_hasPending) {
-      _pending.handleNext(this);
+    _flushPending();
+  }
+
+  void _flushPending() {
+    var pending = _pending;
+    while (pending != null && !pending.isEmpty) {
+      pending.handleNext(this);
+      pending = _pending;
     }
   }
 
@@ -503,8 +505,9 @@
   }
 
   void _callOnCancel() {
-    if (_hasPending) {
-      _pending.clear();
+    var pending = _pending;
+    if (pending != null) {
+      pending.clear();
       _pending = null;
     }
     super._callOnCancel();
diff --git a/sdk_nnbd/lib/async/deferred_load.dart b/sdk_nnbd/lib/async/deferred_load.dart
index 1e2be92..419db58 100644
--- a/sdk_nnbd/lib/async/deferred_load.dart
+++ b/sdk_nnbd/lib/async/deferred_load.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /**
@@ -15,7 +13,7 @@
 @Deprecated("Dart sdk v. 1.8")
 class DeferredLibrary {
   final String libraryName;
-  final String uri;
+  final String? uri;
 
   const DeferredLibrary(this.libraryName, {this.uri});
 
@@ -32,7 +30,7 @@
  * Thrown when a deferred library fails to load.
  */
 class DeferredLoadException implements Exception {
-  DeferredLoadException(this._s);
+  DeferredLoadException(String message) : _s = message;
   String toString() => "DeferredLoadException: '$_s'";
   final String _s;
 }
diff --git a/sdk_nnbd/lib/async/future.dart b/sdk_nnbd/lib/async/future.dart
index 6e5a777..bbf2eab 100644
--- a/sdk_nnbd/lib/async/future.dart
+++ b/sdk_nnbd/lib/async/future.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /// A type representing values that are either `Future<T>` or `T`.
@@ -149,11 +147,11 @@
 abstract class Future<T> {
   /// A `Future<Null>` completed with `null`.
   static final _Future<Null> _nullFuture =
-      new _Future<Null>.zoneValue(null, Zone.root);
+      new _Future<Null>.zoneValue(null, _rootZone);
 
   /// A `Future<bool>` completed with `false`.
   static final _Future<bool> _falseFuture =
-      new _Future<bool>.zoneValue(false, Zone.root);
+      new _Future<bool>.zoneValue(false, _rootZone);
 
   /**
    * Creates a future containing the result of calling [computation]
@@ -225,14 +223,15 @@
       if (result is Future<T>) {
         return result;
       } else {
+        if (result is! T)
+          throw "unreachable"; // TODO(lrn): Remove when type promotion works.
         return new _Future<T>.value(result);
       }
     } catch (error, stackTrace) {
       var future = new _Future<T>();
-      AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+      AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
       if (replacement != null) {
-        future._asyncCompleteError(
-            _nonNullError(replacement.error), replacement.stackTrace);
+        future._asyncCompleteError(replacement.error, replacement.stackTrace);
       } else {
         future._asyncCompleteError(error, stackTrace);
       }
@@ -252,10 +251,14 @@
    * with the [value] value,
    * equivalently to `new Future<T>.sync(() => value)`.
    *
+   * If [value] is omitted or `null`, it is converted to `FutureOr<T>` by
+   * `value as FutureOr<T>`. If `T` is not nullable, then the [value] is
+   * required, otherwise the construction throws.
+   *
    * Use [Completer] to create a future and complete it later.
    */
-  factory Future.value([FutureOr<T> value]) {
-    return new _Future<T>.immediate(value);
+  factory Future.value([FutureOr<T>? value]) {
+    return new _Future<T>.immediate(value as FutureOr<T>);
   }
 
   /**
@@ -270,12 +273,11 @@
    *
    * Use [Completer] to create a future and complete it later.
    */
-  factory Future.error(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+  factory Future.error(Object error, [StackTrace? stackTrace]) {
     if (!identical(Zone.current, _rootZone)) {
-      AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+      AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
       if (replacement != null) {
-        error = _nonNullError(replacement.error);
+        error = replacement.error;
         stackTrace = replacement.stackTrace;
       }
     }
@@ -299,6 +301,7 @@
    * If [computation] is omitted,
    * it will be treated as if [computation] was `() => null`,
    * and the future will eventually complete with the `null` value.
+   * In that case, [T] must be nullable.
    *
    * If calling [computation] throws, the created future will complete with the
    * error.
@@ -306,11 +309,15 @@
    * See also [Completer] for a way to create and complete a future at a
    * later time that isn't necessarily after a known fixed duration.
    */
-  factory Future.delayed(Duration duration, [FutureOr<T> computation()]) {
+  factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
+    if (computation == null && null is! T) {
+      throw ArgumentError.value(
+          null, "computation", "The type parameter is not nullable");
+    }
     _Future<T> result = new _Future<T>();
     new Timer(duration, () {
       if (computation == null) {
-        result._complete(null);
+        result._complete(null as T);
       } else {
         try {
           result._complete(computation());
@@ -352,25 +359,27 @@
    * uncaught asynchronous error.
    */
   static Future<List<T>> wait<T>(Iterable<Future<T>> futures,
-      {bool eagerError: false, void cleanUp(T successValue)}) {
+      {bool eagerError = false, void cleanUp(T successValue)?}) {
     final _Future<List<T>> result = new _Future<List<T>>();
-    List<T> values; // Collects the values. Set to null on error.
+    List<T?>? values; // Collects the values. Set to null on error.
     int remaining = 0; // How many futures are we waiting for.
-    var error; // The first error from a future.
-    StackTrace stackTrace; // The stackTrace that came with the error.
+    Object? error; // The first error from a future.
+    StackTrace? stackTrace; // The stackTrace that came with the error.
 
     // Handle an error from any of the futures.
     // TODO(jmesserly): use `void` return type once it can be inferred for the
     // `then` call below.
-    handleError(theError, StackTrace theStackTrace) {
+    handleError(theError, StackTrace? theStackTrace) {
       remaining--;
-      if (values != null) {
+      List<T?>? valueList = values;
+      if (valueList != null) {
         if (cleanUp != null) {
-          for (var value in values) {
+          for (var value in valueList) {
             if (value != null) {
               // Ensure errors from cleanUp are uncaught.
+              T cleanUpValue = value;
               new Future.sync(() {
-                cleanUp(value);
+                cleanUp(cleanUpValue);
               });
             }
           }
@@ -383,7 +392,7 @@
           stackTrace = theStackTrace;
         }
       } else if (remaining == 0 && !eagerError) {
-        result._completeError(error, stackTrace);
+        result._completeError(error!, stackTrace);
       }
     }
 
@@ -394,12 +403,15 @@
         int pos = remaining;
         future.then((T value) {
           remaining--;
-          if (values != null) {
-            values[pos] = value;
+          List<T?>? valueList = values;
+          if (valueList != null) {
+            valueList[pos] = value;
             if (remaining == 0) {
-              result._completeWithValue(values);
+              result._completeWithValue(List<T>.from(valueList));
             }
           } else {
+            // An error has occurred earlier.
+            assert(error != null);
             if (cleanUp != null && value != null) {
               // Ensure errors from cleanUp are uncaught.
               new Future.sync(() {
@@ -407,7 +419,7 @@
               });
             }
             if (remaining == 0 && !eagerError) {
-              result._completeError(error, stackTrace);
+              result._completeError(error!, stackTrace);
             }
           }
         }, onError: handleError);
@@ -417,12 +429,14 @@
         remaining++;
       }
       if (remaining == 0) {
-        return new Future.value(const []);
+        return new Future<List<T>>.value(const <Never>[]);
       }
-      values = new List<T>(remaining);
+      values = new List<T?>(remaining);
     } catch (e, st) {
       // The error must have been thrown while iterating over the futures
       // list, or while installing a callback handler on the future.
+      // This is a breach of the `Future` protocol, but we try to handle it
+      // gracefully.
       if (remaining == 0 || eagerError) {
         // Throw a new Future.error.
         // Don't just call `result._completeError` since that would propagate
@@ -458,7 +472,7 @@
     var onValue = (T value) {
       if (!completer.isCompleted) completer.complete(value);
     };
-    var onError = (error, StackTrace stack) {
+    var onError = (Object error, StackTrace? stack) {
       if (!completer.isCompleted) completer.completeError(error, stack);
     };
     for (var future in futures) {
@@ -496,7 +510,7 @@
   }
 
   // Constant `true` function, used as callback by [forEach].
-  static bool _kTrue(_) => true;
+  static bool _kTrue(Object? _) => true;
 
   /**
    * Performs an operation repeatedly until it returns `false`.
@@ -521,8 +535,8 @@
    * until that future has completed.
    */
   static Future doWhile(FutureOr<bool> action()) {
-    _Future doneSignal = new _Future();
-    void Function(bool) nextIteration;
+    _Future<void> doneSignal = new _Future<void>();
+    late void Function(bool) nextIteration;
     // Bind this callback explicitly so that each iteration isn't bound in the
     // context of all the previous iterations' callbacks.
     // This avoids, e.g., deeply nested stack traces from the stack trace
@@ -542,7 +556,7 @@
           result.then(nextIteration, onError: doneSignal._completeError);
           return;
         }
-        keepGoing = result;
+        keepGoing = result as bool;
       }
       doneSignal._complete(null);
     });
@@ -598,7 +612,7 @@
    * has completed with an error then the error is reported as unhandled error.
    * See the description on [Future].
    */
-  Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
+  Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});
 
   /**
    * Handles errors emitted by this [Future].
@@ -634,10 +648,10 @@
    */
   // The `Function` below stands for one of two types:
   // - (dynamic) -> FutureOr<T>
-  // - (dynamic, StackTrace) -> FutureOr<T>
+  // - (dynamic, StackTrace?) -> FutureOr<T>
   // Given that there is a `test` function that is usually used to do an
   // `isCheck` we should also expect functions that take a specific argument.
-  Future<T> catchError(Function onError, {bool test(Object error)});
+  Future<T> catchError(Function onError, {bool test(Object error)?});
 
   /**
    * Registers a function to be called when this future completes.
@@ -674,7 +688,7 @@
    *       });
    *     }
    */
-  Future<T> whenComplete(FutureOr action());
+  Future<T> whenComplete(FutureOr<void> action());
 
   /**
    * Creates a [Stream] containing the result of this future.
@@ -701,7 +715,7 @@
    * If `onTimeout` is omitted, a timeout will cause the returned future to
    * complete with a [TimeoutException].
    */
-  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()});
+  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()?});
 }
 
 /**
@@ -709,9 +723,9 @@
  */
 class TimeoutException implements Exception {
   /** Description of the cause of the timeout. */
-  final String message;
+  final String? message;
   /** The duration that was exceeded. */
-  final Duration duration;
+  final Duration? duration;
 
   TimeoutException(this.message, [this.duration]);
 
@@ -855,6 +869,8 @@
    *
    * The value must be either a value of type [T]
    * or a future of type `Future<T>`.
+   * If the value is omitted or null, and `T` is not nullable, the call
+   * to `complete` throws.
    *
    * If the value is itself a future, the completer will wait for that future
    * to complete, and complete with the same result, whether it is a success
@@ -864,7 +880,7 @@
    *
    * All listeners on the future are informed about the value.
    */
-  void complete([FutureOr<T> value]);
+  void complete([FutureOr<T>? value]);
 
   /**
    * Complete [future] with an error.
@@ -874,8 +890,6 @@
    * Completing a future with an error indicates that an exception was thrown
    * while trying to produce a value.
    *
-   * If [error] is `null`, it is replaced by a [NullThrownError].
-   *
    * If `error` is a `Future`, the future itself is used as the error value.
    * If you want to complete with the result of the future, you can use:
    * ```
@@ -886,7 +900,7 @@
    * theFuture.catchError(thisCompleter.completeError);
    * ```
    */
-  void completeError(Object error, [StackTrace stackTrace]);
+  void completeError(Object error, [StackTrace? stackTrace]);
 
   /**
    * Whether the [future] has been completed.
@@ -905,10 +919,11 @@
 
 // Helper function completing a _Future with error, but checking the zone
 // for error replacement first.
-void _completeWithErrorCallback(_Future result, error, StackTrace stackTrace) {
-  AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+void _completeWithErrorCallback(
+    _Future result, Object error, StackTrace? stackTrace) {
+  AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
-    error = _nonNullError(replacement.error);
+    error = replacement.error;
     stackTrace = replacement.stackTrace;
   }
   result._completeError(error, stackTrace);
@@ -916,14 +931,11 @@
 
 // Like [_completeWithErrorCallback] but completes asynchronously.
 void _asyncCompleteWithErrorCallback(
-    _Future result, error, StackTrace stackTrace) {
-  AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+    _Future result, Object error, StackTrace? stackTrace) {
+  AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
-    error = _nonNullError(replacement.error);
+    error = replacement.error;
     stackTrace = replacement.stackTrace;
   }
   result._asyncCompleteError(error, stackTrace);
 }
-
-/** Helper function that converts `null` to a [NullThrownError]. */
-Object _nonNullError(Object error) => error ?? new NullThrownError();
diff --git a/sdk_nnbd/lib/async/future_impl.dart b/sdk_nnbd/lib/async/future_impl.dart
index c9685ff..a4be169 100644
--- a/sdk_nnbd/lib/async/future_impl.dart
+++ b/sdk_nnbd/lib/async/future_impl.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /** The onValue and onError handlers return either a value or a future */
@@ -16,20 +14,19 @@
 abstract class _Completer<T> implements Completer<T> {
   final _Future<T> future = new _Future<T>();
 
-  void complete([FutureOr<T> value]);
+  void complete([FutureOr<T>? value]);
 
-  void completeError(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+  void completeError(Object error, [StackTrace? stackTrace]) {
     if (!future._mayComplete) throw new StateError("Future already completed");
-    AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+    AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
-      error = _nonNullError(replacement.error);
+      error = replacement.error;
       stackTrace = replacement.stackTrace;
     }
     _completeError(error, stackTrace);
   }
 
-  void _completeError(Object error, StackTrace stackTrace);
+  void _completeError(Object error, StackTrace? stackTrace);
 
   // The future's _isComplete doesn't take into account pending completions.
   // We therefore use _mayComplete.
@@ -37,23 +34,23 @@
 }
 
 class _AsyncCompleter<T> extends _Completer<T> {
-  void complete([FutureOr<T> value]) {
+  void complete([FutureOr<T>? value]) {
     if (!future._mayComplete) throw new StateError("Future already completed");
-    future._asyncComplete(value);
+    future._asyncComplete(value as FutureOr<T>);
   }
 
-  void _completeError(Object error, StackTrace stackTrace) {
+  void _completeError(Object error, StackTrace? stackTrace) {
     future._asyncCompleteError(error, stackTrace);
   }
 }
 
 class _SyncCompleter<T> extends _Completer<T> {
-  void complete([FutureOr<T> value]) {
+  void complete([FutureOr<T>? value]) {
     if (!future._mayComplete) throw new StateError("Future already completed");
-    future._complete(value);
+    future._complete(value as FutureOr<T>);
   }
 
-  void _completeError(Object error, StackTrace stackTrace) {
+  void _completeError(Object error, StackTrace? stackTrace) {
     future._completeError(error, stackTrace);
   }
 }
@@ -73,18 +70,18 @@
       maskValue | maskError | maskTestError | maskWhencomplete;
   static const int stateIsAwait = 16;
   // Listeners on the same future are linked through this link.
-  _FutureListener _nextListener;
+  _FutureListener? _nextListener;
   // The future to complete when this listener is activated.
   final _Future<T> result;
   // Which fields means what.
   final int state;
   // Used for then/whenDone callback and error test
-  final Function callback;
+  final Function? callback;
   // Used for error callbacks.
-  final Function errorCallback;
+  final Function? errorCallback;
 
   _FutureListener.then(
-      this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
+      this.result, FutureOr<T> Function(S) onValue, Function? errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
         state = (errorCallback == null) ? stateThen : stateThenOnerror;
@@ -93,8 +90,8 @@
       this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
-        state = ((errorCallback == null) ? stateThen : stateThenOnerror)
-              | stateIsAwait ;
+        state = ((errorCallback == null) ? stateThen : stateThenOnerror) |
+            stateIsAwait;
 
   _FutureListener.catchError(this.result, this.errorCallback, this.callback)
       : state = (callback == null) ? stateCatcherror : stateCatcherrorTest;
@@ -103,7 +100,7 @@
       : errorCallback = null,
         state = stateWhencomplete;
 
-  Zone get _zone => result._zone;
+  _Zone get _zone => result._zone;
 
   bool get handlesValue => (state & maskValue != 0);
   bool get handlesError => (state & maskError != 0);
@@ -111,20 +108,21 @@
   bool get handlesComplete => (state & maskType == stateWhencomplete);
   bool get isAwait => (state & stateIsAwait != 0);
 
-  _FutureOnValue<S, T> get _onValue {
+  FutureOr<T> Function(S) get _onValue {
     assert(handlesValue);
-    return callback;
+    return callback as FutureOr<T> Function(S);
   }
 
-  Function get _onError => errorCallback;
+  Function? get _onError => errorCallback;
+
   _FutureErrorTest get _errorTest {
     assert(hasErrorTest);
-    return callback;
+    return callback as _FutureErrorTest;
   }
 
   _FutureAction get _whenCompleteAction {
     assert(handlesComplete);
-    return callback;
+    return callback as _FutureAction;
   }
 
   /// Whether this listener has an error callback.
@@ -149,12 +147,12 @@
     var errorCallback = this.errorCallback; // To enable promotion.
     // If the errorCallback returns something which is not a FutureOr<T>,
     // this return statement throws, and the caller handles the error.
-    if (errorCallback is dynamic Function(Object, StackTrace)) {
-      return _zone.runBinary<dynamic, Object, StackTrace>(
+    if (errorCallback is dynamic Function(Object, StackTrace?)) {
+      return _zone.runBinary<dynamic, Object, StackTrace?>(
           errorCallback, asyncError.error, asyncError.stackTrace);
     } else {
-      assert(errorCallback is dynamic Function(Object));
-      return _zone.runUnary<dynamic, Object>(errorCallback, asyncError.error);
+      return _zone.runUnary<dynamic, Object>(
+          errorCallback as dynamic Function(Object), asyncError.error);
     }
   }
 
@@ -196,7 +194,7 @@
    * Until the future is completed, the field may hold the zone that
    * listener callbacks used to create this future should be run in.
    */
-  final Zone _zone;
+  final _Zone _zone;
 
   /**
    * Either the result, a list of listeners or another future.
@@ -216,9 +214,9 @@
   var _resultOrListeners;
 
   // This constructor is used by async/await.
-  _Future() : _zone = Zone.current;
+  _Future() : _zone = Zone._current;
 
-  _Future.immediate(FutureOr<T> result) : _zone = Zone.current {
+  _Future.immediate(FutureOr<T> result) : _zone = Zone._current {
     _asyncComplete(result);
   }
 
@@ -227,13 +225,13 @@
     _setValue(value);
   }
 
-  _Future.immediateError(var error, [StackTrace stackTrace])
-      : _zone = Zone.current {
+  _Future.immediateError(var error, [StackTrace? stackTrace])
+      : _zone = Zone._current {
     _asyncCompleteError(error, stackTrace);
   }
 
   /** Creates a future that is already completed with the value. */
-  _Future.value(T value) : this.zoneValue(value, Zone.current);
+  _Future.value(T value) : this.zoneValue(value, Zone._current);
 
   bool get _mayComplete => _state == _stateIncomplete;
   bool get _isPendingComplete => _state == _statePendingComplete;
@@ -242,14 +240,14 @@
   bool get _isComplete => _state >= _stateValue;
   bool get _hasError => _state == _stateError;
 
-  static List<Function> _continuationFunctions(_Future<Object> future) {
-    List<Function> result = null;
+  static List<Function>? _continuationFunctions(_Future<Object> future) {
+    List<Function>? result = null;
     while (true) {
       if (future._mayAddListener) return result;
       assert(!future._isComplete);
       assert(!future._isChained);
       // So _resultOrListeners contains listeners.
-      _FutureListener<Object, Object> listener = future._resultOrListeners;
+      _FutureListener<Object, Object>? listener = future._resultOrListeners;
       if (listener != null &&
           listener._nextListener == null &&
           listener.isAwait) {
@@ -269,7 +267,7 @@
     _resultOrListeners = source;
   }
 
-  Future<R> then<R>(FutureOr<R> f(T value), {Function onError}) {
+  Future<R> then<R>(FutureOr<R> f(T value), {Function? onError}) {
     Zone currentZone = Zone.current;
     if (!identical(currentZone, _rootZone)) {
       f = currentZone.registerUnaryCallback<FutureOr<R>, T>(f);
@@ -291,14 +289,13 @@
   /// The system created liseners are not registered in the zone,
   /// and the listener is marked as being from an `await`.
   /// This marker is used in [_continuationFunctions].
-  Future<E> _thenAwait<E>(
-      FutureOr<E> f(T value), Function onError) {
+  Future<E> _thenAwait<E>(FutureOr<E> f(T value), Function onError) {
     _Future<E> result = new _Future<E>();
     _addListener(new _FutureListener<T, E>.thenAwait(result, f, onError));
     return result;
   }
 
-  Future<T> catchError(Function onError, {bool test(error)}) {
+  Future<T> catchError(Function onError, {bool test(Object error)?}) {
     _Future<T> result = new _Future<T>();
     if (!identical(result._zone, _rootZone)) {
       onError = _registerErrorHandler(onError, result._zone);
@@ -352,7 +349,7 @@
     _resultOrListeners = error;
   }
 
-  void _setError(Object error, StackTrace stackTrace) {
+  void _setError(Object error, StackTrace? stackTrace) {
     _setErrorObject(new AsyncError(error, stackTrace));
   }
 
@@ -391,15 +388,17 @@
     }
   }
 
-  void _prependListeners(_FutureListener listeners) {
+  void _prependListeners(_FutureListener? listeners) {
     if (listeners == null) return;
     if (_mayAddListener) {
       _FutureListener existingListeners = _resultOrListeners;
       _resultOrListeners = listeners;
       if (existingListeners != null) {
         _FutureListener cursor = listeners;
-        while (cursor._nextListener != null) {
-          cursor = cursor._nextListener;
+        _FutureListener? next = cursor._nextListener;
+        while (next != null) {
+          cursor = next;
+          next = cursor._nextListener;
         }
         cursor._nextListener = existingListeners;
       }
@@ -423,20 +422,20 @@
     }
   }
 
-  _FutureListener _removeListeners() {
+  _FutureListener? _removeListeners() {
     // Reverse listeners before returning them, so the resulting list is in
     // subscription order.
     assert(!_isComplete);
-    _FutureListener current = _resultOrListeners;
+    _FutureListener? current = _resultOrListeners;
     _resultOrListeners = null;
     return _reverseListeners(current);
   }
 
-  _FutureListener _reverseListeners(_FutureListener listeners) {
-    _FutureListener prev;
-    _FutureListener current = listeners;
+  _FutureListener? _reverseListeners(_FutureListener? listeners) {
+    _FutureListener? prev = null;
+    _FutureListener? current = listeners;
     while (current != null) {
-      _FutureListener next = current._nextListener;
+      _FutureListener? next = current._nextListener;
       current._nextListener = prev;
       prev = current;
       current = next;
@@ -467,7 +466,7 @@
           // and dependent on the listeners of the target future. If none of
           // the target future's listeners want to have the stack trace we don't
           // need a trace.
-          onError: (error, [StackTrace stackTrace]) {
+          onError: (Object error, [StackTrace? stackTrace]) {
         assert(target._isPendingComplete);
         target._completeError(error, stackTrace);
       });
@@ -490,11 +489,11 @@
       source = source._chainSource;
     }
     if (source._isComplete) {
-      _FutureListener listeners = target._removeListeners();
+      _FutureListener? listeners = target._removeListeners();
       target._cloneResult(source);
       _propagateToListeners(target, listeners);
     } else {
-      _FutureListener listeners = target._resultOrListeners;
+      _FutureListener? listeners = target._resultOrListeners;
       target._setChained(source);
       source._prependListeners(listeners);
     }
@@ -509,8 +508,10 @@
         _chainForeignFuture(value, this);
       }
     } else {
-      _FutureListener listeners = _removeListeners();
-      _setValue(value);
+      if (value is! T)
+        throw "unreachable"; // TODO(lrn): Remove when type promotion works.
+      _FutureListener? listeners = _removeListeners();
+      _setValue(value); // Value promoted to T.
       _propagateToListeners(this, listeners);
     }
   }
@@ -519,15 +520,15 @@
     assert(!_isComplete);
     assert(value is! Future<T>);
 
-    _FutureListener listeners = _removeListeners();
+    _FutureListener? listeners = _removeListeners();
     _setValue(value);
     _propagateToListeners(this, listeners);
   }
 
-  void _completeError(Object error, [StackTrace stackTrace]) {
+  void _completeError(Object error, [StackTrace? stackTrace]) {
     assert(!_isComplete);
 
-    _FutureListener listeners = _removeListeners();
+    _FutureListener? listeners = _removeListeners();
     _setError(error, stackTrace);
     _propagateToListeners(this, listeners);
   }
@@ -549,9 +550,11 @@
       _chainFuture(value);
       return;
     }
+    if (value is! T)
+      throw "unreachable"; // TODO(lrn): Remove when type promotion works.
     _setPendingComplete();
     _zone.scheduleMicrotask(() {
-      _completeWithValue(value);
+      _completeWithValue(value); // Value promoted to T.
     });
   }
 
@@ -572,7 +575,7 @@
     _chainForeignFuture(value, this);
   }
 
-  void _asyncCompleteError(error, StackTrace stackTrace) {
+  void _asyncCompleteError(Object error, StackTrace? stackTrace) {
     assert(!_isComplete);
 
     _setPendingComplete();
@@ -585,7 +588,8 @@
    * Propagates the value/error of [source] to its [listeners], executing the
    * listeners' callbacks.
    */
-  static void _propagateToListeners(_Future source, _FutureListener listeners) {
+  static void _propagateToListeners(
+      _Future source, _FutureListener? listeners) {
     while (true) {
       assert(source._isComplete);
       bool hasError = source._hasError;
@@ -600,13 +604,15 @@
       // Usually futures only have one listener. If they have several, we
       // call handle them separately in recursive calls, continuing
       // here only when there is only one listener left.
-      while (listeners._nextListener != null) {
-        _FutureListener listener = listeners;
-        listeners = listener._nextListener;
+      _FutureListener listener = listeners;
+      _FutureListener? nextListener = listener._nextListener;
+      while (nextListener != null) {
         listener._nextListener = null;
         _propagateToListeners(source, listener);
+        listener = nextListener;
+        nextListener = listener._nextListener;
       }
-      _FutureListener listener = listeners;
+
       final sourceResult = source._resultOrListeners;
       // Do the actual propagation.
       // Set initial state of listenerHasError and listenerValueOrError. These
@@ -622,7 +628,7 @@
       // expensive, branch. Here we'll enter/leave the zone. Many futures
       // don't have callbacks, so this is a significant optimization.
       if (hasError || listener.handlesValue || listener.handlesComplete) {
-        Zone zone = listener._zone;
+        _Zone zone = listener._zone;
         if (hasError && !source._zone.inSameErrorZone(zone)) {
           // Don't cross zone boundaries with errors.
           AsyncError asyncError = source._error;
@@ -631,8 +637,8 @@
           return;
         }
 
-        Zone oldZone;
-        if (!identical(Zone.current, zone)) {
+        _Zone? oldZone;
+        if (!identical(Zone._current, zone)) {
           // Change zone if it's not current.
           oldZone = Zone._enter(zone);
         }
@@ -752,7 +758,7 @@
     }
   }
 
-  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()}) {
+  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()?}) {
     if (_isComplete) return new _Future.immediate(this);
     _Future<T> result = new _Future<T>();
     Timer timer;
@@ -763,10 +769,12 @@
       });
     } else {
       Zone zone = Zone.current;
-      onTimeout = zone.registerCallback(onTimeout);
+      FutureOr<T> Function() onTimeoutHandler =
+          zone.registerCallback(onTimeout);
+
       timer = new Timer(timeLimit, () {
         try {
-          result._complete(zone.run(onTimeout));
+          result._complete(zone.run(onTimeoutHandler));
         } catch (e, s) {
           result._completeError(e, s);
         }
@@ -777,7 +785,7 @@
         timer.cancel();
         result._completeWithValue(v);
       }
-    }, onError: (e, StackTrace s) {
+    }, onError: (Object e, StackTrace? s) {
       if (timer.isActive) {
         timer.cancel();
         result._completeError(e, s);
@@ -810,5 +818,5 @@
       errorHandler,
       "onError",
       "Error handler must accept one Object or one Object and a StackTrace"
-      " as arguments, and return a a valid result");
+          " as arguments, and return a a valid result");
 }
diff --git a/sdk_nnbd/lib/async/schedule_microtask.dart b/sdk_nnbd/lib/async/schedule_microtask.dart
index 41b9d31..95fca9e 100644
--- a/sdk_nnbd/lib/async/schedule_microtask.dart
+++ b/sdk_nnbd/lib/async/schedule_microtask.dart
@@ -2,22 +2,20 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 typedef void _AsyncCallback();
 
 class _AsyncCallbackEntry {
   final _AsyncCallback callback;
-  _AsyncCallbackEntry next;
+  _AsyncCallbackEntry? next;
   _AsyncCallbackEntry(this.callback);
 }
 
 /** Head of single linked list of pending callbacks. */
-_AsyncCallbackEntry _nextCallback;
+_AsyncCallbackEntry? _nextCallback;
 /** Tail of single linked list of pending callbacks. */
-_AsyncCallbackEntry _lastCallback;
+_AsyncCallbackEntry? _lastCallback;
 /**
  * Tail of priority callbacks added by the currently executing callback.
  *
@@ -25,7 +23,7 @@
  * callback queue, so that if one callback schedules more than one
  * priority callback, they are still enqueued in scheduling order.
  */
-_AsyncCallbackEntry _lastPriorityCallback;
+_AsyncCallbackEntry? _lastPriorityCallback;
 /**
  * Whether we are currently inside the callback loop.
  *
@@ -35,11 +33,11 @@
 bool _isInCallbackLoop = false;
 
 void _microtaskLoop() {
-  while (_nextCallback != null) {
+  for (var entry = _nextCallback; entry != null; entry = _nextCallback) {
     _lastPriorityCallback = null;
-    _AsyncCallbackEntry entry = _nextCallback;
-    _nextCallback = entry.next;
-    if (_nextCallback == null) _lastCallback = null;
+    var next = entry.next;
+    _nextCallback = next;
+    if (next == null) _lastCallback = null;
     (entry.callback)();
   }
 }
@@ -67,13 +65,14 @@
  */
 void _scheduleAsyncCallback(_AsyncCallback callback) {
   _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback);
-  if (_nextCallback == null) {
+  _AsyncCallbackEntry? lastCallback = _lastCallback;
+  if (lastCallback == null) {
     _nextCallback = _lastCallback = newEntry;
     if (!_isInCallbackLoop) {
       _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
     }
   } else {
-    _lastCallback.next = newEntry;
+    lastCallback.next = newEntry;
     _lastCallback = newEntry;
   }
 }
@@ -93,14 +92,16 @@
     return;
   }
   _AsyncCallbackEntry entry = new _AsyncCallbackEntry(callback);
-  if (_lastPriorityCallback == null) {
+  _AsyncCallbackEntry? lastPriorityCallback = _lastPriorityCallback;
+  if (lastPriorityCallback == null) {
     entry.next = _nextCallback;
     _nextCallback = _lastPriorityCallback = entry;
   } else {
-    entry.next = _lastPriorityCallback.next;
-    _lastPriorityCallback.next = entry;
+    var next = lastPriorityCallback.next;
+    entry.next = next;
+    lastPriorityCallback.next = entry;
     _lastPriorityCallback = entry;
-    if (entry.next == null) {
+    if (next == null) {
       _lastCallback = entry;
     }
   }
@@ -132,7 +133,7 @@
  * better asynchronous code with fewer surprises.
  */
 void scheduleMicrotask(void callback()) {
-  _Zone currentZone = Zone.current;
+  _Zone currentZone = Zone._current;
   if (identical(_rootZone, currentZone)) {
     // No need to bind the callback. We know that the root's scheduleMicrotask
     // will be invoked in the root zone.
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index 26d4342..afcd3c5 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 // -------------------------------------------------------------------
@@ -152,7 +150,7 @@
    * stack trace as well.
    */
   @Since("2.5")
-  factory Stream.error(Object error, [StackTrace stackTrace]) =>
+  factory Stream.error(Object error, [StackTrace? stackTrace]) =>
       (_AsyncStreamController<T>(null, null, null, null)
             .._addError(error, stackTrace)
             .._closeUnchecked())
@@ -208,7 +206,7 @@
         if (--count == 0) controller._closeUnchecked();
       }
     };
-    var onError = (error, StackTrace stack) {
+    var onError = (Object error, StackTrace? stack) {
       if (!controller.isClosed) {
         controller._addError(error, stack);
         if (--count == 0) controller._closeUnchecked();
@@ -251,65 +249,59 @@
    * this callback is an integer that starts with 0 and is incremented for
    * every event.
    *
+   * The [period] must a non-negative [Duration].
+   *
    * If [computation] is omitted the event values will all be `null`.
    *
-   * [period] must a non-negative [Duration].
+   * The [computation] must not be omitted if the event type [T] does not
+   * allow `null` as a value.
    */
   factory Stream.periodic(Duration period,
-      [T computation(int computationCount)]) {
-    Timer timer;
-    int computationCount = 0;
-    StreamController<T> controller;
+      [T computation(int computationCount)?]) {
+    if (computation == null && null is! T) {
+      throw ArgumentError.value(null, "computation",
+          "Must not be omitted when the event type is non-nullable");
+    }
+    var controller = _SyncStreamController<T>(null, null, null, null);
     // Counts the time that the Stream was running (and not paused).
     Stopwatch watch = new Stopwatch();
-
-    void sendEvent() {
-      watch.reset();
-      T data;
-      if (computation != null) {
-        try {
-          data = computation(computationCount++);
-        } catch (e, s) {
-          controller.addError(e, s);
-          return;
+    controller.onListen = () {
+      int computationCount = 0;
+      void sendEvent(_) {
+        watch.reset();
+        if (computation != null) {
+          T event;
+          try {
+            event = computation(computationCount++);
+          } catch (e, s) {
+            controller.addError(e, s);
+            return;
+          }
+          controller.add(event);
+        } else {
+          controller.add(null as T); // We have checked that null is T.
         }
       }
-      controller.add(data);
-    }
 
-    void startPeriodicTimer() {
-      assert(timer == null);
-      timer = new Timer.periodic(period, (Timer timer) {
-        sendEvent();
-      });
-    }
-
-    controller = new StreamController<T>(
-        sync: true,
-        onListen: () {
-          watch.start();
-          startPeriodicTimer();
-        },
-        onPause: () {
+      Timer timer = Timer.periodic(period, sendEvent);
+      controller
+        ..onCancel = () {
           timer.cancel();
-          timer = null;
+          return Future._nullFuture;
+        }
+        ..onPause = () {
           watch.stop();
-        },
-        onResume: () {
-          assert(timer == null);
+          timer.cancel();
+        }
+        ..onResume = () {
           Duration elapsed = watch.elapsed;
           watch.start();
           timer = new Timer(period - elapsed, () {
-            timer = null;
-            startPeriodicTimer();
-            sendEvent();
+            timer = Timer.periodic(period, sendEvent);
+            sendEvent(null);
           });
-        },
-        onCancel: () {
-          if (timer != null) timer.cancel();
-          timer = null;
-          return Future._nullFuture;
-        });
+        };
+    };
     return controller.stream;
   }
 
@@ -354,7 +346,7 @@
    * The resulting stream is a broadcast stream if [source] is.
    */
   factory Stream.eventTransformed(
-      Stream source, EventSink mapSink(EventSink<T> sink)) {
+      Stream<dynamic> source, EventSink<dynamic> mapSink(EventSink<T> sink)) {
     return new _BoundSinkStream(source, mapSink);
   }
 
@@ -396,8 +388,8 @@
    * subscription when there are no listeners.
    */
   Stream<T> asBroadcastStream(
-      {void onListen(StreamSubscription<T> subscription),
-      void onCancel(StreamSubscription<T> subscription)}) {
+      {void onListen(StreamSubscription<T> subscription)?,
+      void onCancel(StreamSubscription<T> subscription)?}) {
     return new _AsBroadcastStream<T>(this, onListen, onCancel);
   }
 
@@ -415,8 +407,8 @@
    * On errors from this stream, the [onError] handler is called with the
    * error object and possibly a stack trace.
    *
-   * The [onError] callback must be of type `void onError(error)` or
-   * `void onError(error, StackTrace stackTrace)`. If [onError] accepts
+   * The [onError] callback must be of type `void onError(Object error)` or
+   * `void onError(Object error, StackTrace? stackTrace)`. If [onError] accepts
    * two arguments it is called with the error object and the stack trace
    * (which could be `null` if this stream itself received an error without
    * stack trace).
@@ -436,8 +428,8 @@
    * the subscription doesn't receive events and none of the
    * event handler functions are called.
    */
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError});
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError});
 
   /**
    * Creates a new stream from this stream that discards some elements.
@@ -497,15 +489,17 @@
    * The returned stream is a broadcast stream if this stream is.
    */
   Stream<E> asyncMap<E>(FutureOr<E> convert(T event)) {
-    _StreamControllerBase<E> controller;
-    StreamSubscription<T> subscription;
+    _StreamControllerBase<E> controller = isBroadcast
+        ? _SyncBroadcastStreamController<E>(null, null)
+        : _SyncStreamController<E>(null, null, null, null);
 
-    void onListen() {
+    controller.onListen = () {
+      StreamSubscription<T> subscription = this.listen(null,
+          onError: controller._addError, // Avoid Zone error replacement.
+          onDone: controller.close);
       final add = controller.add;
-      assert(controller is _StreamController<E> ||
-          controller is _BroadcastStreamController);
       final addError = controller._addError;
-      subscription = this.listen((T event) {
+      subscription.onData((T event) {
         FutureOr<E> newValue;
         try {
           newValue = convert(event);
@@ -519,30 +513,17 @@
               .then(add, onError: addError)
               .whenComplete(subscription.resume);
         } else {
+          if (newValue is! E) throw "unreachable"; // TODO(lrn): Remove when type promotion works.
           controller.add(newValue);
         }
-      }, onError: addError, onDone: controller.close);
-    }
-
-    if (this.isBroadcast) {
-      controller = new StreamController<E>.broadcast(
-          onListen: onListen,
-          onCancel: () {
-            subscription.cancel();
-          },
-          sync: true);
-    } else {
-      controller = new StreamController<E>(
-          onListen: onListen,
-          onPause: () {
-            subscription.pause();
-          },
-          onResume: () {
-            subscription.resume();
-          },
-          onCancel: () => subscription.cancel(),
-          sync: true);
-    }
+      });
+      controller.onCancel = subscription.cancel;
+      if (!isBroadcast) {
+        controller
+          ..onPause = subscription.pause
+          ..onResume = subscription.resume;
+      }
+    };
     return controller.stream;
   }
 
@@ -565,12 +546,15 @@
    * The returned stream is a broadcast stream if this stream is.
    */
   Stream<E> asyncExpand<E>(Stream<E> convert(T event)) {
-    _StreamControllerBase<E> controller;
-    StreamSubscription<T> subscription;
-    void onListen() {
-      assert(controller is _StreamController ||
-          controller is _BroadcastStreamController);
-      subscription = this.listen((T event) {
+    _StreamControllerBase<E> controller = isBroadcast
+        ? _SyncBroadcastStreamController<E>(null, null)
+        : _SyncStreamController<E>(null, null, null, null);
+
+    controller.onListen = () {
+      StreamSubscription<T> subscription = this.listen(null,
+          onError: controller._addError, // Avoid Zone error replacement.
+          onDone: controller.close);
+      subscription.onData((T event) {
         Stream<E> newStream;
         try {
           newStream = convert(event);
@@ -578,34 +562,16 @@
           controller.addError(e, s);
           return;
         }
-        if (newStream != null) {
-          subscription.pause();
-          controller.addStream(newStream).whenComplete(subscription.resume);
-        }
-      },
-          onError: controller._addError, // Avoid Zone error replacement.
-          onDone: controller.close);
-    }
-
-    if (this.isBroadcast) {
-      controller = new StreamController<E>.broadcast(
-          onListen: onListen,
-          onCancel: () {
-            subscription.cancel();
-          },
-          sync: true);
-    } else {
-      controller = new StreamController<E>(
-          onListen: onListen,
-          onPause: () {
-            subscription.pause();
-          },
-          onResume: () {
-            subscription.resume();
-          },
-          onCancel: () => subscription.cancel(),
-          sync: true);
-    }
+        subscription.pause();
+        controller.addStream(newStream).whenComplete(subscription.resume);
+      });
+      controller.onCancel = subscription.cancel;
+      if (!isBroadcast) {
+        controller
+          ..onPause = subscription.pause
+          ..onResume = subscription.resume;
+      }
+    };
     return controller.stream;
   }
 
@@ -615,8 +581,8 @@
    * If this stream sends an error that matches [test], then it is intercepted
    * by the [onError] function.
    *
-   * The [onError] callback must be of type `void onError(error)` or
-   * `void onError(error, StackTrace stackTrace)`.
+   * The [onError] callback must be of type `void onError(Object error)` or
+   * `void onError(Object error, StackTrace? stackTrace)`.
    * The function type determines whether [onError] is invoked with a stack
    * trace argument.
    * The stack trace argument may be `null` if this stream received an error
@@ -641,7 +607,7 @@
    * If a broadcast stream is listened to more than once, each subscription
    * will individually perform the `test` and handle the error.
    */
-  Stream<T> handleError(Function onError, {bool test(error)}) {
+  Stream<T> handleError(Function onError, {bool test(error)?}) {
     return new _HandleErrorStream<T>(this, onError, test);
   }
 
@@ -741,35 +707,32 @@
   Future<T> reduce(T combine(T previous, T element)) {
     _Future<T> result = new _Future<T>();
     bool seenFirst = false;
-    T value;
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          if (seenFirst) {
-            _runUserCode(() => combine(value, element), (T newValue) {
-              value = newValue;
-            }, _cancelAndErrorClosure(subscription, result));
-          } else {
-            value = element;
-            seenFirst = true;
-          }
-        },
-        onError: result._completeError,
-        onDone: () {
-          if (!seenFirst) {
-            try {
-              // Throw and recatch, instead of just doing
-              //  _completeWithErrorCallback, e, theError, StackTrace.current),
-              // to ensure that the stackTrace is set on the error.
-              throw IterableElementError.noElement();
-            } catch (e, s) {
-              _completeWithErrorCallback(result, e, s);
-            }
-          } else {
-            result._complete(value);
-          }
-        },
-        cancelOnError: true);
+    late T value;
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: result._completeError, onDone: () {
+      if (!seenFirst) {
+        try {
+          // Throw and recatch, instead of just doing
+          //  _completeWithErrorCallback, e, theError, StackTrace.current),
+          // to ensure that the stackTrace is set on the error.
+          throw IterableElementError.noElement();
+        } catch (e, s) {
+          _completeWithErrorCallback(result, e, s);
+        }
+      } else {
+        result._complete(value);
+      }
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      if (seenFirst) {
+        _runUserCode(() => combine(value, element), (T newValue) {
+          value = newValue;
+        }, _cancelAndErrorClosure(subscription, result));
+      } else {
+        value = element;
+        seenFirst = true;
+      }
+    });
     return result;
   }
 
@@ -793,18 +756,15 @@
   Future<S> fold<S>(S initialValue, S combine(S previous, T element)) {
     _Future<S> result = new _Future<S>();
     S value = initialValue;
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          _runUserCode(() => combine(value, element), (S newValue) {
-            value = newValue;
-          }, _cancelAndErrorClosure(subscription, result));
-        },
-        onError: result._completeError,
-        onDone: () {
-          result._complete(value);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: result._completeError, onDone: () {
+      result._complete(value);
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      _runUserCode(() => combine(value, element), (S newValue) {
+        value = newValue;
+      }, _cancelAndErrorClosure(subscription, result));
+    });
     return result;
   }
 
@@ -825,25 +785,30 @@
   Future<String> join([String separator = ""]) {
     _Future<String> result = new _Future<String>();
     StringBuffer buffer = new StringBuffer();
-    StreamSubscription subscription;
     bool first = true;
-    subscription = this.listen(
-        (T element) {
-          if (!first) {
-            buffer.write(separator);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: result._completeError, onDone: () {
+      result._complete(buffer.toString());
+    }, cancelOnError: true);
+    subscription.onData(separator.isEmpty
+        ? (T element) {
+            try {
+              buffer.write(element);
+            } catch (e, s) {
+              _cancelAndErrorWithReplacement(subscription, result, e, s);
+            }
           }
-          first = false;
-          try {
-            buffer.write(element);
-          } catch (e, s) {
-            _cancelAndErrorWithReplacement(subscription, result, e, s);
-          }
-        },
-        onError: result._completeError,
-        onDone: () {
-          result._complete(buffer.toString());
-        },
-        cancelOnError: true);
+        : (T element) {
+            if (!first) {
+              buffer.write(separator);
+            }
+            first = false;
+            try {
+              buffer.write(element);
+            } catch (e, s) {
+              _cancelAndErrorWithReplacement(subscription, result, e, s);
+            }
+          });
     return result;
   }
 
@@ -861,20 +826,17 @@
    */
   Future<bool> contains(Object needle) {
     _Future<bool> future = new _Future<bool>();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          _runUserCode(() => (element == needle), (bool isMatch) {
-            if (isMatch) {
-              _cancelAndValue(subscription, future, true);
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._complete(false);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      future._complete(false);
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      _runUserCode(() => (element == needle), (bool isMatch) {
+        if (isMatch) {
+          _cancelAndValue(subscription, future, true);
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -890,18 +852,14 @@
    */
   Future forEach(void action(T element)) {
     _Future future = new _Future();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          // TODO(floitsch): the type should be 'void' and inferred.
-          _runUserCode<dynamic>(() => action(element), (_) {},
-              _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._complete(null);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      future._complete(null);
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      _runUserCode<void>(() => action(element), (_) {},
+          _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -921,20 +879,17 @@
    */
   Future<bool> every(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          _runUserCode(() => test(element), (bool isMatch) {
-            if (!isMatch) {
-              _cancelAndValue(subscription, future, false);
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._complete(true);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      future._complete(true);
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      _runUserCode(() => test(element), (bool isMatch) {
+        if (!isMatch) {
+          _cancelAndValue(subscription, future, false);
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -954,20 +909,17 @@
    */
   Future<bool> any(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T element) {
-          _runUserCode(() => test(element), (bool isMatch) {
-            if (isMatch) {
-              _cancelAndValue(subscription, future, true);
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._complete(false);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      future._complete(false);
+    }, cancelOnError: true);
+    subscription.onData((T element) {
+      _runUserCode(() => test(element), (bool isMatch) {
+        if (isMatch) {
+          _cancelAndValue(subscription, future, true);
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -1015,16 +967,13 @@
    */
   Future<bool> get isEmpty {
     _Future<bool> future = new _Future<bool>();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (_) {
-          _cancelAndValue(subscription, future, false);
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._complete(true);
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      future._complete(true);
+    }, cancelOnError: true);
+    subscription.onData((_) {
+      _cancelAndValue(subscription, future, false);
+    });
     return future;
   }
 
@@ -1100,15 +1049,19 @@
    * When subscribing using [drain], cancelOnError will be true. This means
    * that the future will complete with the first error on this stream and then
    * cancel the subscription.
-   * If this stream emits an error, or the call to [combine] throws,
-   * the returned future is completed with that error,
-   * and processing is stopped.
+   *
+   * If this stream emits an error, the returned future is completed with
+   * that error, and processing is stopped.
    *
    * In case of a `done` event the future completes with the given
    * [futureValue].
+   *
+   * The [futureValue] must not be omitted if `null` is not assignable to [E].
    */
-  Future<E> drain<E>([E futureValue]) =>
-      listen(null, cancelOnError: true).asFuture<E>(futureValue);
+  Future<E> drain<E>([E? futureValue]) {
+    futureValue = futureValue as E;
+    return listen(null, cancelOnError: true).asFuture<E>(futureValue);
+  }
 
   /**
    * Provides at most the first [count] data events of this stream.
@@ -1223,7 +1176,7 @@
    * If a broadcast stream is listened to more than once, each subscription
    * will individually perform the `equals` test.
    */
-  Stream<T> distinct([bool equals(T previous, T next)]) {
+  Stream<T> distinct([bool equals(T previous, T next)?]) {
     return new _DistinctStream<T>(this, equals);
   }
 
@@ -1247,20 +1200,17 @@
    */
   Future<T> get first {
     _Future<T> future = new _Future<T>();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T value) {
-          _cancelAndValue(subscription, future, value);
-        },
-        onError: future._completeError,
-        onDone: () {
-          try {
-            throw IterableElementError.noElement();
-          } catch (e, s) {
-            _completeWithErrorCallback(future, e, s);
-          }
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      try {
+        throw IterableElementError.noElement();
+      } catch (e, s) {
+        _completeWithErrorCallback(future, e, s);
+      }
+    }, cancelOnError: true);
+    subscription.onData((T value) {
+      _cancelAndValue(subscription, future, value);
+    });
     return future;
   }
 
@@ -1276,7 +1226,7 @@
    */
   Future<T> get last {
     _Future<T> future = new _Future<T>();
-    T result;
+    late T result;
     bool foundResult = false;
     listen(
         (T value) {
@@ -1311,36 +1261,33 @@
    */
   Future<T> get single {
     _Future<T> future = new _Future<T>();
-    T result;
+    late T result;
     bool foundResult = false;
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T value) {
-          if (foundResult) {
-            // This is the second element we get.
-            try {
-              throw IterableElementError.tooMany();
-            } catch (e, s) {
-              _cancelAndErrorWithReplacement(subscription, future, e, s);
-            }
-            return;
-          }
-          foundResult = true;
-          result = value;
-        },
-        onError: future._completeError,
-        onDone: () {
-          if (foundResult) {
-            future._complete(result);
-            return;
-          }
-          try {
-            throw IterableElementError.noElement();
-          } catch (e, s) {
-            _completeWithErrorCallback(future, e, s);
-          }
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      if (foundResult) {
+        future._complete(result);
+        return;
+      }
+      try {
+        throw IterableElementError.noElement();
+      } catch (e, s) {
+        _completeWithErrorCallback(future, e, s);
+      }
+    }, cancelOnError: true);
+    subscription.onError((T value) {
+      if (foundResult) {
+        // This is the second element we get.
+        try {
+          throw IterableElementError.tooMany();
+        } catch (e, s) {
+          _cancelAndErrorWithReplacement(subscription, future, e, s);
+        }
+        return;
+      }
+      foundResult = true;
+      result = value;
+    });
     return future;
   }
 
@@ -1369,30 +1316,29 @@
    * with no [orElse] function provided,
    * the returned future is completed with an error.
    */
-  Future<T> firstWhere(bool test(T element), {T orElse()}) {
+  Future<T> firstWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T value) {
-          _runUserCode(() => test(value), (bool isMatch) {
-            if (isMatch) {
-              _cancelAndValue(subscription, future, value);
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          if (orElse != null) {
-            _runUserCode(orElse, future._complete, future._completeError);
-            return;
-          }
-          try {
-            throw IterableElementError.noElement();
-          } catch (e, s) {
-            _completeWithErrorCallback(future, e, s);
-          }
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      if (orElse != null) {
+        _runUserCode(orElse, future._complete, future._completeError);
+        return;
+      }
+      try {
+        // Sets stackTrace on error.
+        throw IterableElementError.noElement();
+      } catch (e, s) {
+        _completeWithErrorCallback(future, e, s);
+      }
+    }, cancelOnError: true);
+
+    subscription.onData((T value) {
+      _runUserCode(() => test(value), (bool isMatch) {
+        if (isMatch) {
+          _cancelAndValue(subscription, future, value);
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -1407,37 +1353,35 @@
    * That means that a non-error result cannot be provided before this stream
    * is done.
    */
-  Future<T> lastWhere(bool test(T element), {T orElse()}) {
+  Future<T> lastWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
-    T result;
+    late T result;
     bool foundResult = false;
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T value) {
-          _runUserCode(() => true == test(value), (bool isMatch) {
-            if (isMatch) {
-              foundResult = true;
-              result = value;
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
-          if (foundResult) {
-            future._complete(result);
-            return;
-          }
-          if (orElse != null) {
-            _runUserCode(orElse, future._complete, future._completeError);
-            return;
-          }
-          try {
-            throw IterableElementError.noElement();
-          } catch (e, s) {
-            _completeWithErrorCallback(future, e, s);
-          }
-        },
-        cancelOnError: true);
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      if (foundResult) {
+        future._complete(result);
+        return;
+      }
+      if (orElse != null) {
+        _runUserCode(orElse, future._complete, future._completeError);
+        return;
+      }
+      try {
+        throw IterableElementError.noElement();
+      } catch (e, s) {
+        _completeWithErrorCallback(future, e, s);
+      }
+    }, cancelOnError: true);
+
+    subscription.onData((T value) {
+      _runUserCode(() => test(value), (bool isMatch) {
+        if (isMatch) {
+          foundResult = true;
+          result = value;
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -1447,45 +1391,43 @@
    * Like [lastWhere], except that it is an error if more than one
    * matching element occurs in this stream.
    */
-  Future<T> singleWhere(bool test(T element), {T orElse()}) {
+  Future<T> singleWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future<T>();
-    T result;
+    late T result;
     bool foundResult = false;
-    StreamSubscription subscription;
-    subscription = this.listen(
-        (T value) {
-          _runUserCode(() => true == test(value), (bool isMatch) {
-            if (isMatch) {
-              if (foundResult) {
-                try {
-                  throw IterableElementError.tooMany();
-                } catch (e, s) {
-                  _cancelAndErrorWithReplacement(subscription, future, e, s);
-                }
-                return;
-              }
-              foundResult = true;
-              result = value;
-            }
-          }, _cancelAndErrorClosure(subscription, future));
-        },
-        onError: future._completeError,
-        onDone: () {
+    StreamSubscription<T> subscription =
+        this.listen(null, onError: future._completeError, onDone: () {
+      if (foundResult) {
+        future._complete(result);
+        return;
+      }
+      if (orElse != null) {
+        _runUserCode(orElse, future._complete, future._completeError);
+        return;
+      }
+      try {
+        throw IterableElementError.noElement();
+      } catch (e, s) {
+        _completeWithErrorCallback(future, e, s);
+      }
+    }, cancelOnError: true);
+
+    subscription.onData((T value) {
+      _runUserCode(() => test(value), (bool isMatch) {
+        if (isMatch) {
           if (foundResult) {
-            future._complete(result);
+            try {
+              throw IterableElementError.tooMany();
+            } catch (e, s) {
+              _cancelAndErrorWithReplacement(subscription, future, e, s);
+            }
             return;
           }
-          try {
-            if (orElse != null) {
-              _runUserCode(orElse, future._complete, future._completeError);
-              return;
-            }
-            throw IterableElementError.noElement();
-          } catch (e, s) {
-            _completeWithErrorCallback(future, e, s);
-          }
-        },
-        cancelOnError: true);
+          foundResult = true;
+          result = value;
+        }
+      }, _cancelAndErrorClosure(subscription, future));
+    });
     return future;
   }
 
@@ -1506,26 +1448,24 @@
    * with a [RangeError].
    */
   Future<T> elementAt(int index) {
-    ArgumentError.checkNotNull(index, "index");
     RangeError.checkNotNegative(index, "index");
-    _Future<T> future = new _Future<T>();
-    StreamSubscription subscription;
+    _Future<T> result = new _Future<T>();
     int elementIndex = 0;
-    subscription = this.listen(
-        (T value) {
-          if (index == elementIndex) {
-            _cancelAndValue(subscription, future, value);
-            return;
-          }
-          elementIndex += 1;
-        },
-        onError: future._completeError,
-        onDone: () {
-          future._completeError(
-              new RangeError.index(index, this, "index", null, elementIndex));
-        },
-        cancelOnError: true);
-    return future;
+    StreamSubscription<T> subscription;
+    subscription =
+        this.listen(null, onError: result._completeError, onDone: () {
+      result._completeError(
+          new RangeError.index(index, this, "index", null, elementIndex));
+    }, cancelOnError: true);
+    subscription.onData((T value) {
+      if (index == elementIndex) {
+        _cancelAndValue(subscription, result, value);
+        return;
+      }
+      elementIndex += 1;
+    });
+
+    return result;
   }
 
   /**
@@ -1555,81 +1495,75 @@
    * will have its individually timer that starts counting on listen,
    * and the subscriptions' timers can be paused individually.
    */
-  Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) {
-    _StreamControllerBase<T> controller;
-    // The following variables are set on listen.
-    StreamSubscription<T> subscription;
-    Timer timer;
-    Zone zone;
-    _TimerCallback timeout;
+  Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)?}) {
+    _StreamControllerBase<T> controller = isBroadcast
+        ? new _SyncBroadcastStreamController<T>(null, null)
+        : new _SyncStreamController<T>(null, null, null, null);
 
-    void onData(T event) {
-      timer.cancel();
-      timer = zone.createTimer(timeLimit, timeout);
-      // It might close the stream and cancel timer, so create recuring Timer
-      // before calling into add();
-      // issue: https://github.com/dart-lang/sdk/issues/37565
-      controller.add(event);
+    Zone zone = Zone.current;
+    // Register callback immediately.
+    _TimerCallback timeoutCallback;
+    if (onTimeout == null) {
+      timeoutCallback = () {
+        controller.addError(
+            new TimeoutException("No stream event", timeLimit), null);
+      };
+    } else {
+      // TODO(floitsch): the return type should be 'void', and the type
+      // should be inferred.
+      var registeredOnTimeout =
+          zone.registerUnaryCallback<void, EventSink<T>>(onTimeout);
+      var wrapper = new _ControllerEventSinkWrapper<T>(null);
+      timeoutCallback = () {
+        wrapper._sink = controller; // Only valid during call.
+        zone.runUnaryGuarded(registeredOnTimeout, wrapper);
+        wrapper._sink = null;
+      };
     }
 
-    void onError(error, StackTrace stackTrace) {
-      timer.cancel();
-      assert(controller is _StreamController ||
-          controller is _BroadcastStreamController);
-      controller._addError(error, stackTrace); // Avoid Zone error replacement.
-      timer = zone.createTimer(timeLimit, timeout);
-    }
-
-    void onDone() {
-      timer.cancel();
-      controller.close();
-    }
-
-    void onListen() {
-      // This is the onListen callback for of controller.
-      // It runs in the same zone that the subscription was created in.
-      // Use that zone for creating timers and running the onTimeout
-      // callback.
-      zone = Zone.current;
-      if (onTimeout == null) {
-        timeout = () {
-          controller.addError(
-              new TimeoutException("No stream event", timeLimit), null);
-        };
-      } else {
-        // TODO(floitsch): the return type should be 'void', and the type
-        // should be inferred.
-        var registeredOnTimeout =
-            zone.registerUnaryCallback<dynamic, EventSink<T>>(onTimeout);
-        var wrapper = new _ControllerEventSinkWrapper<T>(null);
-        timeout = () {
-          wrapper._sink = controller; // Only valid during call.
-          zone.runUnaryGuarded(registeredOnTimeout, wrapper);
-          wrapper._sink = null;
-        };
-      }
-
-      subscription = this.listen(onData, onError: onError, onDone: onDone);
-      timer = zone.createTimer(timeLimit, timeout);
-    }
-
-    Future onCancel() {
-      timer.cancel();
-      Future result = subscription.cancel();
-      subscription = null;
-      return result;
-    }
-
-    controller = isBroadcast
-        ? new _SyncBroadcastStreamController<T>(onListen, onCancel)
-        : new _SyncStreamController<T>(onListen, () {
-            // Don't null the timer, onCancel may call cancel again.
+    // All further setup happens inside `onListen`.
+    controller.onListen = () {
+      Timer timer = zone.createTimer(timeLimit, timeoutCallback);
+      var subscription = this.listen(null);
+      // Set up event forwarding. Each data or error event resets the timer
+      subscription
+        ..onData((T event) {
+          timer.cancel();
+          timer = zone.createTimer(timeLimit, timeoutCallback);
+          // Controller is synchronous, and the call might close the stream
+          // and cancel the timer,
+          // so create the Timer before calling into add();
+          // issue: https://github.com/dart-lang/sdk/issues/37565
+          controller.add(event);
+        })
+        ..onError((Object error, StackTrace? stackTrace) {
+          timer.cancel();
+          timer = zone.createTimer(timeLimit, timeoutCallback);
+          controller._addError(
+              error, stackTrace); // Avoid Zone error replacement.
+        })
+        ..onDone(() {
+          timer.cancel();
+          controller.close();
+        });
+      // Set up further controller callbacks.
+      controller.onCancel = () {
+        timer.cancel();
+        return subscription.cancel();
+      };
+      if (!isBroadcast) {
+        controller
+          ..onPause = () {
             timer.cancel();
             subscription.pause();
-          }, () {
+          }
+          ..onResume = () {
             subscription.resume();
-            timer = zone.createTimer(timeLimit, timeout);
-          }, onCancel);
+            timer = zone.createTimer(timeLimit, timeoutCallback);
+          };
+      }
+    };
+
     return controller.stream;
   }
 }
@@ -1669,7 +1603,7 @@
    * If the cleanup throws, which it really shouldn't, the returned future
    * completes with that error.
    */
-  Future cancel();
+  Future<void> cancel();
 
   /**
    * Replaces the data event handler of this subscription.
@@ -1681,7 +1615,7 @@
    * This method replaces the current handler set by the invocation of
    * [Stream.listen] or by a previous call to [onData].
    */
-  void onData(void handleData(T data));
+  void onData(void handleData(T data)?);
 
   /**
    * Replaces the error event handler of this subscription.
@@ -1700,7 +1634,7 @@
    * This method replaces the current handler set by the invocation of
    * [Stream.listen], by calling [asFuture], or by a previous call to [onError].
    */
-  void onError(Function handleError);
+  void onError(Function? handleError);
 
   /**
    * Replaces the done event handler of this subscription.
@@ -1711,7 +1645,7 @@
    * This method replaces the current handler set by the invocation of
    * [Stream.listen], by calling [asFuture], or by a previous call to [onDone].
    */
-  void onDone(void handleDone());
+  void onDone(void handleDone()?);
 
   /**
    * Request that the stream pauses events until further notice.
@@ -1748,7 +1682,7 @@
    * Currently DOM streams silently drop events when the stream is paused. This
    * is a bug and will be fixed.
    */
-  void pause([Future resumeSignal]);
+  void pause([Future<void>? resumeSignal]);
 
   /**
    * Resume after a pause.
@@ -1786,8 +1720,12 @@
    *
    * In case of a `done` event the future completes with the given
    * [futureValue].
+   *
+   * If [futureValue] is omitted, the value `null as E` is used as a default.
+   * If `E` is not nullable, this will throw immediately when [asFuture]
+   * is called.
    */
-  Future<E> asFuture<E>([E futureValue]);
+  Future<E> asFuture<E>([E? futureValue]);
 }
 
 /**
@@ -1813,7 +1751,7 @@
    *
    * Must not be called on a closed sink.
    */
-  void addError(Object error, [StackTrace stackTrace]);
+  void addError(Object error, [StackTrace? stackTrace]);
 
   /**
    * Closes the sink.
@@ -1836,12 +1774,12 @@
   bool get isBroadcast => _stream.isBroadcast;
 
   Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription),
-          void onCancel(StreamSubscription<T> subscription)}) =>
+          {void onListen(StreamSubscription<T> subscription)?,
+          void onCancel(StreamSubscription<T> subscription)?}) =>
       _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel);
 
-  StreamSubscription<T> listen(void onData(T value),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void onData(T value)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     return _stream.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -2094,9 +2032,10 @@
    * ```
    */
   factory StreamTransformer.fromHandlers(
-      {void handleData(S data, EventSink<T> sink),
-      void handleError(Object error, StackTrace stackTrace, EventSink<T> sink),
-      void handleDone(EventSink<T> sink)}) = _StreamHandlerTransformer<S, T>;
+      {void handleData(S data, EventSink<T> sink)?,
+      void handleError(
+          Object error, StackTrace? stackTrace, EventSink<T> sink)?,
+      void handleDone(EventSink<T> sink)?}) = _StreamHandlerTransformer<S, T>;
 
   /**
    * Creates a [StreamTransformer] based on a [bind] callback.
@@ -2254,18 +2193,24 @@
  * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
  */
 class _ControllerEventSinkWrapper<T> implements EventSink<T> {
-  EventSink _sink;
+  EventSink? _sink;
   _ControllerEventSinkWrapper(this._sink);
 
-  void add(T data) {
-    _sink.add(data);
+  EventSink _ensureSink() {
+    var sink = _sink;
+    if (sink == null) throw StateError("Sink not available");
+    return sink;
   }
 
-  void addError(error, [StackTrace stackTrace]) {
-    _sink.addError(error, stackTrace);
+  void add(T data) {
+    _ensureSink().add(data);
+  }
+
+  void addError(error, [StackTrace? stackTrace]) {
+    _ensureSink().addError(error, stackTrace);
   }
 
   void close() {
-    _sink.close();
+    _ensureSink().close();
   }
 }
diff --git a/sdk_nnbd/lib/async/stream_controller.dart b/sdk_nnbd/lib/async/stream_controller.dart
index f8f2d6d..9303b86 100644
--- a/sdk_nnbd/lib/async/stream_controller.dart
+++ b/sdk_nnbd/lib/async/stream_controller.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 // -------------------------------------------------------------------
@@ -20,7 +18,7 @@
  *
  * The callback may return either `void` or a future.
  */
-typedef ControllerCancelCallback();
+typedef FutureOr<void> ControllerCancelCallback();
 
 /**
  * A controller with the stream it controls.
@@ -74,18 +72,18 @@
    * [onCancel] should return a future that completes when the cancel operation
    * is done.
    *
-   * If the stream is canceled before the controller needs new data the
+   * If the stream is canceled before the controller needs data the
    * [onResume] call might not be executed.
    */
   factory StreamController(
-      {void onListen(),
-      void onPause(),
-      void onResume(),
-      onCancel(),
-      bool sync: false}) {
+      {void onListen()?,
+      void onPause()?,
+      void onResume()?,
+      FutureOr<void> onCancel()?,
+      bool sync = false}) {
     return sync
-        ? new _SyncStreamController<T>(onListen, onPause, onResume, onCancel)
-        : new _AsyncStreamController<T>(onListen, onPause, onResume, onCancel);
+        ? _SyncStreamController<T>(onListen, onPause, onResume, onCancel)
+        : _AsyncStreamController<T>(onListen, onPause, onResume, onCancel);
   }
 
   /**
@@ -140,10 +138,10 @@
    * the [onListen] will be called again.
    */
   factory StreamController.broadcast(
-      {void onListen(), void onCancel(), bool sync: false}) {
+      {void onListen()?, void onCancel()?, bool sync = false}) {
     return sync
-        ? new _SyncBroadcastStreamController<T>(onListen, onCancel)
-        : new _AsyncBroadcastStreamController<T>(onListen, onCancel);
+        ? _SyncBroadcastStreamController<T>(onListen, onCancel)
+        : _AsyncBroadcastStreamController<T>(onListen, onCancel);
   }
 
   /**
@@ -151,9 +149,9 @@
    *
    * May be set to `null`, in which case no callback will happen.
    */
-  ControllerCallback get onListen;
+  void Function()? get onListen;
 
-  void set onListen(void onListenHandler());
+  void set onListen(void onListenHandler()?);
 
   /**
    * The callback which is called when the stream is paused.
@@ -162,9 +160,9 @@
    *
    * Pause related callbacks are not supported on broadcast stream controllers.
    */
-  ControllerCallback get onPause;
+  void Function()? get onPause;
 
-  void set onPause(void onPauseHandler());
+  void set onPause(void onPauseHandler()?);
 
   /**
    * The callback which is called when the stream is resumed.
@@ -173,18 +171,18 @@
    *
    * Pause related callbacks are not supported on broadcast stream controllers.
    */
-  ControllerCallback get onResume;
+  void Function()? get onResume;
 
-  void set onResume(void onResumeHandler());
+  void set onResume(void onResumeHandler()?);
 
   /**
    * The callback which is called when the stream is canceled.
    *
    * May be set to `null`, in which case no callback will happen.
    */
-  ControllerCancelCallback get onCancel;
+  FutureOr<void> Function()? get onCancel;
 
-  void set onCancel(onCancelHandler());
+  void set onCancel(FutureOr<void> onCancelHandler()?);
 
   /**
    * Returns a view of this object that only exposes the [StreamSink] interface.
@@ -244,7 +242,7 @@
    * controllers have to satisfy the preconditions mentioned in the
    * documentation of the constructors.
    */
-  void addError(Object error, [StackTrace stackTrace]);
+  void addError(Object error, [StackTrace? stackTrace]);
 
   /**
    * Closes the stream.
@@ -273,9 +271,9 @@
    * forwarded to the controller's stream, and the `addStream` ends
    * after this. If [cancelOnError] is false, all errors are forwarded
    * and only a done event will end the `addStream`.
-   * If [cancelOnError] is omitted, it defaults to false.
+   * If [cancelOnError] is omitted or `null`, it defaults to false.
    */
-  Future addStream(Stream<T> source, {bool cancelOnError});
+  Future addStream(Stream<T> source, {bool? cancelOnError});
 }
 
 /**
@@ -364,7 +362,7 @@
    * As [StreamController.addError], but must not be called while an event is
    * being added by [add], [addError] or [close].
    */
-  void addError(Object error, [StackTrace stackTrace]);
+  void addError(Object error, [StackTrace? stackTrace]);
 
   /**
    * Closes the controller's stream.
@@ -376,11 +374,11 @@
 }
 
 abstract class _StreamControllerLifecycle<T> {
-  StreamSubscription<T> _subscribe(
-      void onData(T data), Function onError, void onDone(), bool cancelOnError);
+  StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
+      void onDone()?, bool cancelOnError);
   void _recordPause(StreamSubscription<T> subscription) {}
   void _recordResume(StreamSubscription<T> subscription) {}
-  Future _recordCancel(StreamSubscription<T> subscription) => null;
+  Future<void>? _recordCancel(StreamSubscription<T> subscription) => null;
 }
 
 // Base type for implementations of stream controllers.
@@ -445,9 +443,10 @@
    *
    * While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription.
    *
-   * When [_state] is [_STATE_CANCELED] the field is currently not used.
+   * When [_state] is [_STATE_CANCELED] the field is currently not used,
+   * and will contain `null`.
    */
-  var _varData;
+  Object? _varData;
 
   /** Current state of the controller. */
   int _state = _STATE_INITIAL;
@@ -460,22 +459,22 @@
   // TODO(lrn): Could this be stored in the varData field too, if it's not
   // accessed until the call to "close"? Then we need to special case if it's
   // accessed earlier, or if close is called before subscribing.
-  _Future _doneFuture;
+  _Future<void>? _doneFuture;
 
-  ControllerCallback onListen;
-  ControllerCallback onPause;
-  ControllerCallback onResume;
-  ControllerCancelCallback onCancel;
+  void Function()? onListen;
+  void Function()? onPause;
+  void Function()? onResume;
+  FutureOr<void> Function()? onCancel;
 
   _StreamController(this.onListen, this.onPause, this.onResume, this.onCancel);
 
   // Return a new stream every time. The streams are equal, but not identical.
-  Stream<T> get stream => new _ControllerStream<T>(this);
+  Stream<T> get stream => _ControllerStream<T>(this);
 
   /**
    * Returns a view of this object that only exposes the [StreamSink] interface.
    */
-  StreamSink<T> get sink => new _StreamSinkWrapper<T>(this);
+  StreamSink<T> get sink => _StreamSinkWrapper<T>(this);
 
   /**
    * Whether a listener has existed and been canceled.
@@ -511,9 +510,9 @@
   _PendingEvents<T> get _pendingEvents {
     assert(_isInitialState);
     if (!_isAddingStream) {
-      return _varData;
+      return _varData as _PendingEvents<T>;
     }
-    _StreamControllerAddStreamState<T> state = _varData;
+    var state = _varData as _StreamControllerAddStreamState<T>;
     return state.varData;
   }
 
@@ -521,12 +520,18 @@
   _StreamImplEvents<T> _ensurePendingEvents() {
     assert(_isInitialState);
     if (!_isAddingStream) {
-      _varData ??= new _StreamImplEvents<T>();
-      return _varData;
+      Object? events = _varData;
+      if (events is! _StreamImplEvents<T>) {
+        _varData = events = _StreamImplEvents<T>();
+      }
+      return events;
     }
-    _StreamControllerAddStreamState<T> state = _varData;
-    if (state.varData == null) state.varData = new _StreamImplEvents<T>();
-    return state.varData;
+    var state = _varData as _StreamControllerAddStreamState<T>;
+    Object? events = state.varData;
+    if (events is! _StreamImplEvents<T>) {
+      state.varData = events = _StreamImplEvents<T>();
+    }
+    return events;
   }
 
   // Get the current subscription.
@@ -534,11 +539,11 @@
   // object to allow the state object to use the _varData field.
   _ControllerSubscription<T> get _subscription {
     assert(hasListener);
+    Object? varData = _varData;
     if (_isAddingStream) {
-      _StreamControllerAddStreamState<T> addState = _varData;
-      return addState.varData;
+      varData = (varData as _StreamControllerAddStreamState<Object?>).varData;
     }
-    return _varData;
+    return _varData as _ControllerSubscription<T>;
   }
 
   /**
@@ -548,18 +553,18 @@
    */
   Error _badEventState() {
     if (isClosed) {
-      return new StateError("Cannot add event after closing");
+      return StateError("Cannot add event after closing");
     }
     assert(_isAddingStream);
-    return new StateError("Cannot add event while adding a stream");
+    return StateError("Cannot add event while adding a stream");
   }
 
   // StreamSink interface.
-  Future addStream(Stream<T> source, {bool cancelOnError}) {
+  Future addStream(Stream<T> source, {bool? cancelOnError}) {
     if (!_mayAddEvent) throw _badEventState();
-    if (_isCanceled) return new _Future.immediate(null);
+    if (_isCanceled) return _Future.immediate(null);
     _StreamControllerAddStreamState<T> addState =
-        new _StreamControllerAddStreamState<T>(
+        _StreamControllerAddStreamState<T>(
             this, _varData, source, cancelOnError ?? false);
     _varData = addState;
     _state |= _STATE_ADDSTREAM;
@@ -573,12 +578,10 @@
    * This happens either when the done event has been sent, or if the
    * subscriber of a single-subscription stream is cancelled.
    */
-  Future get done => _ensureDoneFuture();
+  Future<void> get done => _ensureDoneFuture();
 
-  Future _ensureDoneFuture() {
-    _doneFuture ??= _isCanceled ? Future._nullFuture : new _Future();
-    return _doneFuture;
-  }
+  Future<void> _ensureDoneFuture() =>
+      _doneFuture ??= _isCanceled ? Future._nullFuture : _Future<void>();
 
   /**
    * Send or enqueue a data event.
@@ -591,12 +594,11 @@
   /**
    * Send or enqueue an error event.
    */
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     if (!_mayAddEvent) throw _badEventState();
-    error = _nonNullError(error);
-    AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+    AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
-      error = _nonNullError(replacement.error);
+      error = replacement.error;
       stackTrace = replacement.stackTrace;
     }
     _addError(error, stackTrace);
@@ -641,22 +643,22 @@
     if (hasListener) {
       _sendData(value);
     } else if (_isInitialState) {
-      _ensurePendingEvents().add(new _DelayedData<T>(value));
+      _ensurePendingEvents().add(_DelayedData<T>(value));
     }
   }
 
-  void _addError(Object error, StackTrace stackTrace) {
+  void _addError(Object error, StackTrace? stackTrace) {
     if (hasListener) {
       _sendError(error, stackTrace);
     } else if (_isInitialState) {
-      _ensurePendingEvents().add(new _DelayedError(error, stackTrace));
+      _ensurePendingEvents().add(_DelayedError(error, stackTrace));
     }
   }
 
   void _close() {
     // End of addStream stream.
     assert(_isAddingStream);
-    _StreamControllerAddStreamState<T> addState = _varData;
+    var addState = _varData as _StreamControllerAddStreamState<T>;
     _varData = addState.varData;
     _state &= ~_STATE_ADDSTREAM;
     addState.complete();
@@ -664,18 +666,18 @@
 
   // _StreamControllerLifeCycle interface
 
-  StreamSubscription<T> _subscribe(void onData(T data), Function onError,
-      void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
+      void onDone()?, bool cancelOnError) {
     if (!_isInitialState) {
-      throw new StateError("Stream has already been listened to.");
+      throw StateError("Stream has already been listened to.");
     }
-    _ControllerSubscription<T> subscription = new _ControllerSubscription<T>(
+    _ControllerSubscription<T> subscription = _ControllerSubscription<T>(
         this, onData, onError, onDone, cancelOnError);
 
     _PendingEvents<T> pendingEvents = _pendingEvents;
     _state |= _STATE_SUBSCRIBED;
     if (_isAddingStream) {
-      _StreamControllerAddStreamState<T> addState = _varData;
+      var addState = _varData as _StreamControllerAddStreamState<T>;
       addState.varData = subscription;
       addState.resume();
     } else {
@@ -689,7 +691,7 @@
     return subscription;
   }
 
-  Future _recordCancel(StreamSubscription<T> subscription) {
+  Future<void>? _recordCancel(StreamSubscription<T> subscription) {
     // When we cancel, we first cancel any stream being added,
     // Then we call `onCancel`, and finally the _doneFuture is completed.
     // If either of addStream's cancel or `onCancel` returns a future,
@@ -698,26 +700,30 @@
     // If more errors happen, we act as if it happens inside nested try/finallys
     // or whenComplete calls, and only the last error ends up in the
     // returned future.
-    Future result;
+    Future<void>? result;
     if (_isAddingStream) {
-      _StreamControllerAddStreamState<T> addState = _varData;
+      var addState = _varData as _StreamControllerAddStreamState<T>;
       result = addState.cancel();
     }
     _varData = null;
     _state =
         (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED;
 
+    var onCancel = this.onCancel;
     if (onCancel != null) {
       if (result == null) {
         // Only introduce a future if one is needed.
         // If _onCancel returns null, no future is needed.
         try {
-          result = onCancel();
+          var cancelResult = onCancel();
+          if (cancelResult is Future<void>) {
+            result = cancelResult;
+          }
         } catch (e, s) {
           // Return the error in the returned future.
           // Complete it asynchronously, so there is time for a listener
           // to handle the error.
-          result = new _Future().._asyncCompleteError(e, s);
+          result = _Future().._asyncCompleteError(e, s);
         }
       } else {
         // Simpler case when we already know that we will return a future.
@@ -726,8 +732,9 @@
     }
 
     void complete() {
-      if (_doneFuture != null && _doneFuture._mayComplete) {
-        _doneFuture._asyncComplete(null);
+      var doneFuture = _doneFuture;
+      if (doneFuture != null && doneFuture._mayComplete) {
+        doneFuture._asyncComplete(null);
       }
     }
 
@@ -742,7 +749,7 @@
 
   void _recordPause(StreamSubscription<T> subscription) {
     if (_isAddingStream) {
-      _StreamControllerAddStreamState<T> addState = _varData;
+      var addState = _varData as _StreamControllerAddStreamState<T>;
       addState.pause();
     }
     _runGuarded(onPause);
@@ -750,7 +757,7 @@
 
   void _recordResume(StreamSubscription<T> subscription) {
     if (_isAddingStream) {
-      _StreamControllerAddStreamState<T> addState = _varData;
+      var addState = _varData as _StreamControllerAddStreamState<T>;
       addState.resume();
     }
     _runGuarded(onResume);
@@ -766,7 +773,7 @@
     _subscription._add(data);
   }
 
-  void _sendError(Object error, StackTrace stackTrace) {
+  void _sendError(Object error, StackTrace? stackTrace) {
     _subscription._addError(error, stackTrace);
   }
 
@@ -778,11 +785,11 @@
 abstract class _AsyncStreamControllerDispatch<T>
     implements _StreamController<T> {
   void _sendData(T data) {
-    _subscription._addPending(new _DelayedData<T>(data));
+    _subscription._addPending(_DelayedData<T>(data));
   }
 
-  void _sendError(Object error, StackTrace stackTrace) {
-    _subscription._addPending(new _DelayedError(error, stackTrace));
+  void _sendError(Object error, StackTrace? stackTrace) {
+    _subscription._addPending(_DelayedError(error, stackTrace));
   }
 
   void _sendDone() {
@@ -799,9 +806,7 @@
 class _SyncStreamController<T> = _StreamController<T>
     with _SyncStreamControllerDispatch<T>;
 
-typedef _NotificationHandler();
-
-void _runGuarded(_NotificationHandler notificationHandler) {
+void _runGuarded(void Function()? notificationHandler) {
   if (notificationHandler == null) return;
   try {
     notificationHandler();
@@ -815,8 +820,8 @@
 
   _ControllerStream(this._controller);
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-          Function onError, void onDone(), bool cancelOnError) =>
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+          Function? onError, void onDone()?, bool cancelOnError) =>
       _controller._subscribe(onData, onError, onDone, cancelOnError);
 
   // Override == and hashCode so that new streams returned by the same
@@ -835,11 +840,11 @@
 class _ControllerSubscription<T> extends _BufferingStreamSubscription<T> {
   final _StreamControllerLifecycle<T> _controller;
 
-  _ControllerSubscription(this._controller, void onData(T data),
-      Function onError, void onDone(), bool cancelOnError)
+  _ControllerSubscription(this._controller, void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError)
       : super(onData, onError, onDone, cancelOnError);
 
-  Future _onCancel() {
+  Future<void>? _onCancel() {
     return _controller._recordCancel(this);
   }
 
@@ -860,7 +865,7 @@
     _target.add(data);
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     _target.addError(error, stackTrace);
   }
 
@@ -883,7 +888,7 @@
 
   _AddStreamState(
       _EventSink<T> controller, Stream<T> source, bool cancelOnError)
-      : addStreamFuture = new _Future(),
+      : addStreamFuture = _Future(),
         addSubscription = source.listen(controller._add,
             onError: cancelOnError
                 ? makeErrorHandler(controller)
@@ -891,7 +896,7 @@
             onDone: controller._close,
             cancelOnError: cancelOnError);
 
-  static makeErrorHandler(_EventSink controller) => (e, StackTrace s) {
+  static makeErrorHandler(_EventSink controller) => (Object e, StackTrace? s) {
         controller._addError(e, s);
         controller._close();
       };
@@ -912,11 +917,11 @@
    *
    * Return a future if the cancel takes time, otherwise return `null`.
    */
-  Future cancel() {
+  Future<void> cancel() {
     var cancel = addSubscription.cancel();
     if (cancel == null) {
       addStreamFuture._asyncComplete(null);
-      return null;
+      return Future._nullFuture;
     }
     return cancel.whenComplete(() {
       addStreamFuture._asyncComplete(null);
diff --git a/sdk_nnbd/lib/async/stream_impl.dart b/sdk_nnbd/lib/async/stream_impl.dart
index fac736c..c5f331c 100644
--- a/sdk_nnbd/lib/async/stream_impl.dart
+++ b/sdk_nnbd/lib/async/stream_impl.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /** Abstract and private interface for a place to put events. */
 abstract class _EventSink<T> {
   void _add(T data);
-  void _addError(Object error, StackTrace stackTrace);
+  void _addError(Object error, StackTrace? stackTrace);
   void _close();
 }
 
@@ -22,7 +20,7 @@
  */
 abstract class _EventDispatch<T> {
   void _sendData(T data);
-  void _sendError(Object error, StackTrace stackTrace);
+  void _sendError(Object error, StackTrace? stackTrace);
   void _sendDone();
 }
 
@@ -92,29 +90,33 @@
   _DataHandler<T> _onData;
   Function _onError;
   _DoneHandler _onDone;
-  final Zone _zone = Zone.current;
+
+  final Zone _zone;
 
   /** Bit vector based on state-constants above. */
   int _state;
 
   // TODO(floitsch): reuse another field
   /** The future [_onCancel] may return. */
-  Future _cancelFuture;
+  Future? _cancelFuture;
 
   /**
    * Queue of pending events.
    *
    * Is created when necessary, or set in constructor for preconfigured events.
    */
-  _PendingEvents<T> _pending;
+  _PendingEvents<T>? _pending;
 
-  _BufferingStreamSubscription(
-      void onData(T data), Function onError, void onDone(), bool cancelOnError)
-      : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) {
-    this.onData(onData);
-    this.onError(onError);
-    this.onDone(onDone);
-  }
+  _BufferingStreamSubscription(void onData(T data)?, Function? onError,
+      void onDone()?, bool cancelOnError)
+      : this.zoned(Zone.current, onData, onError, onDone, cancelOnError);
+
+  _BufferingStreamSubscription.zoned(this._zone, void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError)
+      : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0),
+        _onData = _registerDataHandler<T>(_zone, onData),
+        _onError = _registerErrorHandler(_zone, onError),
+        _onDone = _registerDoneHandler(_zone, onDone);
 
   /**
    * Sets the subscription's pending events object.
@@ -128,45 +130,56 @@
     _pending = pendingEvents;
     if (!pendingEvents.isEmpty) {
       _state |= _STATE_HAS_PENDING;
-      _pending.schedule(this);
+      pendingEvents.schedule(this);
     }
   }
 
   // StreamSubscription interface.
 
-  void onData(void handleData(T event)) {
-    handleData ??= _nullDataHandler;
-    // TODO(floitsch): the return type should be 'void', and the type
-    // should be inferred.
-    _onData = _zone.registerUnaryCallback<dynamic, T>(handleData);
+  void onData(void handleData(T event)?) {
+    _onData = _registerDataHandler<T>(_zone, handleData);
   }
 
-  void onError(Function handleError) {
+  static void Function(T) _registerDataHandler<T>(
+      Zone zone, void Function(T)? handleData) {
+    return zone.registerUnaryCallback<void, T>(handleData ?? _nullDataHandler);
+  }
+
+  void onError(Function? handleError) {
+    _onError = _registerErrorHandler(_zone, handleError);
+  }
+
+  static Function _registerErrorHandler(Zone zone, Function? handleError) {
+    // TODO(lrn): Consider whether we need to register the null handler.
     handleError ??= _nullErrorHandler;
-    if (handleError is void Function(Object, StackTrace)) {
-      _onError = _zone
-          .registerBinaryCallback<dynamic, Object, StackTrace>(handleError);
-    } else if (handleError is void Function(Object)) {
-      _onError = _zone.registerUnaryCallback<dynamic, Object>(handleError);
-    } else {
-      throw new ArgumentError("handleError callback must take either an Object "
-          "(the error), or both an Object (the error) and a StackTrace.");
+    if (handleError is void Function(Object, StackTrace?)) {
+      return zone
+          .registerBinaryCallback<dynamic, Object, StackTrace?>(handleError);
     }
+    if (handleError is void Function(Object)) {
+      return zone.registerUnaryCallback<dynamic, Object>(handleError);
+    }
+    throw new ArgumentError("handleError callback must take either an Object "
+        "(the error), or both an Object (the error) and a StackTrace.");
   }
 
-  void onDone(void handleDone()) {
-    handleDone ??= _nullDoneHandler;
-    _onDone = _zone.registerCallback(handleDone);
+  void onDone(void handleDone()?) {
+    _onDone = _registerDoneHandler(_zone, handleDone);
   }
 
-  void pause([Future resumeSignal]) {
+  static void Function() _registerDoneHandler(
+      Zone zone, void Function()? handleDone) {
+    return zone.registerCallback(handleDone ?? _nullDoneHandler);
+  }
+
+  void pause([Future<void>? resumeSignal]) {
     if (_isCanceled) return;
     bool wasPaused = _isPaused;
     bool wasInputPaused = _isInputPaused;
     // Increment pause count and mark input paused (if it isn't already).
     _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED;
-    if (resumeSignal != null) resumeSignal.whenComplete(resume);
-    if (!wasPaused && _pending != null) _pending.cancelSchedule();
+    resumeSignal?.whenComplete(resume);
+    if (!wasPaused) _pending?.cancelSchedule();
     if (!wasInputPaused && !_inCallback) _guardCallback(_onPause);
   }
 
@@ -175,9 +188,9 @@
     if (_isPaused) {
       _decrementPauseCount();
       if (!_isPaused) {
-        if (_hasPending && !_pending.isEmpty) {
+        if (_hasPending && !_pending!.isEmpty) {
           // Input is still paused.
-          _pending.schedule(this);
+          _pending!.schedule(this);
         } else {
           assert(_mayResumeInput);
           _state &= ~_STATE_INPUT_PAUSED;
@@ -198,25 +211,27 @@
     return _cancelFuture ?? Future._nullFuture;
   }
 
-  Future<E> asFuture<E>([E futureValue]) {
-    _Future<E> result = new _Future<E>();
-
-    // Overwrite the onDone and onError handlers.
-    _onDone = () {
-      result._complete(futureValue);
-    };
-    _onError = (error, StackTrace stackTrace) {
-      Future cancelFuture = cancel();
-      if (!identical(cancelFuture, Future._nullFuture)) {
-        cancelFuture.whenComplete(() {
+  Future<E> asFuture<E>([E? futureValue]) {
+    if (futureValue is E) {
+      // Overwrite the onDone and onError handlers.
+      _Future<E> result = new _Future<E>();
+      E resultValue = futureValue;
+      _onDone = () {
+        result._complete(resultValue);
+      };
+      _onError = (Object error, StackTrace? stackTrace) {
+        Future cancelFuture = cancel();
+        if (!identical(cancelFuture, Future._nullFuture)) {
+          cancelFuture.whenComplete(() {
+            result._completeError(error, stackTrace);
+          });
+        } else {
           result._completeError(error, stackTrace);
-        });
-      } else {
-        result._completeError(error, stackTrace);
-      }
-    };
-
-    return result;
+        }
+      };
+      return result;
+    }
+    throw ArgumentError.notNull("futureValue");
   }
 
   // State management.
@@ -229,8 +244,7 @@
   bool get _hasPending => (_state & _STATE_HAS_PENDING) != 0;
   bool get _isPaused => _state >= _STATE_PAUSE_COUNT;
   bool get _canFire => _state < _STATE_IN_CALLBACK;
-  bool get _mayResumeInput =>
-      !_isPaused && (_pending == null || _pending.isEmpty);
+  bool get _mayResumeInput => !_isPaused && (_pending?.isEmpty ?? true);
   bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0;
 
   bool get isPaused => _isPaused;
@@ -238,7 +252,7 @@
   void _cancel() {
     _state |= _STATE_CANCELED;
     if (_hasPending) {
-      _pending.cancelSchedule();
+      _pending!.cancelSchedule();
     }
     if (!_inCallback) _pending = null;
     _cancelFuture = _onCancel();
@@ -268,7 +282,7 @@
     }
   }
 
-  void _addError(Object error, StackTrace stackTrace) {
+  void _addError(Object error, StackTrace? stackTrace) {
     if (_isCanceled) return;
     if (_canFire) {
       _sendError(error, stackTrace); // Reports cancel after sending.
@@ -300,7 +314,7 @@
     assert(!_isInputPaused);
   }
 
-  Future _onCancel() {
+  Future<void>? _onCancel() {
     assert(_isCanceled);
     return null;
   }
@@ -314,15 +328,17 @@
    * of pending events later (if necessary).
    */
   void _addPending(_DelayedEvent event) {
-    _StreamImplEvents<T> pending = _pending;
-    if (_pending == null) {
-      pending = _pending = new _StreamImplEvents<T>();
-    }
+    // TODO(lrn): Restore to:
+    // _StreamImplEvents<T> pending = (_pending ??= _StreamImplEvents<T>());
+    // when that type-checks.
+    var streamEvents = _StreamImplEvents<T>();
+    _pending ??= streamEvents;
+    _StreamImplEvents<T> pending = streamEvents;
     pending.add(event);
     if (!_hasPending) {
       _state |= _STATE_HAS_PENDING;
       if (!_isPaused) {
-        _pending.schedule(this);
+        pending.schedule(this);
       }
     }
   }
@@ -340,7 +356,7 @@
     _checkState(wasInputPaused);
   }
 
-  void _sendError(Object error, StackTrace stackTrace) {
+  void _sendError(Object error, StackTrace? stackTrace) {
     assert(!_isCanceled);
     assert(!_isPaused);
     assert(!_inCallback);
@@ -353,11 +369,10 @@
       _state |= _STATE_IN_CALLBACK;
       // TODO(floitsch): this dynamic should be 'void'.
       var onError = _onError;
-      if (onError is void Function(Object, StackTrace)) {
-        _zone.runBinaryGuarded<Object, StackTrace>(onError, error, stackTrace);
+      if (onError is void Function(Object, StackTrace?)) {
+        _zone.runBinaryGuarded<Object, StackTrace?>(onError, error, stackTrace);
       } else {
-        assert(_onError is void Function(Object));
-        _zone.runUnaryGuarded<Object>(_onError, error);
+        _zone.runUnaryGuarded<Object>(_onError as void Function(Object), error);
       }
       _state &= ~_STATE_IN_CALLBACK;
     }
@@ -365,9 +380,10 @@
     if (_cancelOnError) {
       _state |= _STATE_WAIT_FOR_CANCEL;
       _cancel();
-      if (_cancelFuture != null &&
-          !identical(_cancelFuture, Future._nullFuture)) {
-        _cancelFuture.whenComplete(sendError);
+      var cancelFuture = _cancelFuture;
+      if (cancelFuture != null &&
+          !identical(cancelFuture, Future._nullFuture)) {
+        cancelFuture.whenComplete(sendError);
       } else {
         sendError();
       }
@@ -394,9 +410,10 @@
 
     _cancel();
     _state |= _STATE_WAIT_FOR_CANCEL;
-    if (_cancelFuture != null &&
-        !identical(_cancelFuture, Future._nullFuture)) {
-      _cancelFuture.whenComplete(sendDone);
+    var cancelFuture = _cancelFuture;
+    if (cancelFuture != null &&
+        !identical(cancelFuture, Future._nullFuture)) {
+      cancelFuture.whenComplete(sendDone);
     } else {
       sendDone();
     }
@@ -430,7 +447,7 @@
    */
   void _checkState(bool wasInputPaused) {
     assert(!_inCallback);
-    if (_hasPending && _pending.isEmpty) {
+    if (_hasPending && _pending!.isEmpty) {
       _state &= ~_STATE_HAS_PENDING;
       if (_isInputPaused && _mayResumeInput) {
         _state &= ~_STATE_INPUT_PAUSED;
@@ -455,7 +472,7 @@
       wasInputPaused = isInputPaused;
     }
     if (_hasPending && !_isPaused) {
-      _pending.schedule(this);
+      _pending!.schedule(this);
     }
   }
 }
@@ -467,9 +484,9 @@
   // ------------------------------------------------------------------
   // Stream interface.
 
-  StreamSubscription<T> listen(void onData(T data),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    cancelOnError = identical(true, cancelOnError);
+  StreamSubscription<T> listen(void onData(T data)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
+    cancelOnError ??= false;
     StreamSubscription<T> subscription =
         _createSubscription(onData, onError, onDone, cancelOnError);
     _onListen(subscription);
@@ -478,8 +495,8 @@
 
   // -------------------------------------------------------------------
   /** Create a subscription object. Called by [subcribe]. */
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
     return new _BufferingStreamSubscription<T>(
         onData, onError, onDone, cancelOnError);
   }
@@ -502,8 +519,8 @@
    */
   _GeneratedStreamImpl(this._pending);
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
     if (_isUsed) throw new StateError("Stream has already been listened to.");
     _isUsed = true;
     return new _BufferingStreamSubscription<T>(
@@ -516,14 +533,15 @@
 class _IterablePendingEvents<T> extends _PendingEvents<T> {
   // The iterator providing data for data events.
   // Set to null when iteration has completed.
-  Iterator<T> _iterator;
+  Iterator<T>? _iterator;
 
   _IterablePendingEvents(Iterable<T> data) : _iterator = data.iterator;
 
   bool get isEmpty => _iterator == null;
 
   void handleNext(_EventDispatch<T> dispatch) {
-    if (_iterator == null) {
+    var iterator = _iterator;
+    if (iterator == null) {
       throw new StateError("No events pending.");
     }
     // Send one event per call to moveNext.
@@ -532,25 +550,23 @@
     // If moveNext returns false, send a done event and clear the _iterator.
     // If moveNext throws an error, send an error and prepare to send a done
     // event afterwards.
-    bool hasMore;
+    bool movedNext = false;
     try {
-      hasMore = _iterator.moveNext();
-      if (hasMore) {
-        dispatch._sendData(_iterator.current);
+      if (iterator.moveNext()) {
+        movedNext = true;
+        dispatch._sendData(iterator.current);
       } else {
         _iterator = null;
         dispatch._sendDone();
       }
     } catch (e, s) {
-      if (hasMore == null) {
+      if (!movedNext) {
         // Threw in .moveNext().
         // Ensure that we send a done afterwards.
-        _iterator = const EmptyIterator<Null>();
-        dispatch._sendError(e, s);
-      } else {
-        // Threw in .current.
-        dispatch._sendError(e, s);
+        _iterator = const EmptyIterator<Never>();
       }
+      // Else threw in .current.
+      dispatch._sendError(e, s);
     }
   }
 
@@ -570,7 +586,7 @@
 void _nullDataHandler(Object value) {}
 
 /** Default error handler, reports the error to the current zone's handler. */
-void _nullErrorHandler(Object error, [StackTrace stackTrace]) {
+void _nullErrorHandler(Object error, [StackTrace? stackTrace]) {
   Zone.current.handleUncaughtError(error, stackTrace);
 }
 
@@ -580,7 +596,7 @@
 /** A delayed event on a buffering stream subscription. */
 abstract class _DelayedEvent<T> {
   /** Added as a linked list on the [StreamController]. */
-  _DelayedEvent next;
+  _DelayedEvent? next;
   /** Execute the delayed event on the [StreamController]. */
   void perform(_EventDispatch<T> dispatch);
 }
@@ -596,8 +612,8 @@
 
 /** A delayed error event. */
 class _DelayedError extends _DelayedEvent {
-  final error;
-  final StackTrace stackTrace;
+  final Object error;
+  final StackTrace? stackTrace;
 
   _DelayedError(this.error, this.stackTrace);
   void perform(_EventDispatch dispatch) {
@@ -612,9 +628,9 @@
     dispatch._sendDone();
   }
 
-  _DelayedEvent get next => null;
+  _DelayedEvent? get next => null;
 
-  void set next(_DelayedEvent _) {
+  void set next(_DelayedEvent? _) {
     throw new StateError("No events after a done.");
   }
 }
@@ -684,26 +700,29 @@
 /** Class holding pending events for a [_StreamImpl]. */
 class _StreamImplEvents<T> extends _PendingEvents<T> {
   /// Single linked list of [_DelayedEvent] objects.
-  _DelayedEvent firstPendingEvent;
+  _DelayedEvent? firstPendingEvent;
 
   /// Last element in the list of pending events. New events are added after it.
-  _DelayedEvent lastPendingEvent;
+  _DelayedEvent? lastPendingEvent;
 
   bool get isEmpty => lastPendingEvent == null;
 
   void add(_DelayedEvent event) {
-    if (lastPendingEvent == null) {
+    var lastEvent = lastPendingEvent;
+    if (lastEvent == null) {
       firstPendingEvent = lastPendingEvent = event;
     } else {
-      lastPendingEvent = lastPendingEvent.next = event;
+      lastPendingEvent = lastEvent.next = event;
     }
   }
 
   void handleNext(_EventDispatch<T> dispatch) {
     assert(!isScheduled);
-    _DelayedEvent event = firstPendingEvent;
-    firstPendingEvent = event.next;
-    if (firstPendingEvent == null) {
+    assert(!isEmpty);
+    _DelayedEvent event = firstPendingEvent!;
+    _DelayedEvent? nextEvent = event.next;
+    firstPendingEvent = nextEvent;
+    if (nextEvent == null) {
       lastPendingEvent = null;
     }
     event.perform(dispatch);
@@ -727,7 +746,7 @@
 
   final Zone _zone;
   int _state = 0;
-  _DoneHandler _onDone;
+  _DoneHandler? _onDone;
 
   _DoneStreamSubscription(this._onDone) : _zone = Zone.current {
     _schedule();
@@ -743,13 +762,13 @@
     _state |= _SCHEDULED;
   }
 
-  void onData(void handleData(T data)) {}
-  void onError(Function handleError) {}
-  void onDone(void handleDone()) {
+  void onData(void handleData(T data)?) {}
+  void onError(Function? handleError) {}
+  void onDone(void handleDone()?) {
     _onDone = handleDone;
   }
 
-  void pause([Future resumeSignal]) {
+  void pause([Future<void>? resumeSignal]) {
     _state += _PAUSED;
     if (resumeSignal != null) resumeSignal.whenComplete(resume);
   }
@@ -765,42 +784,45 @@
 
   Future cancel() => Future._nullFuture;
 
-  Future<E> asFuture<E>([E futureValue]) {
-    _Future<E> result = new _Future<E>();
-    _onDone = () {
-      result._completeWithValue(futureValue);
-    };
-    return result;
+  Future<E> asFuture<E>([E? futureValue]) {
+    if (futureValue is E) {
+      _Future<E> result = new _Future<E>();
+      E resultValue = futureValue;
+      _onDone = () {
+        result._completeWithValue(resultValue);
+      };
+      return result;
+    }
+    throw ArgumentError.notNull("futureValue");
   }
 
   void _sendDone() {
     _state &= ~_SCHEDULED;
     if (isPaused) return;
     _state |= _DONE_SENT;
-    if (_onDone != null) _zone.runGuarded(_onDone);
+    var doneHandler = _onDone;
+    if (doneHandler != null) _zone.runGuarded(doneHandler);
   }
 }
 
 class _AsBroadcastStream<T> extends Stream<T> {
   final Stream<T> _source;
-  final _BroadcastCallback<T> _onListenHandler;
-  final _BroadcastCallback<T> _onCancelHandler;
+  final _BroadcastCallback<T>? _onListenHandler;
+  final _BroadcastCallback<T>? _onCancelHandler;
   final Zone _zone;
 
-  _AsBroadcastStreamController<T> _controller;
-  StreamSubscription<T> _subscription;
+  late _AsBroadcastStreamController<T>? _controller;
+  StreamSubscription<T>? _subscription;
 
   _AsBroadcastStream(
       this._source,
-      void onListenHandler(StreamSubscription<T> subscription),
-      void onCancelHandler(StreamSubscription<T> subscription))
-      // TODO(floitsch): the return type should be void and should be
-      // inferred.
-      : _onListenHandler = Zone.current
-            .registerUnaryCallback<dynamic, StreamSubscription<T>>(
+      void onListenHandler(StreamSubscription<T> subscription)?,
+      void onCancelHandler(StreamSubscription<T> subscription)?)
+      : _onListenHandler = onListenHandler == null ? null : Zone.current
+            .registerUnaryCallback<void, StreamSubscription<T>>(
                 onListenHandler),
-        _onCancelHandler = Zone.current
-            .registerUnaryCallback<dynamic, StreamSubscription<T>>(
+        _onCancelHandler = onCancelHandler == null ? null : Zone.current
+            .registerUnaryCallback<void, StreamSubscription<T>>(
                 onCancelHandler),
         _zone = Zone.current {
     _controller = new _AsBroadcastStreamController<T>(_onListen, _onCancel);
@@ -808,63 +830,66 @@
 
   bool get isBroadcast => true;
 
-  StreamSubscription<T> listen(void onData(T data),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    if (_controller == null || _controller.isClosed) {
+  StreamSubscription<T> listen(void onData(T data)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
+    var controller = _controller;
+    if (controller == null || controller.isClosed) {
       // Return a dummy subscription backed by nothing, since
       // it will only ever send one done event.
       return new _DoneStreamSubscription<T>(onDone);
     }
-    _subscription ??= _source.listen(_controller.add,
-        onError: _controller.addError, onDone: _controller.close);
-    cancelOnError = identical(true, cancelOnError);
-    return _controller._subscribe(onData, onError, onDone, cancelOnError);
+    _subscription ??= _source.listen(controller.add,
+        onError: controller.addError, onDone: controller.close);
+    return controller._subscribe(
+        onData, onError, onDone, cancelOnError ?? false);
   }
 
   void _onCancel() {
-    bool shutdown = (_controller == null) || _controller.isClosed;
-    if (_onCancelHandler != null) {
+    var controller = _controller;
+    bool shutdown = (controller == null) || controller.isClosed;
+    var cancelHandler = _onCancelHandler;
+    if (cancelHandler != null) {
       _zone.runUnary(
-          _onCancelHandler, new _BroadcastSubscriptionWrapper<T>(this));
+          cancelHandler, new _BroadcastSubscriptionWrapper<T>(this));
     }
     if (shutdown) {
-      if (_subscription != null) {
-        _subscription.cancel();
+      var subscription = _subscription;
+      if (subscription != null) {
+        subscription.cancel();
         _subscription = null;
       }
     }
   }
 
   void _onListen() {
-    if (_onListenHandler != null) {
+    var listenHandler = _onListenHandler;
+    if (listenHandler != null) {
       _zone.runUnary(
-          _onListenHandler, new _BroadcastSubscriptionWrapper<T>(this));
+          listenHandler, new _BroadcastSubscriptionWrapper<T>(this));
     }
   }
 
   // Methods called from _BroadcastSubscriptionWrapper.
   void _cancelSubscription() {
-    if (_subscription == null) return;
     // Called by [_controller] when it has no subscribers left.
-    StreamSubscription subscription = _subscription;
-    _subscription = null;
-    _controller = null; // Marks the stream as no longer listenable.
-    subscription.cancel();
+    var subscription = _subscription;
+    if (subscription != null) {
+      _subscription = null;
+      _controller = null; // Marks the stream as no longer listenable.
+      subscription.cancel();
+    }
   }
 
-  void _pauseSubscription(Future resumeSignal) {
-    if (_subscription == null) return;
-    _subscription.pause(resumeSignal);
+  void _pauseSubscription(Future<void>? resumeSignal) {
+    _subscription?.pause(resumeSignal);
   }
 
   void _resumeSubscription() {
-    if (_subscription == null) return;
-    _subscription.resume();
+    _subscription?.resume();
   }
 
   bool get _isSubscriptionPaused {
-    if (_subscription == null) return false;
-    return _subscription.isPaused;
+    return _subscription?.isPaused ?? false;
   }
 }
 
@@ -876,22 +901,22 @@
 
   _BroadcastSubscriptionWrapper(this._stream);
 
-  void onData(void handleData(T data)) {
+  void onData(void handleData(T data)?) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
 
-  void onError(Function handleError) {
+  void onError(Function? handleError) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
 
-  void onDone(void handleDone()) {
+  void onDone(void handleDone()?) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
 
-  void pause([Future resumeSignal]) {
+  void pause([Future<void>? resumeSignal]) {
     _stream._pauseSubscription(resumeSignal);
   }
 
@@ -908,7 +933,7 @@
     return _stream._isSubscriptionPaused;
   }
 
-  Future<E> asFuture<E>([E futureValue]) {
+  Future<E> asFuture<E>([E? futureValue]) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
@@ -947,7 +972,7 @@
   /// Subscription being listened to.
   ///
   /// Set to `null` when the stream subscription is done or canceled.
-  StreamSubscription _subscription;
+  StreamSubscription<T>? _subscription;
 
   /// Data value depending on the current state.
   ///
@@ -961,7 +986,7 @@
   ///
   /// After calling [moveNext] and the returned future has completed
   /// with `false`, or after calling [cancel]: `null`.
-  Object _stateData;
+  Object? _stateData;
 
   /// Whether the iterator is between calls to `moveNext`.
   /// This will usually cause the [_subscription] to be paused, but as an
@@ -970,22 +995,23 @@
   bool _isPaused = false;
 
   _StreamIterator(final Stream<T> stream)
-      : _stateData = stream ?? (throw ArgumentError.notNull("stream"));
+      : _stateData = stream;
 
   T get current {
     if (_subscription != null && _isPaused) {
-      return _stateData;
+      return _stateData as T;
     }
-    return null;
+    return null as T;
   }
 
   Future<bool> moveNext() {
-    if (_subscription != null) {
+    var subscription = _subscription;
+    if (subscription != null) {
       if (_isPaused) {
         var future = new _Future<bool>();
         _stateData = future;
         _isPaused = false;
-        _subscription.resume();
+        subscription.resume();
         return future;
       }
       throw new StateError("Already waiting for next.");
@@ -1002,7 +1028,7 @@
     assert(_subscription == null);
     var stateData = _stateData;
     if (stateData != null) {
-      Stream<T> stream = stateData;
+      var stream = stateData as Stream<T>;
       _subscription = stream.listen(_onData,
           onError: _onError, onDone: _onDone, cancelOnError: true);
       var future = new _Future<bool>();
@@ -1013,13 +1039,13 @@
   }
 
   Future cancel() {
-    StreamSubscription<T> subscription = _subscription;
-    Object stateData = _stateData;
+    StreamSubscription<T>? subscription = _subscription;
+    Object? stateData = _stateData;
     _stateData = null;
     if (subscription != null) {
       _subscription = null;
       if (!_isPaused) {
-        _Future<bool> future = stateData;
+        var future = stateData as _Future<bool>;
         future._asyncComplete(false);
       }
       return subscription.cancel();
@@ -1029,16 +1055,16 @@
 
   void _onData(T data) {
     assert(_subscription != null && !_isPaused);
-    _Future<bool> moveNextFuture = _stateData;
+    var moveNextFuture = _stateData as _Future<bool>;
     _stateData = data;
     _isPaused = true;
     moveNextFuture._complete(true);
-    if (_subscription != null && _isPaused) _subscription.pause();
+    if (_isPaused) _subscription?.pause();
   }
 
-  void _onError(Object error, [StackTrace stackTrace]) {
+  void _onError(Object error, [StackTrace? stackTrace]) {
     assert(_subscription != null && !_isPaused);
-    _Future<bool> moveNextFuture = _stateData;
+    var moveNextFuture = _stateData as _Future<bool>;
     _subscription = null;
     _stateData = null;
     moveNextFuture._completeError(error, stackTrace);
@@ -1046,7 +1072,7 @@
 
   void _onDone() {
     assert(_subscription != null && !_isPaused);
-    _Future<bool> moveNextFuture = _stateData;
+    var moveNextFuture = _stateData as _Future<bool>;
     _subscription = null;
     _stateData = null;
     moveNextFuture._complete(false);
@@ -1057,8 +1083,8 @@
 class _EmptyStream<T> extends Stream<T> {
   const _EmptyStream() : super._internal();
   bool get isBroadcast => true;
-  StreamSubscription<T> listen(void onData(T data),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void onData(T data)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     return new _DoneStreamSubscription<T>(onDone);
   }
 }
diff --git a/sdk_nnbd/lib/async/stream_pipe.dart b/sdk_nnbd/lib/async/stream_pipe.dart
index 1549ad5..b307ed6 100644
--- a/sdk_nnbd/lib/async/stream_pipe.dart
+++ b/sdk_nnbd/lib/async/stream_pipe.dart
@@ -2,21 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /** Runs user code and takes actions depending on success or failure. */
 _runUserCode<T>(
-    T userCode(), onSuccess(T value), onError(error, StackTrace stackTrace)) {
+    T userCode(), onSuccess(T value), onError(Object error, StackTrace? stackTrace)) {
   try {
     onSuccess(userCode());
   } catch (e, s) {
-    AsyncError replacement = Zone.current.errorCallback(e, s);
+    AsyncError? replacement = Zone.current.errorCallback(e, s);
     if (replacement == null) {
       onError(e, s);
     } else {
-      var error = _nonNullError(replacement.error);
+      var error = replacement.error;
       var stackTrace = replacement.stackTrace;
       onError(error, stackTrace);
     }
@@ -25,8 +23,8 @@
 
 /** Helper function to cancel a subscription and wait for the potential future,
   before completing with an error. */
-void _cancelAndError(StreamSubscription subscription, _Future future, error,
-    StackTrace stackTrace) {
+void _cancelAndError(StreamSubscription subscription, _Future future,
+    Object error, StackTrace? stackTrace) {
   var cancelFuture = subscription.cancel();
   if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
     cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
@@ -36,21 +34,21 @@
 }
 
 void _cancelAndErrorWithReplacement(StreamSubscription subscription,
-    _Future future, error, StackTrace stackTrace) {
-  AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+    _Future future, Object error, StackTrace? stackTrace) {
+  AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
-    error = _nonNullError(replacement.error);
+    error = replacement.error;
     stackTrace = replacement.stackTrace;
   }
   _cancelAndError(subscription, future, error, stackTrace);
 }
 
-typedef void _ErrorCallback(error, StackTrace stackTrace);
+typedef void _ErrorCallback(Object error, StackTrace? stackTrace);
 
 /** Helper function to make an onError argument to [_runUserCode]. */
 _ErrorCallback _cancelAndErrorClosure(
     StreamSubscription subscription, _Future future) {
-  return (error, StackTrace stackTrace) {
+  return (Object error, StackTrace? stackTrace) {
     _cancelAndError(subscription, future, error, stackTrace);
   };
 }
@@ -82,25 +80,22 @@
 
   bool get isBroadcast => _source.isBroadcast;
 
-  StreamSubscription<T> listen(void onData(T value),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    cancelOnError = identical(true, cancelOnError);
-    return _createSubscription(onData, onError, onDone, cancelOnError);
+  StreamSubscription<T> listen(void onData(T value)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
+    return _createSubscription(onData, onError, onDone, cancelOnError ?? false);
   }
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
     return new _ForwardingStreamSubscription<S, T>(
         this, onData, onError, onDone, cancelOnError);
   }
 
   // Override the following methods in subclasses to change the behavior.
 
-  void _handleData(S data, _EventSink<T> sink) {
-    sink._add(data as Object);
-  }
+  void _handleData(S data, _EventSink<T> sink);
 
-  void _handleError(error, StackTrace stackTrace, _EventSink<T> sink) {
+  void _handleError(Object error, StackTrace? stackTrace, _EventSink<T> sink) {
     sink._addError(error, stackTrace);
   }
 
@@ -116,10 +111,10 @@
     extends _BufferingStreamSubscription<T> {
   final _ForwardingStream<S, T> _stream;
 
-  StreamSubscription<S> _subscription;
+  StreamSubscription<S>? _subscription;
 
-  _ForwardingStreamSubscription(this._stream, void onData(T data),
-      Function onError, void onDone(), bool cancelOnError)
+  _ForwardingStreamSubscription(this._stream, void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError)
       : super(onData, onError, onDone, cancelOnError) {
     _subscription = _stream._source
         .listen(_handleData, onError: _handleError, onDone: _handleDone);
@@ -134,7 +129,7 @@
     super._add(data);
   }
 
-  void _addError(Object error, StackTrace stackTrace) {
+  void _addError(Object error, StackTrace? stackTrace) {
     if (_isClosed) return;
     super._addError(error, stackTrace);
   }
@@ -142,18 +137,16 @@
   // StreamSubscription callbacks.
 
   void _onPause() {
-    if (_subscription == null) return;
-    _subscription.pause();
+    _subscription?.pause();
   }
 
   void _onResume() {
-    if (_subscription == null) return;
-    _subscription.resume();
+    _subscription?.resume();
   }
 
-  Future _onCancel() {
-    if (_subscription != null) {
-      StreamSubscription subscription = _subscription;
+  Future<void>? _onCancel() {
+    var subscription = _subscription;
+    if (subscription != null) {
       _subscription = null;
       return subscription.cancel();
     }
@@ -166,7 +159,7 @@
     _stream._handleData(data, this);
   }
 
-  void _handleError(error, StackTrace stackTrace) {
+  void _handleError(error, StackTrace? stackTrace) {
     _stream._handleError(error, stackTrace, this);
   }
 
@@ -179,19 +172,18 @@
 // Stream transformers used by the default Stream implementation.
 // -------------------------------------------------------------------
 
-typedef bool _Predicate<T>(T value);
-
-void _addErrorWithReplacement(_EventSink sink, error, StackTrace stackTrace) {
-  AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
+void _addErrorWithReplacement(
+    _EventSink sink, Object error, StackTrace? stackTrace) {
+  AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
-    error = _nonNullError(replacement.error);
+    error = replacement.error;
     stackTrace = replacement.stackTrace;
   }
   sink._addError(error, stackTrace);
 }
 
 class _WhereStream<T> extends _ForwardingStream<T, T> {
-  final _Predicate<T> _test;
+  final bool Function(T) _test;
 
   _WhereStream(Stream<T> source, bool test(T value))
       : _test = test,
@@ -258,26 +250,30 @@
   }
 }
 
-typedef bool _ErrorTest(error);
-
 /**
  * A stream pipe that converts or disposes error events
  * before passing them on.
  */
 class _HandleErrorStream<T> extends _ForwardingStream<T, T> {
   final Function _transform;
-  final _ErrorTest _test;
+  final bool Function(Object)? _test;
 
-  _HandleErrorStream(Stream<T> source, Function onError, bool test(error))
+  _HandleErrorStream(
+      Stream<T> source, Function onError, bool test(Object error)?)
       : this._transform = onError,
         this._test = test,
         super(source);
 
-  void _handleError(Object error, StackTrace stackTrace, _EventSink<T> sink) {
+  void _handleData(T data, _EventSink<T> sink) {
+    sink._add(data);
+  }
+
+  void _handleError(Object error, StackTrace? stackTrace, _EventSink<T> sink) {
     bool matches = true;
-    if (_test != null) {
+    var test = _test;
+    if (test != null) {
       try {
-        matches = _test(error);
+        matches = test(error);
       } catch (e, s) {
         _addErrorWithReplacement(sink, e, s);
         return;
@@ -305,29 +301,25 @@
 
   _TakeStream(Stream<T> source, int count)
       : this._count = count,
-        super(source) {
-    // This test is done early to avoid handling an async error
-    // in the _handleData method.
-    ArgumentError.checkNotNull(count, "count");
-  }
+        super(source);
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
     if (_count == 0) {
       _source.listen(null).cancel();
       return new _DoneStreamSubscription<T>(onDone);
     }
-    return new _StateStreamSubscription<T>(
+    return new _StateStreamSubscription<int, T>(
         this, onData, onError, onDone, cancelOnError, _count);
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription<T> subscription = sink;
-    int count = subscription._count;
+    var subscription = sink as _StateStreamSubscription<int, T>;
+    int count = subscription._subState;
     if (count > 0) {
       sink._add(inputEvent);
       count -= 1;
-      subscription._count = count;
+      subscription._subState = count;
       if (count == 0) {
         // Closing also unsubscribes all subscribers, which unsubscribes
         // this from source.
@@ -342,32 +334,17 @@
  *
  * Use by several different classes, storing an integer, bool or general.
  */
-class _StateStreamSubscription<T> extends _ForwardingStreamSubscription<T, T> {
-  // Raw state field. Typed access provided by getters and setters below.
-  var _sharedState;
+class _StateStreamSubscription<S, T>
+    extends _ForwardingStreamSubscription<T, T> {
+  S _subState;
 
-  _StateStreamSubscription(_ForwardingStream<T, T> stream, void onData(T data),
-      Function onError, void onDone(), bool cancelOnError, this._sharedState)
+  _StateStreamSubscription(_ForwardingStream<T, T> stream, void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError, this._subState)
       : super(stream, onData, onError, onDone, cancelOnError);
-
-  bool get _flag => _sharedState;
-  void set _flag(bool flag) {
-    _sharedState = flag;
-  }
-
-  int get _count => _sharedState;
-  void set _count(int count) {
-    _sharedState = count;
-  }
-
-  Object get _value => _sharedState;
-  void set _value(Object value) {
-    _sharedState = value;
-  }
 }
 
 class _TakeWhileStream<T> extends _ForwardingStream<T, T> {
-  final _Predicate<T> _test;
+  final bool Function(T) _test;
 
   _TakeWhileStream(Stream<T> source, bool test(T value))
       : this._test = test,
@@ -399,21 +376,20 @@
         super(source) {
     // This test is done early to avoid handling an async error
     // in the _handleData method.
-    ArgumentError.checkNotNull(count, "count");
     RangeError.checkNotNegative(count, "count");
   }
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
-    return new _StateStreamSubscription<T>(
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
+    return new _StateStreamSubscription<int, T>(
         this, onData, onError, onDone, cancelOnError, _count);
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription<T> subscription = sink;
-    int count = subscription._count;
+    var subscription = sink as _StateStreamSubscription<int, T>;
+    int count = subscription._subState;
     if (count > 0) {
-      subscription._count = count - 1;
+      subscription._subState = count - 1;
       return;
     }
     sink._add(inputEvent);
@@ -421,21 +397,21 @@
 }
 
 class _SkipWhileStream<T> extends _ForwardingStream<T, T> {
-  final _Predicate<T> _test;
+  final bool Function(T) _test;
 
   _SkipWhileStream(Stream<T> source, bool test(T value))
       : this._test = test,
         super(source);
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
-    return new _StateStreamSubscription<T>(
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
+    return new _StateStreamSubscription<bool, T>(
         this, onData, onError, onDone, cancelOnError, false);
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription<T> subscription = sink;
-    bool hasFailed = subscription._flag;
+    var subscription = sink as _StateStreamSubscription<bool, T>;
+    bool hasFailed = subscription._subState;
     if (hasFailed) {
       sink._add(inputEvent);
       return;
@@ -446,48 +422,47 @@
     } catch (e, s) {
       _addErrorWithReplacement(sink, e, s);
       // A failure to return a boolean is considered "not matching".
-      subscription._flag = true;
+      subscription._subState = true;
       return;
     }
     if (!satisfies) {
-      subscription._flag = true;
+      subscription._subState = true;
       sink._add(inputEvent);
     }
   }
 }
 
-typedef bool _Equality<T>(T a, T b);
-
 class _DistinctStream<T> extends _ForwardingStream<T, T> {
   static final _SENTINEL = new Object();
 
-  final _Equality<T> _equals;
+  final bool Function(T, T)? _equals;
 
-  _DistinctStream(Stream<T> source, bool equals(T a, T b))
+  _DistinctStream(Stream<T> source, bool equals(T a, T b)?)
       : _equals = equals,
         super(source);
 
-  StreamSubscription<T> _createSubscription(void onData(T data),
-      Function onError, void onDone(), bool cancelOnError) {
-    return new _StateStreamSubscription<T>(
+  StreamSubscription<T> _createSubscription(void onData(T data)?,
+      Function? onError, void onDone()?, bool cancelOnError) {
+    return new _StateStreamSubscription<Object?, T>(
         this, onData, onError, onDone, cancelOnError, _SENTINEL);
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription<T> subscription = sink;
-    var previous = subscription._value;
+    var subscription = sink as _StateStreamSubscription<Object?, T>;
+    var previous = subscription._subState;
     if (identical(previous, _SENTINEL)) {
-      // First event.
-      subscription._value = inputEvent;
+      // First event. Cannot use [_equals].
+      subscription._subState = inputEvent;
       sink._add(inputEvent);
     } else {
-      T previousEvent = previous;
+      T previousEvent = previous as T;
+      var equals = _equals;
       bool isEqual;
       try {
-        if (_equals == null) {
+        if (equals == null) {
           isEqual = (previousEvent == inputEvent);
         } else {
-          isEqual = _equals(previousEvent, inputEvent);
+          isEqual = equals(previousEvent, inputEvent);
         }
       } catch (e, s) {
         _addErrorWithReplacement(sink, e, s);
@@ -495,7 +470,7 @@
       }
       if (!isEqual) {
         sink._add(inputEvent);
-        subscription._value = inputEvent;
+        subscription._subState = inputEvent;
       }
     }
   }
diff --git a/sdk_nnbd/lib/async/stream_transformers.dart b/sdk_nnbd/lib/async/stream_transformers.dart
index 5c788fe..3e332b4 100644
--- a/sdk_nnbd/lib/async/stream_transformers.dart
+++ b/sdk_nnbd/lib/async/stream_transformers.dart
@@ -2,22 +2,20 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /**
  * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
  */
 class _EventSinkWrapper<T> implements EventSink<T> {
-  _EventSink _sink;
+  _EventSink<T> _sink;
   _EventSinkWrapper(this._sink);
 
   void add(T data) {
     _sink._add(data);
   }
 
-  void addError(error, [StackTrace stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     _sink._addError(error, stackTrace);
   }
 
@@ -36,24 +34,25 @@
 class _SinkTransformerStreamSubscription<S, T>
     extends _BufferingStreamSubscription<T> {
   /// The transformer's input sink.
-  EventSink<S> _transformerSink;
+  late EventSink<S> _transformerSink;
 
   /// The subscription to the input stream.
-  StreamSubscription<S> _subscription;
+  StreamSubscription<S>? _subscription;
 
-  _SinkTransformerStreamSubscription(Stream<S> source, _SinkMapper<S, T> mapper,
-      void onData(T data), Function onError, void onDone(), bool cancelOnError)
+  _SinkTransformerStreamSubscription(
+      Stream<S> source,
+      _SinkMapper<S, T> mapper,
+      void onData(T data)?,
+      Function? onError,
+      void onDone()?,
+      bool cancelOnError)
       // We set the adapter's target only when the user is allowed to send data.
       : super(onData, onError, onDone, cancelOnError) {
-    _EventSinkWrapper<T> eventSink = new _EventSinkWrapper<T>(this);
-    _transformerSink = mapper(eventSink);
+    _transformerSink = mapper(_EventSinkWrapper<T>(this));
     _subscription =
         source.listen(_handleData, onError: _handleError, onDone: _handleDone);
   }
 
-  /** Whether this subscription is still subscribed to its source. */
-  bool get _isSubscribed => _subscription != null;
-
   // _EventSink interface.
 
   /**
@@ -65,7 +64,7 @@
    */
   void _add(T data) {
     if (_isClosed) {
-      throw new StateError("Stream is already closed");
+      throw StateError("Stream is already closed");
     }
     super._add(data);
   }
@@ -77,7 +76,7 @@
    * events when the stream is already closed. Report them as state
    * error.
    */
-  void _addError(Object error, StackTrace stackTrace) {
+  void _addError(Object error, StackTrace? stackTrace) {
     if (_isClosed) {
       throw new StateError("Stream is already closed");
     }
@@ -101,16 +100,16 @@
   // _BufferingStreamSubscription hooks.
 
   void _onPause() {
-    if (_isSubscribed) _subscription.pause();
+    _subscription?.pause();
   }
 
   void _onResume() {
-    if (_isSubscribed) _subscription.resume();
+    _subscription?.resume();
   }
 
-  Future _onCancel() {
-    if (_isSubscribed) {
-      StreamSubscription subscription = _subscription;
+  Future<void>? _onCancel() {
+    var subscription = _subscription;
+    if (subscription != null) {
       _subscription = null;
       return subscription.cancel();
     }
@@ -125,7 +124,7 @@
     }
   }
 
-  void _handleError(error, [StackTrace stackTrace]) {
+  void _handleError(Object error, StackTrace? stackTrace) {
     try {
       _transformerSink.addError(error, stackTrace);
     } catch (e, s) {
@@ -180,12 +179,11 @@
 
   _BoundSinkStream(this._stream, this._sinkMapper);
 
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    cancelOnError = identical(true, cancelOnError);
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     StreamSubscription<T> subscription =
-        new _SinkTransformerStreamSubscription<S, T>(
-            _stream, _sinkMapper, onData, onError, onDone, cancelOnError);
+        _SinkTransformerStreamSubscription<S, T>(_stream, _sinkMapper, onData,
+            onError, onDone, cancelOnError ?? false);
     return subscription;
   }
 }
@@ -195,7 +193,7 @@
 
 /// Error-handler coming from [StreamTransformer.fromHandlers].
 typedef void _TransformErrorHandler<T>(
-    Object error, StackTrace stackTrace, EventSink<T> sink);
+    Object error, StackTrace? stackTrace, EventSink<T> sink);
 
 /// Done-handler coming from [StreamTransformer.fromHandlers].
 typedef void _TransformDoneHandler<T>(EventSink<T> sink);
@@ -206,50 +204,50 @@
  * This way we can reuse the code from [_StreamSinkTransformer].
  */
 class _HandlerEventSink<S, T> implements EventSink<S> {
-  final _TransformDataHandler<S, T> _handleData;
-  final _TransformErrorHandler<T> _handleError;
-  final _TransformDoneHandler<T> _handleDone;
+  final _TransformDataHandler<S, T>? _handleData;
+  final _TransformErrorHandler<T>? _handleError;
+  final _TransformDoneHandler<T>? _handleDone;
 
   /// The output sink where the handlers should send their data into.
-  EventSink<T> _sink;
+  /// Set to `null` when closed.
+  EventSink<T>? _sink;
 
-  _HandlerEventSink(
-      this._handleData, this._handleError, this._handleDone, this._sink) {
-    if (_sink == null) {
-      throw new ArgumentError("The provided sink must not be null.");
-    }
-  }
-
-  bool get _isClosed => _sink == null;
+  _HandlerEventSink(this._handleData, this._handleError, this._handleDone,
+      EventSink<T> this._sink);
 
   void add(S data) {
-    if (_isClosed) {
+    var sink = _sink;
+    if (sink == null) {
       throw StateError("Sink is closed");
     }
-    if (_handleData != null) {
-      _handleData(data, _sink);
+    var handleData = _handleData;
+    if (handleData != null) {
+      handleData(data, sink);
     } else {
-      _sink.add(data as T);
+      sink.add(data as T);
     }
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
-    if (_isClosed) {
+  void addError(Object error, [StackTrace? stackTrace]) {
+    var sink = _sink;
+    if (sink == null) {
       throw StateError("Sink is closed");
     }
-    if (_handleError != null) {
-      _handleError(error, stackTrace, _sink);
+    var handleError = _handleError;
+    if (handleError != null) {
+      handleError(error, stackTrace, sink);
     } else {
-      _sink.addError(error, stackTrace);
+      sink.addError(error, stackTrace);
     }
   }
 
   void close() {
-    if (_isClosed) return;
     var sink = _sink;
+    if (sink == null) return;
     _sink = null;
-    if (_handleDone != null) {
-      _handleDone(sink);
+    var handleDone = _handleDone;
+    if (handleDone != null) {
+      handleDone(sink);
     } else {
       sink.close();
     }
@@ -263,9 +261,10 @@
  */
 class _StreamHandlerTransformer<S, T> extends _StreamSinkTransformer<S, T> {
   _StreamHandlerTransformer(
-      {void handleData(S data, EventSink<T> sink),
-      void handleError(Object error, StackTrace stackTrace, EventSink<T> sink),
-      void handleDone(EventSink<T> sink)})
+      {void handleData(S data, EventSink<T> sink)?,
+      void handleError(
+          Object error, StackTrace? stackTrace, EventSink<T> sink)?,
+      void handleDone(EventSink<T> sink)?})
       : super((EventSink<T> outputSink) {
           return new _HandlerEventSink<S, T>(
               handleData, handleError, handleDone, outputSink);
@@ -326,10 +325,9 @@
 
   _BoundSubscriptionStream(this._stream, this._onListen);
 
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    cancelOnError = identical(true, cancelOnError);
-    StreamSubscription<T> result = _onListen(_stream, cancelOnError);
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
+    StreamSubscription<T> result = _onListen(_stream, cancelOnError ?? false);
     result.onData(onData);
     result.onError(onError);
     result.onDone(onDone);
diff --git a/sdk_nnbd/lib/async/timer.dart b/sdk_nnbd/lib/async/timer.dart
index c1089bc..97560a9 100644
--- a/sdk_nnbd/lib/async/timer.dart
+++ b/sdk_nnbd/lib/async/timer.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 /**
diff --git a/sdk_nnbd/lib/async/zone.dart b/sdk_nnbd/lib/async/zone.dart
index 6a2d015..4e956a2 100644
--- a/sdk_nnbd/lib/async/zone.dart
+++ b/sdk_nnbd/lib/async/zone.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.async;
 
 typedef R ZoneCallback<R>();
@@ -11,7 +9,7 @@
 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
 
 typedef HandleUncaughtErrorHandler = void Function(Zone self,
-    ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace);
+    ZoneDelegate parent, Zone zone, Object error, StackTrace? stackTrace);
 typedef RunHandler = R Function<R>(
     Zone self, ZoneDelegate parent, Zone zone, R Function() f);
 typedef RunUnaryHandler = R Function<R, T>(
@@ -25,8 +23,8 @@
 typedef RegisterBinaryCallbackHandler
     = ZoneBinaryCallback<R, T1, T2> Function<R, T1, T2>(Zone self,
         ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f);
-typedef AsyncError ErrorCallbackHandler(Zone self, ZoneDelegate parent,
-    Zone zone, Object error, StackTrace stackTrace);
+typedef AsyncError? ErrorCallbackHandler(Zone self, ZoneDelegate parent,
+    Zone zone, Object error, StackTrace? stackTrace);
 typedef void ScheduleMicrotaskHandler(
     Zone self, ZoneDelegate parent, Zone zone, void f());
 typedef Timer CreateTimerHandler(
@@ -36,12 +34,12 @@
 typedef void PrintHandler(
     Zone self, ZoneDelegate parent, Zone zone, String line);
 typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone,
-    ZoneSpecification specification, Map zoneValues);
+    ZoneSpecification? specification, Map<Object?, Object?>? zoneValues);
 
 /** Pair of error and stack trace. Returned by [Zone.errorCallback]. */
 class AsyncError implements Error {
   final Object error;
-  final StackTrace stackTrace;
+  final StackTrace? stackTrace;
 
   AsyncError(this.error, this.stackTrace);
 
@@ -78,38 +76,38 @@
    * Creates a specification with the provided handlers.
    */
   const factory ZoneSpecification(
-      {HandleUncaughtErrorHandler handleUncaughtError,
-      RunHandler run,
-      RunUnaryHandler runUnary,
-      RunBinaryHandler runBinary,
-      RegisterCallbackHandler registerCallback,
-      RegisterUnaryCallbackHandler registerUnaryCallback,
-      RegisterBinaryCallbackHandler registerBinaryCallback,
-      ErrorCallbackHandler errorCallback,
-      ScheduleMicrotaskHandler scheduleMicrotask,
-      CreateTimerHandler createTimer,
-      CreatePeriodicTimerHandler createPeriodicTimer,
-      PrintHandler print,
-      ForkHandler fork}) = _ZoneSpecification;
+      {HandleUncaughtErrorHandler? handleUncaughtError,
+      RunHandler? run,
+      RunUnaryHandler? runUnary,
+      RunBinaryHandler? runBinary,
+      RegisterCallbackHandler? registerCallback,
+      RegisterUnaryCallbackHandler? registerUnaryCallback,
+      RegisterBinaryCallbackHandler? registerBinaryCallback,
+      ErrorCallbackHandler? errorCallback,
+      ScheduleMicrotaskHandler? scheduleMicrotask,
+      CreateTimerHandler? createTimer,
+      CreatePeriodicTimerHandler? createPeriodicTimer,
+      PrintHandler? print,
+      ForkHandler? fork}) = _ZoneSpecification;
 
   /**
    * Creates a specification from [other] with the provided handlers overriding
    * the ones in [other].
    */
   factory ZoneSpecification.from(ZoneSpecification other,
-      {HandleUncaughtErrorHandler handleUncaughtError,
-      RunHandler run,
-      RunUnaryHandler runUnary,
-      RunBinaryHandler runBinary,
-      RegisterCallbackHandler registerCallback,
-      RegisterUnaryCallbackHandler registerUnaryCallback,
-      RegisterBinaryCallbackHandler registerBinaryCallback,
-      ErrorCallbackHandler errorCallback,
-      ScheduleMicrotaskHandler scheduleMicrotask,
-      CreateTimerHandler createTimer,
-      CreatePeriodicTimerHandler createPeriodicTimer,
-      PrintHandler print,
-      ForkHandler fork}) {
+      {HandleUncaughtErrorHandler? handleUncaughtError,
+      RunHandler? run,
+      RunUnaryHandler? runUnary,
+      RunBinaryHandler? runBinary,
+      RegisterCallbackHandler? registerCallback,
+      RegisterUnaryCallbackHandler? registerUnaryCallback,
+      RegisterBinaryCallbackHandler? registerBinaryCallback,
+      ErrorCallbackHandler? errorCallback,
+      ScheduleMicrotaskHandler? scheduleMicrotask,
+      CreateTimerHandler? createTimer,
+      CreatePeriodicTimerHandler? createPeriodicTimer,
+      PrintHandler? print,
+      ForkHandler? fork}) {
     return new ZoneSpecification(
         handleUncaughtError: handleUncaughtError ?? other.handleUncaughtError,
         run: run ?? other.run,
@@ -128,19 +126,19 @@
         fork: fork ?? other.fork);
   }
 
-  HandleUncaughtErrorHandler get handleUncaughtError;
-  RunHandler get run;
-  RunUnaryHandler get runUnary;
-  RunBinaryHandler get runBinary;
-  RegisterCallbackHandler get registerCallback;
-  RegisterUnaryCallbackHandler get registerUnaryCallback;
-  RegisterBinaryCallbackHandler get registerBinaryCallback;
-  ErrorCallbackHandler get errorCallback;
-  ScheduleMicrotaskHandler get scheduleMicrotask;
-  CreateTimerHandler get createTimer;
-  CreatePeriodicTimerHandler get createPeriodicTimer;
-  PrintHandler get print;
-  ForkHandler get fork;
+  HandleUncaughtErrorHandler? get handleUncaughtError;
+  RunHandler? get run;
+  RunUnaryHandler? get runUnary;
+  RunBinaryHandler? get runBinary;
+  RegisterCallbackHandler? get registerCallback;
+  RegisterUnaryCallbackHandler? get registerUnaryCallback;
+  RegisterBinaryCallbackHandler? get registerBinaryCallback;
+  ErrorCallbackHandler? get errorCallback;
+  ScheduleMicrotaskHandler? get scheduleMicrotask;
+  CreateTimerHandler? get createTimer;
+  CreatePeriodicTimerHandler? get createPeriodicTimer;
+  PrintHandler? get print;
+  ForkHandler? get fork;
 }
 
 /**
@@ -166,19 +164,19 @@
       this.print,
       this.fork});
 
-  final HandleUncaughtErrorHandler handleUncaughtError;
-  final RunHandler run;
-  final RunUnaryHandler runUnary;
-  final RunBinaryHandler runBinary;
-  final RegisterCallbackHandler registerCallback;
-  final RegisterUnaryCallbackHandler registerUnaryCallback;
-  final RegisterBinaryCallbackHandler registerBinaryCallback;
-  final ErrorCallbackHandler errorCallback;
-  final ScheduleMicrotaskHandler scheduleMicrotask;
-  final CreateTimerHandler createTimer;
-  final CreatePeriodicTimerHandler createPeriodicTimer;
-  final PrintHandler print;
-  final ForkHandler fork;
+  final HandleUncaughtErrorHandler? handleUncaughtError;
+  final RunHandler? run;
+  final RunUnaryHandler? runUnary;
+  final RunBinaryHandler? runBinary;
+  final RegisterCallbackHandler? registerCallback;
+  final RegisterUnaryCallbackHandler? registerUnaryCallback;
+  final RegisterBinaryCallbackHandler? registerBinaryCallback;
+  final ErrorCallbackHandler? errorCallback;
+  final ScheduleMicrotaskHandler? scheduleMicrotask;
+  final CreateTimerHandler? createTimer;
+  final CreatePeriodicTimerHandler? createPeriodicTimer;
+  final PrintHandler? print;
+  final ForkHandler? fork;
 }
 
 /**
@@ -204,7 +202,7 @@
  *   to skip zones that would just delegate to their parents.
  */
 abstract class ZoneDelegate {
-  void handleUncaughtError(Zone zone, error, StackTrace stackTrace);
+  void handleUncaughtError(Zone zone, Object error, StackTrace? stackTrace);
   R run<R>(Zone zone, R f());
   R runUnary<R, T>(Zone zone, R f(T arg), T arg);
   R runBinary<R, T1, T2>(Zone zone, R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2);
@@ -212,12 +210,12 @@
   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(Zone zone, R f(T arg));
   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
       Zone zone, R f(T1 arg1, T2 arg2));
-  AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace);
+  AsyncError? errorCallback(Zone zone, Object error, StackTrace? stackTrace);
   void scheduleMicrotask(Zone zone, void f());
   Timer createTimer(Zone zone, Duration duration, void f());
   Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
   void print(Zone zone, String line);
-  Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues);
+  Zone fork(Zone zone, ZoneSpecification? specification, Map? zoneValues);
 }
 
 /**
@@ -288,7 +286,7 @@
   static const Zone root = _rootZone;
 
   /** The currently running zone. */
-  static Zone _current = _rootZone;
+  static _Zone _current = _rootZone;
 
   /** The zone that is currently active. */
   static Zone get current => _current;
@@ -311,7 +309,7 @@
    * By default, when handled by the root zone, uncaught asynchronous errors are
    * treated like uncaught synchronous exceptions.
    */
-  void handleUncaughtError(error, StackTrace stackTrace);
+  void handleUncaughtError(Object error, StackTrace? stackTrace);
 
   /**
    * The parent zone of the this zone.
@@ -322,7 +320,7 @@
    * forks the [current] zone. The new zone's parent zone is the zone it was
    * forked from.
    */
-  Zone get parent;
+  Zone? get parent;
 
   /**
    * The error zone is the one that is responsible for dealing with uncaught
@@ -343,7 +341,7 @@
    *   runZoned(() {
    *     // The asynchronous error is caught by the custom zone which prints
    *     // 'asynchronous error'.
-   *     future = new Future.error("asynchronous error");
+   *     future = Future.error("asynchronous error");
    *   }, onError: (e) { print(e); });  // Creates a zone with an error handler.
    *   // The following `catchError` handler is never invoked, because the
    *   // custom zone created by the call to `runZoned` provides an
@@ -364,7 +362,7 @@
    *     // with different error handlers.
    *     // Instead the error is handled by the current error handler,
    *     // printing "Caught by outer zone: asynchronous error".
-   *     var future = new Future.error("asynchronous error");
+   *     var future = Future.error("asynchronous error");
    *     runZoned(() {
    *       future.catchError((e) { throw "is never reached"; });
    *     }, onError: (e) { throw "is never reached"; });
@@ -396,7 +394,8 @@
    * the zone specification (or zone values), giving the forking zone full
    * control over the child zone.
    */
-  Zone fork({ZoneSpecification specification, Map zoneValues});
+  Zone fork(
+      {ZoneSpecification? specification, Map<Object?, Object?>? zoneValues});
 
   /**
    * Executes [action] in this zone.
@@ -604,7 +603,7 @@
    * errors are usually reported through future completers or stream
    * controllers.
    */
-  AsyncError errorCallback(Object error, StackTrace stackTrace);
+  AsyncError? errorCallback(Object error, StackTrace? stackTrace);
 
   /**
    * Runs [callback] asynchronously in this zone.
@@ -656,10 +655,9 @@
    *
    * The previous current zone is returned.
    */
-  static Zone _enter(Zone zone) {
-    assert(zone != null);
+  static _Zone _enter(_Zone zone) {
     assert(!identical(zone, _current));
-    Zone previous = _current;
+    _Zone previous = _current;
     _current = zone;
     return previous;
   }
@@ -669,7 +667,7 @@
    *
    * The previous Zone must be provided as `previous`.
    */
-  static void _leave(Zone previous) {
+  static void _leave(_Zone previous) {
     assert(previous != null);
     Zone._current = previous;
   }
@@ -685,12 +683,7 @@
    * By controlling access to the key, a zone can grant or deny access to the
    * zone value.
    */
-  operator [](Object key);
-}
-
-ZoneDelegate _parentDelegate(_Zone zone) {
-  if (zone.parent == null) return null;
-  return zone.parent._delegate;
+  dynamic operator [](Object? key);
 }
 
 class _ZoneDelegate implements ZoneDelegate {
@@ -698,100 +691,99 @@
 
   _ZoneDelegate(this._delegationTarget);
 
-  void handleUncaughtError(Zone zone, error, StackTrace stackTrace) {
+  void handleUncaughtError(Zone zone, Object error, StackTrace? stackTrace) {
     var implementation = _delegationTarget._handleUncaughtError;
     _Zone implZone = implementation.zone;
     HandleUncaughtErrorHandler handler = implementation.function;
-    return handler(
-        implZone, _parentDelegate(implZone), zone, error, stackTrace);
+    return handler(implZone, implZone._parentDelegate, zone, error, stackTrace);
   }
 
   R run<R>(Zone zone, R f()) {
     var implementation = _delegationTarget._run;
     _Zone implZone = implementation.zone;
-    RunHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    var handler = implementation.function as RunHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f);
   }
 
   R runUnary<R, T>(Zone zone, R f(T arg), T arg) {
     var implementation = _delegationTarget._runUnary;
     _Zone implZone = implementation.zone;
-    RunUnaryHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f, arg);
+    var handler = implementation.function as RunUnaryHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f, arg);
   }
 
   R runBinary<R, T1, T2>(Zone zone, R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) {
     var implementation = _delegationTarget._runBinary;
     _Zone implZone = implementation.zone;
-    RunBinaryHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f, arg1, arg2);
+    var handler = implementation.function as RunBinaryHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f, arg1, arg2);
   }
 
   ZoneCallback<R> registerCallback<R>(Zone zone, R f()) {
     var implementation = _delegationTarget._registerCallback;
     _Zone implZone = implementation.zone;
-    RegisterCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    var handler = implementation.function as RegisterCallbackHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f);
   }
 
   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(Zone zone, R f(T arg)) {
     var implementation = _delegationTarget._registerUnaryCallback;
     _Zone implZone = implementation.zone;
-    RegisterUnaryCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    var handler = implementation.function as RegisterUnaryCallbackHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f);
   }
 
   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
       Zone zone, R f(T1 arg1, T2 arg2)) {
     var implementation = _delegationTarget._registerBinaryCallback;
     _Zone implZone = implementation.zone;
-    RegisterBinaryCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    var handler = implementation.function as RegisterBinaryCallbackHandler;
+    return handler(implZone, implZone._parentDelegate, zone, f);
   }
 
-  AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) {
+  AsyncError? errorCallback(Zone zone, Object error, StackTrace? stackTrace) {
     var implementation = _delegationTarget._errorCallback;
     _Zone implZone = implementation.zone;
     if (identical(implZone, _rootZone)) return null;
     ErrorCallbackHandler handler = implementation.function;
-    return handler(
-        implZone, _parentDelegate(implZone), zone, error, stackTrace);
+    return handler(implZone, implZone._parentDelegate, zone, error, stackTrace);
   }
 
   void scheduleMicrotask(Zone zone, f()) {
     var implementation = _delegationTarget._scheduleMicrotask;
     _Zone implZone = implementation.zone;
     ScheduleMicrotaskHandler handler = implementation.function;
-    handler(implZone, _parentDelegate(implZone), zone, f);
+    handler(implZone, implZone._parentDelegate, zone, f);
   }
 
   Timer createTimer(Zone zone, Duration duration, void f()) {
     var implementation = _delegationTarget._createTimer;
     _Zone implZone = implementation.zone;
     CreateTimerHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, duration, f);
+    return handler(implZone, implZone._parentDelegate, zone, duration, f);
   }
 
   Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)) {
     var implementation = _delegationTarget._createPeriodicTimer;
     _Zone implZone = implementation.zone;
     CreatePeriodicTimerHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, period, f);
+    return handler(implZone, implZone._parentDelegate, zone, period, f);
   }
 
   void print(Zone zone, String line) {
     var implementation = _delegationTarget._print;
     _Zone implZone = implementation.zone;
     PrintHandler handler = implementation.function;
-    handler(implZone, _parentDelegate(implZone), zone, line);
+    handler(implZone, implZone._parentDelegate, zone, line);
   }
 
-  Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues) {
+  Zone fork(Zone zone, ZoneSpecification? specification,
+      Map<Object?, Object?>? zoneValues) {
     var implementation = _delegationTarget._fork;
     _Zone implZone = implementation.zone;
     ForkHandler handler = implementation.function;
     return handler(
-        implZone, _parentDelegate(implZone), zone, specification, zoneValues);
+        implZone, implZone._parentDelegate, zone, specification, zoneValues);
   }
 }
 
@@ -816,9 +808,11 @@
   _ZoneFunction<PrintHandler> get _print;
   _ZoneFunction<ForkHandler> get _fork;
   _ZoneFunction<HandleUncaughtErrorHandler> get _handleUncaughtError;
-  _Zone get parent;
+  // Parent zone. Only `null` for the root zone.
+  _Zone? get parent;
   ZoneDelegate get _delegate;
-  Map get _map;
+  ZoneDelegate get _parentDelegate;
+  Map<Object?, Object?> get _map;
 
   bool inSameErrorZone(Zone otherZone) {
     return identical(this, otherZone) ||
@@ -830,7 +824,7 @@
   // The actual zone and implementation of each of these
   // inheritable zone functions.
   // TODO(floitsch): the types of the `_ZoneFunction`s should have a type for
-  // all fields.
+  // all fields, but we can't use generic function types as type arguments.
   _ZoneFunction<Function> _run;
   _ZoneFunction<Function> _runUnary;
   _ZoneFunction<Function> _runBinary;
@@ -846,7 +840,7 @@
   _ZoneFunction<HandleUncaughtErrorHandler> _handleUncaughtError;
 
   // A cached delegate to this zone.
-  ZoneDelegate _delegateCache;
+  ZoneDelegate? _delegateCache;
 
   /// The parent zone.
   final _Zone parent;
@@ -854,62 +848,85 @@
   /// The zone's scoped value declaration map.
   ///
   /// This is always a [HashMap].
-  final Map _map;
+  final Map<Object?, Object?> _map;
 
-  ZoneDelegate get _delegate {
-    if (_delegateCache != null) return _delegateCache;
-    _delegateCache = new _ZoneDelegate(this);
-    return _delegateCache;
-  }
+  ZoneDelegate get _delegate => _delegateCache ??= _ZoneDelegate(this);
+  ZoneDelegate get _parentDelegate => parent._delegate;
 
-  _CustomZone(this.parent, ZoneSpecification specification, this._map) {
+  _CustomZone(this.parent, ZoneSpecification specification, this._map)
+      : _run = parent._run,
+        _runUnary = parent._runUnary,
+        _runBinary = parent._runBinary,
+        _registerCallback = parent._registerCallback,
+        _registerUnaryCallback = parent._registerUnaryCallback,
+        _registerBinaryCallback = parent._registerBinaryCallback,
+        _errorCallback = parent._errorCallback,
+        _scheduleMicrotask = parent._scheduleMicrotask,
+        _createTimer = parent._createTimer,
+        _createPeriodicTimer = parent._createPeriodicTimer,
+        _print = parent._print,
+        _fork = parent._fork,
+        _handleUncaughtError = parent._handleUncaughtError {
     // The root zone will have implementations of all parts of the
     // specification, so it will never try to access the (null) parent.
     // All other zones have a non-null parent.
-    _run = (specification.run != null)
-        ? new _ZoneFunction<Function>(this, specification.run)
-        : parent._run;
-    _runUnary = (specification.runUnary != null)
-        ? new _ZoneFunction<Function>(this, specification.runUnary)
-        : parent._runUnary;
-    _runBinary = (specification.runBinary != null)
-        ? new _ZoneFunction<Function>(this, specification.runBinary)
-        : parent._runBinary;
-    _registerCallback = (specification.registerCallback != null)
-        ? new _ZoneFunction<Function>(this, specification.registerCallback)
-        : parent._registerCallback;
-    _registerUnaryCallback = (specification.registerUnaryCallback != null)
-        ? new _ZoneFunction<Function>(this, specification.registerUnaryCallback)
-        : parent._registerUnaryCallback;
-    _registerBinaryCallback = (specification.registerBinaryCallback != null)
-        ? new _ZoneFunction<Function>(
-            this, specification.registerBinaryCallback)
-        : parent._registerBinaryCallback;
-    _errorCallback = (specification.errorCallback != null)
-        ? new _ZoneFunction<ErrorCallbackHandler>(
-            this, specification.errorCallback)
-        : parent._errorCallback;
-    _scheduleMicrotask = (specification.scheduleMicrotask != null)
-        ? new _ZoneFunction<ScheduleMicrotaskHandler>(
-            this, specification.scheduleMicrotask)
-        : parent._scheduleMicrotask;
-    _createTimer = (specification.createTimer != null)
-        ? new _ZoneFunction<CreateTimerHandler>(this, specification.createTimer)
-        : parent._createTimer;
-    _createPeriodicTimer = (specification.createPeriodicTimer != null)
-        ? new _ZoneFunction<CreatePeriodicTimerHandler>(
-            this, specification.createPeriodicTimer)
-        : parent._createPeriodicTimer;
-    _print = (specification.print != null)
-        ? new _ZoneFunction<PrintHandler>(this, specification.print)
-        : parent._print;
-    _fork = (specification.fork != null)
-        ? new _ZoneFunction<ForkHandler>(this, specification.fork)
-        : parent._fork;
-    _handleUncaughtError = (specification.handleUncaughtError != null)
-        ? new _ZoneFunction<HandleUncaughtErrorHandler>(
-            this, specification.handleUncaughtError)
-        : parent._handleUncaughtError;
+    var run = specification.run;
+    if (run != null) {
+      _run = _ZoneFunction<Function>(this, run);
+    }
+    var runUnary = specification.runUnary;
+    if (runUnary != null) {
+      _runUnary = _ZoneFunction<Function>(this, runUnary);
+    }
+    var runBinary = specification.runBinary;
+    if (runBinary != null) {
+      _runBinary = _ZoneFunction<Function>(this, runBinary);
+    }
+    var registerCallback = specification.registerCallback;
+    if (registerCallback != null) {
+      _registerCallback = _ZoneFunction<Function>(this, registerCallback);
+    }
+    var registerUnaryCallback = specification.registerUnaryCallback;
+    if (registerUnaryCallback != null) {
+      _registerUnaryCallback =
+          _ZoneFunction<Function>(this, registerUnaryCallback);
+    }
+    var registerBinaryCallback = specification.registerBinaryCallback;
+    if (registerBinaryCallback != null) {
+      _registerBinaryCallback =
+          _ZoneFunction<Function>(this, registerBinaryCallback);
+    }
+    var errorCallback = specification.errorCallback;
+    if (errorCallback != null) {
+      _errorCallback = _ZoneFunction<ErrorCallbackHandler>(this, errorCallback);
+    }
+    var scheduleMicrotask = specification.scheduleMicrotask;
+    if (scheduleMicrotask != null) {
+      _scheduleMicrotask =
+          _ZoneFunction<ScheduleMicrotaskHandler>(this, scheduleMicrotask);
+    }
+    var createTimer = specification.createTimer;
+    if (createTimer != null) {
+      _createTimer = _ZoneFunction<CreateTimerHandler>(this, createTimer);
+    }
+    var createPeriodicTimer = specification.createPeriodicTimer;
+    if (createPeriodicTimer != null) {
+      _createPeriodicTimer =
+          _ZoneFunction<CreatePeriodicTimerHandler>(this, createPeriodicTimer);
+    }
+    var print = specification.print;
+    if (print != null) {
+      _print = _ZoneFunction<PrintHandler>(this, print);
+    }
+    var fork = specification.fork;
+    if (fork != null) {
+      _fork = _ZoneFunction<ForkHandler>(this, fork);
+    }
+    var handleUncaughtError = specification.handleUncaughtError;
+    if (handleUncaughtError != null) {
+      _handleUncaughtError =
+          _ZoneFunction<HandleUncaughtErrorHandler>(this, handleUncaughtError);
+    }
   }
 
   /**
@@ -976,7 +993,7 @@
     return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2);
   }
 
-  operator [](Object key) {
+  dynamic operator [](Object? key) {
     var result = _map[key];
     if (result != null || _map.containsKey(key)) return result;
     // If we are not the root zone, look up in the parent zone.
@@ -997,19 +1014,18 @@
 
   // Methods that can be customized by the zone specification.
 
-  void handleUncaughtError(error, StackTrace stackTrace) {
+  void handleUncaughtError(Object error, StackTrace? stackTrace) {
     var implementation = this._handleUncaughtError;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     HandleUncaughtErrorHandler handler = implementation.function;
     return handler(
         implementation.zone, parentDelegate, this, error, stackTrace);
   }
 
-  Zone fork({ZoneSpecification specification, Map zoneValues}) {
+  Zone fork(
+      {ZoneSpecification? specification, Map<Object?, Object?>? zoneValues}) {
     var implementation = this._fork;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     ForkHandler handler = implementation.function;
     return handler(
         implementation.zone, parentDelegate, this, specification, zoneValues);
@@ -1017,111 +1033,103 @@
 
   R run<R>(R f()) {
     var implementation = this._run;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RunHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RunHandler;
     return handler(implementation.zone, parentDelegate, this, f);
   }
 
   R runUnary<R, T>(R f(T arg), T arg) {
     var implementation = this._runUnary;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RunUnaryHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RunUnaryHandler;
     return handler(implementation.zone, parentDelegate, this, f, arg);
   }
 
   R runBinary<R, T1, T2>(R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) {
     var implementation = this._runBinary;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RunBinaryHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RunBinaryHandler;
     return handler(implementation.zone, parentDelegate, this, f, arg1, arg2);
   }
 
   ZoneCallback<R> registerCallback<R>(R callback()) {
     var implementation = this._registerCallback;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RegisterCallbackHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RegisterCallbackHandler;
     return handler(implementation.zone, parentDelegate, this, callback);
   }
 
   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(R callback(T arg)) {
     var implementation = this._registerUnaryCallback;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RegisterUnaryCallbackHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RegisterUnaryCallbackHandler;
     return handler(implementation.zone, parentDelegate, this, callback);
   }
 
   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
       R callback(T1 arg1, T2 arg2)) {
     var implementation = this._registerBinaryCallback;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
-    RegisterBinaryCallbackHandler handler = implementation.function;
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
+    var handler = implementation.function as RegisterBinaryCallbackHandler;
     return handler(implementation.zone, parentDelegate, this, callback);
   }
 
-  AsyncError errorCallback(Object error, StackTrace stackTrace) {
+  AsyncError? errorCallback(Object error, StackTrace? stackTrace) {
     var implementation = this._errorCallback;
-    assert(implementation != null);
-    final Zone implementationZone = implementation.zone;
+    final _Zone implementationZone = implementation.zone;
     if (identical(implementationZone, _rootZone)) return null;
-    final ZoneDelegate parentDelegate = _parentDelegate(implementationZone);
+    final ZoneDelegate parentDelegate = implementationZone._parentDelegate;
     ErrorCallbackHandler handler = implementation.function;
     return handler(implementationZone, parentDelegate, this, error, stackTrace);
   }
 
   void scheduleMicrotask(void f()) {
     var implementation = this._scheduleMicrotask;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     ScheduleMicrotaskHandler handler = implementation.function;
     return handler(implementation.zone, parentDelegate, this, f);
   }
 
   Timer createTimer(Duration duration, void f()) {
     var implementation = this._createTimer;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     CreateTimerHandler handler = implementation.function;
     return handler(implementation.zone, parentDelegate, this, duration, f);
   }
 
   Timer createPeriodicTimer(Duration duration, void f(Timer timer)) {
     var implementation = this._createPeriodicTimer;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     CreatePeriodicTimerHandler handler = implementation.function;
     return handler(implementation.zone, parentDelegate, this, duration, f);
   }
 
   void print(String line) {
     var implementation = this._print;
-    assert(implementation != null);
-    ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
+    ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
     PrintHandler handler = implementation.function;
     return handler(implementation.zone, parentDelegate, this, line);
   }
 }
 
-void _rootHandleUncaughtError(
-    Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
+void _rootHandleUncaughtError(Zone? self, ZoneDelegate? parent, Zone zone,
+    Object error, StackTrace? stackTrace) {
   _schedulePriorityAsyncCallback(() {
-    error ??= new NullThrownError();
     if (stackTrace == null) throw error;
     _rethrow(error, stackTrace);
   });
 }
 
-external void _rethrow(Object error, StackTrace stackTrace);
+external void _rethrow(Object error, StackTrace? stackTrace);
 
-R _rootRun<R>(Zone self, ZoneDelegate parent, Zone zone, R f()) {
-  if (Zone._current == zone) return f();
+R _rootRun<R>(Zone? self, ZoneDelegate? parent, Zone zone, R f()) {
+  if (identical(Zone._current, zone)) return f();
 
-  Zone old = Zone._enter(zone);
+  if (zone is! _Zone) {
+    throw ArgumentError.value(zone, "zone", "Can only run in platform zones");
+  }
+
+  _Zone old = Zone._enter(zone);
   try {
     return f();
   } finally {
@@ -1130,10 +1138,14 @@
 }
 
 R _rootRunUnary<R, T>(
-    Zone self, ZoneDelegate parent, Zone zone, R f(T arg), T arg) {
-  if (Zone._current == zone) return f(arg);
+    Zone? self, ZoneDelegate? parent, Zone zone, R f(T arg), T arg) {
+  if (identical(Zone._current, zone)) return f(arg);
 
-  Zone old = Zone._enter(zone);
+  if (zone is! _Zone) {
+    throw ArgumentError.value(zone, "zone", "Can only run in platform zones");
+  }
+
+  _Zone old = Zone._enter(zone);
   try {
     return f(arg);
   } finally {
@@ -1141,11 +1153,15 @@
   }
 }
 
-R _rootRunBinary<R, T1, T2>(Zone self, ZoneDelegate parent, Zone zone,
+R _rootRunBinary<R, T1, T2>(Zone? self, ZoneDelegate? parent, Zone zone,
     R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2) {
-  if (Zone._current == zone) return f(arg1, arg2);
+  if (identical(Zone._current, zone)) return f(arg1, arg2);
 
-  Zone old = Zone._enter(zone);
+  if (zone is! _Zone) {
+    throw ArgumentError.value(zone, "zone", "Can only run in platform zones");
+  }
+
+  _Zone old = Zone._enter(zone);
   try {
     return f(arg1, arg2);
   } finally {
@@ -1168,12 +1184,12 @@
   return f;
 }
 
-AsyncError _rootErrorCallback(Zone self, ZoneDelegate parent, Zone zone,
-        Object error, StackTrace stackTrace) =>
+AsyncError? _rootErrorCallback(Zone self, ZoneDelegate parent, Zone zone,
+        Object error, StackTrace? stackTrace) =>
     null;
 
 void _rootScheduleMicrotask(
-    Zone self, ZoneDelegate parent, Zone zone, void f()) {
+    Zone? self, ZoneDelegate? parent, Zone zone, void f()) {
   if (!identical(_rootZone, zone)) {
     bool hasErrorHandler = !_rootZone.inSameErrorZone(zone);
     if (hasErrorHandler) {
@@ -1181,8 +1197,6 @@
     } else {
       f = zone.bindCallback(f);
     }
-    // Use root zone as event zone if the function is already bound.
-    zone = _rootZone;
   }
   _scheduleAsyncCallback(f);
 }
@@ -1198,8 +1212,7 @@
 Timer _rootCreatePeriodicTimer(Zone self, ZoneDelegate parent, Zone zone,
     Duration duration, void callback(Timer timer)) {
   if (!identical(_rootZone, zone)) {
-    // TODO(floitsch): the return type should be 'void'.
-    callback = zone.bindUnaryCallback<dynamic, Timer>(callback);
+    callback = zone.bindUnaryCallback<void, Timer>(callback);
   }
   return Timer._createPeriodicTimer(duration, callback);
 }
@@ -1212,8 +1225,11 @@
   Zone.current.print(line);
 }
 
-Zone _rootFork(Zone self, ZoneDelegate parent, Zone zone,
-    ZoneSpecification specification, Map zoneValues) {
+Zone _rootFork(Zone? self, ZoneDelegate? parent, Zone zone,
+    ZoneSpecification? specification, Map<Object?, Object?>? zoneValues) {
+  if (zone is! _Zone) {
+    throw ArgumentError.value(zone, "zone", "Can only fork a platform zone");
+  }
   // TODO(floitsch): it would be nice if we could get rid of this hack.
   // Change the static zoneOrDirectPrint function to go through zones
   // from now on.
@@ -1222,20 +1238,17 @@
   if (specification == null) {
     specification = const ZoneSpecification();
   } else if (specification is! _ZoneSpecification) {
-    throw new ArgumentError("ZoneSpecifications must be instantiated"
-        " with the provided constructor.");
+    specification = ZoneSpecification.from(specification);
   }
-  Map valueMap;
+  Map<Object?, Object?> valueMap;
   if (zoneValues == null) {
-    if (zone is _Zone) {
-      valueMap = zone._map;
-    } else {
-      valueMap = new HashMap();
-    }
+    valueMap = zone._map;
   } else {
-    valueMap = new HashMap.from(zoneValues);
+    valueMap = HashMap<Object?, Object?>.from(zoneValues);
   }
-  return new _CustomZone(zone, specification, valueMap);
+  if (specification == null)
+    throw "unreachable"; // TODO(lrn): Remove when type promotion works.
+  return _CustomZone(zone, specification, valueMap);
 }
 
 class _RootZone extends _Zone {
@@ -1272,21 +1285,20 @@
           _rootZone, _rootHandleUncaughtError);
 
   // The parent zone.
-  _Zone get parent => null;
+  _Zone? get parent => null;
 
   /// The zone's scoped value declaration map.
   ///
   /// This is always a [HashMap].
-  Map get _map => _rootMap;
+  Map<Object?, Object?> get _map => _rootMap;
 
-  static final _rootMap = new HashMap();
+  static final _rootMap = HashMap();
 
-  static ZoneDelegate _rootDelegate;
+  static ZoneDelegate? _rootDelegate;
 
-  ZoneDelegate get _delegate {
-    if (_rootDelegate != null) return _rootDelegate;
-    return _rootDelegate = new _ZoneDelegate(this);
-  }
+  ZoneDelegate get _delegate => _rootDelegate ??= new _ZoneDelegate(this);
+  // It's a lie, but the root zone never uses the parent delegate.
+  ZoneDelegate get _parentDelegate => _delegate;
 
   /**
    * The closest error-handling zone.
@@ -1360,15 +1372,16 @@
     return (arg1, arg2) => this.runBinaryGuarded(f, arg1, arg2);
   }
 
-  operator [](Object key) => null;
+  dynamic operator [](Object? key) => null;
 
   // Methods that can be customized by the zone specification.
 
-  void handleUncaughtError(error, StackTrace stackTrace) {
+  void handleUncaughtError(Object error, StackTrace? stackTrace) {
     _rootHandleUncaughtError(null, null, this, error, stackTrace);
   }
 
-  Zone fork({ZoneSpecification specification, Map zoneValues}) {
+  Zone fork(
+      {ZoneSpecification? specification, Map<Object?, Object?>? zoneValues}) {
     return _rootFork(null, null, this, specification, zoneValues);
   }
 
@@ -1395,7 +1408,7 @@
           R f(T1 arg1, T2 arg2)) =>
       f;
 
-  AsyncError errorCallback(Object error, StackTrace stackTrace) => null;
+  AsyncError? errorCallback(Object error, StackTrace? stackTrace) => null;
 
   void scheduleMicrotask(void f()) {
     _rootScheduleMicrotask(null, null, this, f);
@@ -1414,7 +1427,7 @@
   }
 }
 
-const _rootZone = const _RootZone();
+const _Zone _rootZone = const _RootZone();
 
 /**
  * Runs [body] in its own zone.
@@ -1441,7 +1454,7 @@
  * Errors that try to cross error-zone boundaries are considered uncaught in
  * their originating error zone.
  *
- *     var future = new Future.value(499);
+ *     var future = Future.value(499);
  *     runZoned(() {
  *       var future2 = future.then((_) { throw "error in first error-zone"; });
  *       runZoned(() {
@@ -1460,13 +1473,15 @@
  * occur in the original zone where [runZoned] was called.
  */
 R runZoned<R>(R body(),
-    {Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) {
+    {Map<Object?, Object?>? zoneValues,
+    ZoneSpecification? zoneSpecification,
+    Function? onError}) {
   if (onError == null) {
     return _runZoned<R>(body, zoneValues, zoneSpecification);
   }
-  void Function(Object) unaryOnError;
-  void Function(Object, StackTrace) binaryOnError;
-  if (onError is void Function(Object, StackTrace)) {
+  void Function(Object)? unaryOnError;
+  void Function(Object, StackTrace?)? binaryOnError;
+  if (onError is void Function(Object, StackTrace?)) {
     binaryOnError = onError;
   } else if (onError is void Function(Object)) {
     unaryOnError = onError;
@@ -1474,14 +1489,15 @@
     throw new ArgumentError("onError callback must take either an Object "
         "(the error), or both an Object (the error) and a StackTrace.");
   }
+  _Zone parentZone = Zone._current;
   HandleUncaughtErrorHandler errorHandler = (Zone self, ZoneDelegate parent,
-      Zone zone, error, StackTrace stackTrace) {
+      Zone zone, Object error, StackTrace? stackTrace) {
     try {
       if (binaryOnError != null) {
-        self.parent.runBinary(binaryOnError, error, stackTrace);
+        parentZone.runBinary(binaryOnError, error, stackTrace);
       } else {
         assert(unaryOnError != null);
-        self.parent.runUnary(unaryOnError, error);
+        parentZone.runUnary(unaryOnError!, error);
       }
     } catch (e, s) {
       if (identical(e, error)) {
@@ -1495,7 +1511,7 @@
     zoneSpecification =
         new ZoneSpecification(handleUncaughtError: errorHandler);
   } else {
-    zoneSpecification = new ZoneSpecification.from(zoneSpecification,
+    zoneSpecification = ZoneSpecification.from(zoneSpecification,
         handleUncaughtError: errorHandler);
   }
   try {
@@ -1505,14 +1521,17 @@
       binaryOnError(e, stackTrace);
     } else {
       assert(unaryOnError != null);
-      unaryOnError(e);
+      unaryOnError!(e);
     }
   }
-  return null;
+  // TODO(lrn): Change behavior to throw the actual resulting error,
+  // perhaps even synchronously.
+  return null as R;
 }
 
 /// Runs [body] in a new zone based on [zoneValues] and [specification].
-R _runZoned<R>(R body(), Map zoneValues, ZoneSpecification specification) =>
+R _runZoned<R>(R body(), Map<Object?, Object?>? zoneValues,
+        ZoneSpecification? specification) =>
     Zone.current
         .fork(specification: specification, zoneValues: zoneValues)
         .run<R>(body);
diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart
index 262490f..2ae10f0 100644
--- a/sdk_nnbd/lib/collection/list.dart
+++ b/sdk_nnbd/lib/collection/list.dart
@@ -102,7 +102,7 @@
     return this[0];
   }
 
-  bool contains(Object element) {
+  bool contains(Object? element) {
     int length = this.length;
     for (int i = 0; i < length; i++) {
       if (this[i] == element) return true;
@@ -269,7 +269,7 @@
     }
   }
 
-  bool remove(Object element) {
+  bool remove(Object? element) {
     for (int i = 0; i < this.length; i++) {
       if (this[i] == element) {
         this._closeGap(i, i + 1);
@@ -456,7 +456,7 @@
     }
   }
 
-  int indexOf(Object element, [int start = 0]) {
+  int indexOf(E element, [int start = 0]) {
     if (start < 0) start = 0;
     for (int i = start; i < this.length; i++) {
       if (this[i] == element) return i;
@@ -472,7 +472,7 @@
     return -1;
   }
 
-  int lastIndexOf(Object element, [int? start]) {
+  int lastIndexOf(E element, [int? start]) {
     if (start == null || start >= this.length) start = this.length - 1;
 
     // TODO(38493): The previous line should promote.
diff --git a/sdk_nnbd/lib/collection/queue.dart b/sdk_nnbd/lib/collection/queue.dart
index 685f5dc..c2fc394 100644
--- a/sdk_nnbd/lib/collection/queue.dart
+++ b/sdk_nnbd/lib/collection/queue.dart
@@ -89,7 +89,7 @@
   ///
   /// Returns `true` if a value was removed, or `false` if the queue
   /// contained no element equal to [value].
-  bool remove(Object value);
+  bool remove(Object? value);
 
   /// Adds all elements of [iterable] at the end of the queue. The
   /// length of the queue is extended by the length of [iterable].
diff --git a/sdk_nnbd/lib/core/errors.dart b/sdk_nnbd/lib/core/errors.dart
index 044e2aa..46b852a 100644
--- a/sdk_nnbd/lib/core/errors.dart
+++ b/sdk_nnbd/lib/core/errors.dart
@@ -590,3 +590,8 @@
         : "Reading static variable '$variableName' during its initialization";
   }
 }
+
+/**
+ * Error thrown when a late field is set or get when it shouldn't be.
+ */
+class LateInitializationError extends Error {}
diff --git a/sdk_nnbd/lib/core/list.dart b/sdk_nnbd/lib/core/list.dart
index 2ef1601..f72158f 100644
--- a/sdk_nnbd/lib/core/list.dart
+++ b/sdk_nnbd/lib/core/list.dart
@@ -544,7 +544,7 @@
    *
    * An [UnsupportedError] occurs if the list is fixed-length.
    */
-  bool remove(Object value);
+  bool remove(Object? value);
 
   /**
    * Removes the object at position [index] from this list.
diff --git a/sdk_nnbd/lib/developer/developer.dart b/sdk_nnbd/lib/developer/developer.dart
index 5e0df5a..e9df841 100644
--- a/sdk_nnbd/lib/developer/developer.dart
+++ b/sdk_nnbd/lib/developer/developer.dart
@@ -39,7 +39,7 @@
 /// Send a reference to [object] to any attached debuggers.
 ///
 /// Debuggers may open an inspector on the object. Returns the argument.
-external Object inspect(Object? object);
+external Object? inspect(Object? object);
 
 /// Emit a log event.
 ///
diff --git a/sdk_nnbd/lib/developer/extension.dart b/sdk_nnbd/lib/developer/extension.dart
index bf03cd9..184a00f 100644
--- a/sdk_nnbd/lib/developer/extension.dart
+++ b/sdk_nnbd/lib/developer/extension.dart
@@ -158,5 +158,5 @@
 // these into Dart code unless you can ensure that the operations will can be
 // done atomically. Native code lives in vm/isolate.cc-
 // LookupServiceExtensionHandler and RegisterServiceExtensionHandler.
-external ServiceExtensionHandler _lookupExtension(String method);
+external ServiceExtensionHandler? _lookupExtension(String method);
 external _registerExtension(String method, ServiceExtensionHandler handler);
diff --git a/sdk_nnbd/lib/developer/service.dart b/sdk_nnbd/lib/developer/service.dart
index a9757e4..9fab7f4 100644
--- a/sdk_nnbd/lib/developer/service.dart
+++ b/sdk_nnbd/lib/developer/service.dart
@@ -19,7 +19,7 @@
 
   /// The Uri to access the service. If the web server is not running, this
   /// will be null.
-  final Uri serverUri;
+  final Uri? serverUri;
 
   ServiceProtocolInfo(this.serverUri);
 
@@ -77,7 +77,7 @@
   ///
   /// Returns null if the running Dart environment does not support the service
   /// protocol.
-  static String getIsolateID(Isolate isolate) {
+  static String? getIsolateID(Isolate isolate) {
     // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(isolate, 'isolate');
     return _getIsolateIDFromSendPort(isolate.controlPort);
@@ -97,4 +97,4 @@
 external int _getServiceMinorVersion();
 
 /// Returns the service id for the isolate that owns [sendPort].
-external String _getIsolateIDFromSendPort(SendPort sendPort);
+external String? _getIsolateIDFromSendPort(SendPort sendPort);
diff --git a/sdk_nnbd/lib/ffi/ffi.dart b/sdk_nnbd/lib/ffi/ffi.dart
index a8428bc..1962918 100644
--- a/sdk_nnbd/lib/ffi/ffi.dart
+++ b/sdk_nnbd/lib/ffi/ffi.dart
@@ -7,8 +7,7 @@
 /**
  * Foreign Function Interface for interoperability with the C programming language.
  *
- * **NOTE**: Dart:FFI is in technical preview. The overall feature is incomplete,
- * may contain issues, and breaking API changes are still expected.
+ * **NOTE**: Dart:FFI is in beta, and breaking API changes might still happen.
  *
  * For further details, please see: https://dart.dev/server/c-interop
  *
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index bcad33f..c7913ec 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * HTML elements and other resources for web-based applications that need to
  * interact with the browser and the DOM (Document Object Model).
diff --git a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
index b287be1..1ff21ba 100644
--- a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
@@ -100,14 +100,6 @@
 bool isJavaScriptPromise(value) =>
     JS('bool', r'typeof Promise != "undefined" && # instanceof Promise', value);
 
-Future<T> promiseToFuture<T>(promise) {
-  var completer = new Completer<T>();
-  var then = convertDartClosureToJS((r) => completer.complete(r), 1);
-  var error = convertDartClosureToJS((e) => completer.completeError(e), 1);
-  JS('', '#.then(#, #)', promise, then, error);
-  return completer.future;
-}
-
 const String _serializedScriptValue = 'num|String|bool|'
     'JSExtendableArray|=Object|'
     'Blob|File|NativeByteBuffer|NativeTypedData|MessagePort'
diff --git a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
index 710d1f1..73141ac 100644
--- a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
@@ -17,6 +17,9 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_interceptors' show Interceptor, JSExtendableArray, JSObject;
 
+import 'dart:js_util' show promiseToFuture;
+export 'dart:js_util' show promiseToFuture;
+
 import 'dart:_metadata';
 export 'dart:_metadata';
 
diff --git a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index baefa2a..f1acb15 100644
--- a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * A client-side key-value store with support for indexes.
  *
diff --git a/sdk_nnbd/lib/internal/async_cast.dart b/sdk_nnbd/lib/internal/async_cast.dart
index 9f4448d..677f303 100644
--- a/sdk_nnbd/lib/internal/async_cast.dart
+++ b/sdk_nnbd/lib/internal/async_cast.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 // Casting wrappers for asynchronous classes.
@@ -13,8 +11,8 @@
   CastStream(this._source);
   bool get isBroadcast => _source.isBroadcast;
 
-  StreamSubscription<T> listen(void onData(T data),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void Function(T data)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     return new CastStreamSubscription<S, T>(
         _source.listen(null, onDone: onDone, cancelOnError: cancelOnError))
       ..onData(onData)
@@ -30,12 +28,11 @@
   /// Zone where listen was called.
   final Zone _zone = Zone.current;
 
-  /// User's data handler. May be null.
-  void Function(T) _handleData;
+  /// User's data handler.
+  void Function(T)? _handleData;
 
   /// Copy of _source's handleError so we can report errors in onData.
-  /// May be null.
-  Function _handleError;
+  Function? _handleError;
 
   CastStreamSubscription(this._source) {
     _source.onData(_onData);
@@ -43,25 +40,28 @@
 
   Future cancel() => _source.cancel();
 
-  void onData(void handleData(T data)) {
+  void onData(void Function(T data)? handleData) {
     _handleData = handleData == null
         ? null
         : _zone.registerUnaryCallback<dynamic, T>(handleData);
   }
 
-  void onError(Function handleError) {
+  void onError(Function? handleError) {
     _source.onError(handleError);
     if (handleError == null) {
       _handleError = null;
-    } else if (handleError is Function(Null, Null)) {
+    } else if (handleError is void Function(Object, StackTrace?)) {
       _handleError = _zone
-          .registerBinaryCallback<dynamic, Object, StackTrace>(handleError);
-    } else {
+          .registerBinaryCallback<dynamic, Object, StackTrace?>(handleError);
+    } else if (handleError is void Function(Object)) {
       _handleError = _zone.registerUnaryCallback<dynamic, Object>(handleError);
+    } else {
+      throw ArgumentError("handleError callback must take either an Object "
+          "(the error), or both an Object (the error) and a StackTrace.");
     }
   }
 
-  void onDone(void handleDone()) {
+  void onDone(void handleDone()?) {
     _source.onDone(handleDone);
   }
 
@@ -71,19 +71,21 @@
     try {
       targetData = data as T;
     } catch (error, stack) {
-      if (_handleError == null) {
+      var handleError = _handleError;
+      if (handleError == null) {
         _zone.handleUncaughtError(error, stack);
-      } else if (_handleError is Function(Null, Null)) {
-        _zone.runBinaryGuarded(_handleError, error, stack);
+      } else if (handleError is void Function(Object, StackTrace?)) {
+        _zone.runBinaryGuarded<Object, StackTrace?>(handleError, error, stack);
       } else {
-        _zone.runUnaryGuarded(_handleError, error);
+        _zone.runUnaryGuarded<Object>(
+            handleError as void Function(Object), error);
       }
       return;
     }
-    _zone.runUnaryGuarded(_handleData, targetData);
+    _zone.runUnaryGuarded(_handleData!, targetData);
   }
 
-  void pause([Future resumeSignal]) {
+  void pause([Future? resumeSignal]) {
     _source.pause(resumeSignal);
   }
 
@@ -93,7 +95,7 @@
 
   bool get isPaused => _source.isPaused;
 
-  Future<E> asFuture<E>([E futureValue]) => _source.asFuture<E>(futureValue);
+  Future<E> asFuture<E>([E? futureValue]) => _source.asFuture<E>(futureValue);
 }
 
 class CastStreamTransformer<SS, ST, TS, TT>
diff --git a/sdk_nnbd/lib/internal/cast.dart b/sdk_nnbd/lib/internal/cast.dart
index ae20c66..f994dab 100644
--- a/sdk_nnbd/lib/internal/cast.dart
+++ b/sdk_nnbd/lib/internal/cast.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 // Casting wrappers for collection classes.
@@ -46,11 +44,11 @@
   T get last => _source.last as T;
   T get single => _source.single as T;
 
-  bool contains(Object other) => _source.contains(other);
+  bool contains(Object? other) => _source.contains(other);
 
   // Might be implemented by testing backwards from the end,
   // so use the _source's implementation.
-  T lastWhere(bool test(T element), {T orElse()}) =>
+  T lastWhere(bool test(T element), {T Function()? orElse}) =>
       _source.lastWhere((S element) => test(element as T),
           orElse: (orElse == null) ? null : () => orElse() as S) as T;
 
@@ -116,12 +114,12 @@
     _source.addAll(new CastIterable<T, S>(values));
   }
 
-  void sort([int compare(T v1, T v2)]) {
+  void sort([int Function(T v1, T v2)? compare]) {
     _source.sort(
         compare == null ? null : (S v1, S v2) => compare(v1 as T, v2 as T));
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     _source.shuffle(random);
   }
 
@@ -137,7 +135,7 @@
     _source.setAll(index, new CastIterable<T, S>(elements));
   }
 
-  bool remove(Object value) => _source.remove(value);
+  bool remove(Object? value) => _source.remove(value);
 
   T removeAt(int index) => _source.removeAt(index) as T;
 
@@ -162,7 +160,7 @@
     _source.removeRange(start, end);
   }
 
-  void fillRange(int start, int end, [T fillValue]) {
+  void fillRange(int start, int end, [T? fillValue]) {
     _source.fillRange(start, end, fillValue as S);
   }
 
@@ -184,7 +182,7 @@
   /// Creates a new empty set of the same *kind* as [_source],
   /// but with `<R>` as type argument.
   /// Used by [toSet] and [union].
-  final Set<R> Function<R>() _emptySet;
+  final Set<R> Function<R>()? _emptySet;
 
   CastSet(this._source, this._emptySet);
 
@@ -197,13 +195,13 @@
     _source.addAll(new CastIterable<T, S>(elements));
   }
 
-  bool remove(Object object) => _source.remove(object);
+  bool remove(Object? object) => _source.remove(object);
 
-  void removeAll(Iterable<Object> objects) {
+  void removeAll(Iterable<Object?> objects) {
     _source.removeAll(objects);
   }
 
-  void retainAll(Iterable<Object> objects) {
+  void retainAll(Iterable<Object?> objects) {
     _source.retainAll(objects);
   }
 
@@ -215,20 +213,21 @@
     _source.retainWhere((S element) => test(element as T));
   }
 
-  bool containsAll(Iterable<Object> objects) => _source.containsAll(objects);
+  bool containsAll(Iterable<Object?> objects) => _source.containsAll(objects);
 
-  Set<T> intersection(Set<Object> other) {
+  Set<T> intersection(Set<Object?> other) {
     if (_emptySet != null) return _conditionalAdd(other, true);
     return new CastSet<S, T>(_source.intersection(other), null);
   }
 
-  Set<T> difference(Set<Object> other) {
+  Set<T> difference(Set<Object?> other) {
     if (_emptySet != null) return _conditionalAdd(other, false);
     return new CastSet<S, T>(_source.difference(other), null);
   }
 
-  Set<T> _conditionalAdd(Set<Object> other, bool otherContains) {
-    Set<T> result = (_emptySet == null) ? new Set<T>() : _emptySet<T>();
+  Set<T> _conditionalAdd(Set<Object?> other, bool otherContains) {
+    var emptySet = _emptySet;
+    Set<T> result = (emptySet == null) ? new Set<T>() : emptySet<T>();
     for (var element in _source) {
       T castElement = element as T;
       if (otherContains == other.contains(castElement)) result.add(castElement);
@@ -243,14 +242,15 @@
   }
 
   Set<T> _clone() {
-    Set<T> result = (_emptySet == null) ? new Set<T>() : _emptySet<T>();
+    var emptySet = _emptySet;
+    Set<T> result = (emptySet == null) ? new Set<T>() : emptySet<T>();
     result.addAll(this);
     return result;
   }
 
   Set<T> toSet() => _clone();
 
-  T lookup(Object key) => _source.lookup(key) as T;
+  T lookup(Object? key) => _source.lookup(key) as T;
 }
 
 class CastMap<SK, SV, K, V> extends MapBase<K, V> {
@@ -260,11 +260,11 @@
 
   Map<RK, RV> cast<RK, RV>() => new CastMap<SK, SV, RK, RV>(_source);
 
-  bool containsValue(Object value) => _source.containsValue(value);
+  bool containsValue(Object? value) => _source.containsValue(value);
 
-  bool containsKey(Object key) => _source.containsKey(key);
+  bool containsKey(Object? key) => _source.containsKey(key);
 
-  V operator [](Object key) => _source[key] as V;
+  V? operator [](Object? key) => _source[key] as V?;
 
   void operator []=(K key, V value) {
     _source[key as SK] = value as SV;
@@ -277,7 +277,7 @@
     _source.addAll(new CastMap<K, V, SK, SV>(other));
   }
 
-  V remove(Object key) => _source.remove(key) as V;
+  V remove(Object? key) => _source.remove(key) as V;
 
   void clear() {
     _source.clear();
@@ -299,7 +299,7 @@
 
   bool get isNotEmpty => _source.isNotEmpty;
 
-  V update(K key, V update(V value), {V ifAbsent()}) {
+  V update(K key, V update(V value), {V Function()? ifAbsent}) {
     return _source.update(key as SK, (SV value) => update(value as V) as SV,
         ifAbsent: (ifAbsent == null) ? null : () => ifAbsent() as SV) as V;
   }
@@ -344,7 +344,7 @@
     _source.addLast(value as S);
   }
 
-  bool remove(Object other) => _source.remove(other);
+  bool remove(Object? other) => _source.remove(other);
   void addAll(Iterable<T> elements) {
     _source.addAll(new CastIterable<T, S>(elements));
   }
diff --git a/sdk_nnbd/lib/internal/internal.dart b/sdk_nnbd/lib/internal/internal.dart
index 94fb13e..11ee996 100644
--- a/sdk_nnbd/lib/internal/internal.dart
+++ b/sdk_nnbd/lib/internal/internal.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 library dart._internal;
 
 import 'dart:collection';
diff --git a/sdk_nnbd/lib/internal/iterable.dart b/sdk_nnbd/lib/internal/iterable.dart
index 55cf780..3865626 100644
--- a/sdk_nnbd/lib/internal/iterable.dart
+++ b/sdk_nnbd/lib/internal/iterable.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /**
@@ -63,7 +61,7 @@
     return elementAt(0);
   }
 
-  bool contains(Object element) {
+  bool contains(Object? element) {
     int length = this.length;
     for (int i = 0; i < length; i++) {
       if (elementAt(i) == element) return true;
@@ -96,7 +94,7 @@
     return false;
   }
 
-  E firstWhere(bool test(E element), {E orElse()}) {
+  E firstWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
     for (int i = 0; i < length; i++) {
       E element = elementAt(i);
@@ -109,7 +107,7 @@
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E element), {E orElse()}) {
+  E lastWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
     for (int i = length - 1; i >= 0; i--) {
       E element = elementAt(i);
@@ -122,9 +120,9 @@
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E element), {E orElse()}) {
+  E singleWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
-    E match = null;
+    late E match;
     bool matchFound = false;
     for (int i = 0; i < length; i++) {
       E element = elementAt(i);
@@ -210,18 +208,7 @@
 
   Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test);
 
-  List<E> toList({bool growable: true}) {
-    List<E> result;
-    if (growable) {
-      result = <E>[]..length = length;
-    } else {
-      result = new List<E>(length);
-    }
-    for (int i = 0; i < length; i++) {
-      result[i] = elementAt(i);
-    }
-    return result;
-  }
+  List<E> toList({bool growable: true}) => List<E>.of(this, growable: growable);
 
   Set<E> toSet() {
     Set<E> result = new Set<E>();
@@ -236,22 +223,24 @@
   final Iterable<E> _iterable; // Has efficient length and elementAt.
   final int _start;
   /** If null, represents the length of the iterable. */
-  final int _endOrLength;
+  final int? _endOrLength;
 
   SubListIterable(this._iterable, this._start, this._endOrLength) {
     RangeError.checkNotNegative(_start, "start");
-    if (_endOrLength != null) {
-      RangeError.checkNotNegative(_endOrLength, "end");
-      if (_start > _endOrLength) {
-        throw new RangeError.range(_start, 0, _endOrLength, "start");
+    int? endOrLength = _endOrLength;
+    if (endOrLength != null) {
+      RangeError.checkNotNegative(endOrLength, "end");
+      if (_start > endOrLength) {
+        throw new RangeError.range(_start, 0, endOrLength, "start");
       }
     }
   }
 
   int get _endIndex {
     int length = _iterable.length;
-    if (_endOrLength == null || _endOrLength > length) return length;
-    return _endOrLength;
+    int? endOrLength = _endOrLength;
+    if (endOrLength == null || endOrLength > length) return length;
+    return endOrLength;
   }
 
   int get _startIndex {
@@ -263,10 +252,11 @@
   int get length {
     int length = _iterable.length;
     if (_start >= length) return 0;
-    if (_endOrLength == null || _endOrLength >= length) {
+    int? endOrLength = _endOrLength;
+    if (endOrLength == null || endOrLength >= length) {
       return length - _start;
     }
-    return _endOrLength - _start;
+    return endOrLength - _start;
   }
 
   E elementAt(int index) {
@@ -280,7 +270,8 @@
   Iterable<E> skip(int count) {
     RangeError.checkNotNegative(count, "count");
     int newStart = _start + count;
-    if (_endOrLength != null && newStart >= _endOrLength) {
+    int? endOrLength = _endOrLength;
+    if (endOrLength != null && newStart >= endOrLength) {
       return new EmptyIterable<E>();
     }
     return new SubListIterable<E>(_iterable, newStart, _endOrLength);
@@ -288,11 +279,12 @@
 
   Iterable<E> take(int count) {
     RangeError.checkNotNegative(count, "count");
-    if (_endOrLength == null) {
+    int? endOrLength = _endOrLength;
+    if (endOrLength == null) {
       return new SubListIterable<E>(_iterable, _start, _start + count);
     } else {
       int newEnd = _start + count;
-      if (_endOrLength < newEnd) return this;
+      if (endOrLength < newEnd) return this;
       return new SubListIterable<E>(_iterable, _start, newEnd);
     }
   }
@@ -300,12 +292,14 @@
   List<E> toList({bool growable: true}) {
     int start = _start;
     int end = _iterable.length;
-    if (_endOrLength != null && _endOrLength < end) end = _endOrLength;
+    int? endOrLength = _endOrLength;
+    if (endOrLength != null && endOrLength < end) end = endOrLength;
     int length = end - start;
-    if (length < 0) length = 0;
+    if (length <= 0) return List<E>.empty(growable: growable);
+
     List<E> result =
-        growable ? (new List<E>()..length = length) : new List<E>(length);
-    for (int i = 0; i < length; i++) {
+        List<E>.filled(length, _iterable.elementAt(start), growable: growable);
+    for (int i = 1; i < length; i++) {
       result[i] = _iterable.elementAt(start + i);
       if (_iterable.length < end) throw new ConcurrentModificationError(this);
     }
@@ -324,14 +318,14 @@
   final Iterable<E> _iterable;
   final int _length;
   int _index;
-  E _current;
+  E? _current;
 
   ListIterator(Iterable<E> iterable)
       : _iterable = iterable,
         _length = iterable.length,
         _index = 0;
 
-  E get current => _current;
+  E get current => _current as E;
 
   @pragma("vm:prefer-inline")
   bool moveNext() {
@@ -384,7 +378,7 @@
 }
 
 class MappedIterator<S, T> extends Iterator<T> {
-  T _current;
+  T? _current;
   final Iterator<S> _iterator;
   final _Transformation<S, T> _f;
 
@@ -399,7 +393,7 @@
     return false;
   }
 
-  T get current => _current;
+  T get current => _current as T;
 }
 
 /**
@@ -466,16 +460,16 @@
   // Initialize _currentExpansion to an empty iterable. A null value
   // marks the end of iteration, and we don't want to call _f before
   // the first moveNext call.
-  Iterator<T> _currentExpansion = const EmptyIterator();
-  T _current;
+  Iterator<T>? _currentExpansion = const EmptyIterator<Never>();
+  T? _current;
 
   ExpandIterator(this._iterator, this._f);
 
-  T get current => _current;
+  T get current => _current as T;
 
   bool moveNext() {
     if (_currentExpansion == null) return false;
-    while (!_currentExpansion.moveNext()) {
+    while (!_currentExpansion!.moveNext()) {
       _current = null;
       if (_iterator.moveNext()) {
         // If _f throws, this ends iteration. Otherwise _currentExpansion and
@@ -486,7 +480,7 @@
         return false;
       }
     }
-    _current = _currentExpansion.current;
+    _current = _currentExpansion!.current;
     return true;
   }
 }
@@ -541,7 +535,11 @@
   }
 
   E get current {
-    if (_remaining < 0) return null;
+    // Before NNBD, this returned null when iteration was complete. In order to
+    // avoid a hard breaking change, we return "null as E" in that case so that
+    // if strong checking is not enabled or E is nullable, the existing
+    // behavior is preserved.
+    if (_remaining < 0) return null as E;
     return _iterator.current;
   }
 }
@@ -574,7 +572,7 @@
   }
 
   E get current {
-    if (_isFinished) return null;
+    if (_isFinished) throw IterableElementError.noElement();
     return _iterator.current;
   }
 }
@@ -682,7 +680,7 @@
 class EmptyIterable<E> extends EfficientLengthIterable<E> {
   const EmptyIterable();
 
-  Iterator<E> get iterator => const EmptyIterator();
+  Iterator<E> get iterator => const EmptyIterator<Never>();
 
   void forEach(void action(E element)) {}
 
@@ -706,23 +704,23 @@
     throw new RangeError.range(index, 0, 0, "index");
   }
 
-  bool contains(Object element) => false;
+  bool contains(Object? element) => false;
 
   bool every(bool test(E element)) => true;
 
   bool any(bool test(E element)) => false;
 
-  E firstWhere(bool test(E element), {E orElse()}) {
+  E firstWhere(bool test(E element), {E Function()? orElse}) {
     if (orElse != null) return orElse();
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E element), {E orElse()}) {
+  E lastWhere(bool test(E element), {E Function()? orElse}) {
     if (orElse != null) return orElse();
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E element), {E orElse()}) {
+  E singleWhere(bool test(E element), {E Function()? orElse}) {
     if (orElse != null) return orElse();
     throw IterableElementError.noElement();
   }
@@ -755,7 +753,7 @@
 
   Iterable<E> takeWhile(bool test(E element)) => this;
 
-  List<E> toList({bool growable: true}) => growable ? <E>[] : new List<E>(0);
+  List<E> toList({bool growable: true}) => List<E>.empty(growable: growable);
 
   Set<E> toSet() => new Set<E>();
 }
@@ -764,11 +762,13 @@
 class EmptyIterator<E> implements Iterator<E> {
   const EmptyIterator();
   bool moveNext() => false;
-  E get current => null;
+  E get current {
+    throw IterableElementError.noElement();
+  }
 }
 
 class FollowedByIterable<E> extends Iterable<E> {
-  final Iterable<E> _first;
+  final EfficientLengthIterable<E> _first;
   final Iterable<E> _second;
   FollowedByIterable(this._first, this._second);
 
@@ -787,7 +787,7 @@
   bool get isNotEmpty => _first.isNotEmpty || _second.isNotEmpty;
 
   // May be more efficient if either iterable is a Set.
-  bool contains(Object value) =>
+  bool contains(Object? value) =>
       _first.contains(value) || _second.contains(value);
 
   E get first {
@@ -816,20 +816,6 @@
       EfficientLengthIterable<E> first, EfficientLengthIterable<E> second)
       : super(first, second);
 
-  Iterable<E> skip(int count) {
-    int firstLength = _first.length;
-    if (count >= firstLength) return _second.skip(count - firstLength);
-    return new EfficientLengthFollowedByIterable<E>(
-        _first.skip(count), _second);
-  }
-
-  Iterable<E> take(int count) {
-    int firstLength = _first.length;
-    if (count <= firstLength) return _first.take(count);
-    return new EfficientLengthFollowedByIterable<E>(
-        _first, _second.take(count - firstLength));
-  }
-
   E elementAt(int index) {
     int firstLength = _first.length;
     if (index < firstLength) return _first.elementAt(index);
@@ -849,7 +835,7 @@
 
 class FollowedByIterator<E> implements Iterator<E> {
   Iterator<E> _currentIterator;
-  Iterable<E> _nextIterable;
+  Iterable<E>? _nextIterable;
 
   FollowedByIterator(Iterable<E> first, this._nextIterable)
       : _currentIterator = first.iterator;
@@ -857,7 +843,7 @@
   bool moveNext() {
     if (_currentIterator.moveNext()) return true;
     if (_nextIterable != null) {
-      _currentIterator = _nextIterable.iterator;
+      _currentIterator = _nextIterable!.iterator;
       _nextIterable = null;
       return _currentIterator.moveNext();
     }
@@ -883,7 +869,7 @@
     return false;
   }
 
-  T get current => _source.current;
+  T get current => _source.current as T;
 }
 
 /**
diff --git a/sdk_nnbd/lib/internal/linked_list.dart b/sdk_nnbd/lib/internal/linked_list.dart
index 5c2e79a..e11cd7d 100644
--- a/sdk_nnbd/lib/internal/linked_list.dart
+++ b/sdk_nnbd/lib/internal/linked_list.dart
@@ -2,14 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /// A rudimentary linked list.
 class LinkedList<T extends LinkedListEntry<T>> extends IterableBase<T> {
-  T first;
-  T last;
+  T get first => _first as T;
+  T? _first;
+
+  T get last => _last as T;
+  T? _last;
+
   int length = 0;
 
   bool get isEmpty => length == 0;
@@ -19,15 +21,15 @@
    */
   void add(T newLast) {
     assert(newLast._next == null && newLast._previous == null);
-    if (last != null) {
-      assert(last._next == null);
-      last._next = newLast;
+    if (_last != null) {
+      assert(_last!._next == null);
+      _last!._next = newLast;
     } else {
-      first = newLast;
+      _first = newLast;
     }
-    newLast._previous = last;
-    last = newLast;
-    last._list = this;
+    newLast._previous = _last;
+    _last = newLast;
+    _last!._list = this;
     length++;
   }
 
@@ -35,15 +37,15 @@
    * Adds [newFirst] to the beginning of this linked list.
    */
   void addFirst(T newFirst) {
-    if (first != null) {
-      assert(first._previous == null);
-      first._previous = newFirst;
+    if (_first != null) {
+      assert(_first!._previous == null);
+      _first!._previous = newFirst;
     } else {
-      last = newFirst;
+      _last = newFirst;
     }
-    newFirst._next = first;
-    first = newFirst;
-    first._list = this;
+    newFirst._next = _first;
+    _first = newFirst;
+    _first!._list = this;
     length++;
   }
 
@@ -58,16 +60,16 @@
     if (node._list != this) return;
     length--;
     if (node._previous == null) {
-      assert(identical(node, first));
-      first = node._next;
+      assert(identical(node, _first));
+      _first = node._next;
     } else {
-      node._previous._next = node._next;
+      node._previous!._next = node._next;
     }
     if (node._next == null) {
-      assert(identical(node, last));
-      last = node._previous;
+      assert(identical(node, _last));
+      _last = node._previous;
     } else {
-      node._next._previous = node._previous;
+      node._next!._previous = node._previous;
     }
     node._next = node._previous = null;
     node._list = null;
@@ -77,9 +79,9 @@
 }
 
 class LinkedListEntry<T extends LinkedListEntry<T>> {
-  T _next;
-  T _previous;
-  LinkedList<T> _list;
+  T? _next;
+  T? _previous;
+  LinkedList<T>? _list;
 
   /**
    * Unlinks the element from its linked list.
@@ -89,15 +91,14 @@
    * is currently in.
    */
   void unlink() {
-    if (_list == null) return;
-    _list.remove(this);
+    _list?.remove(this as T);
   }
 }
 
 class _LinkedListIterator<T extends LinkedListEntry<T>> implements Iterator<T> {
   /// The current element of the iterator.
-  // This field is writeable, but should only read by users of this class.
-  T current;
+  T? _current;
+  T get current => _current as T;
 
   /// The list the iterator iterates over.
   ///
@@ -106,23 +107,24 @@
   ///
   /// Set to [null] as soon as [moveNext] was invoked (indicating that the
   /// iterator has to work with [current] from now on.
-  LinkedList<T> _list;
+  LinkedList<T>? _list;
 
-  _LinkedListIterator(this._list) {
-    if (_list.length == 0) _list = null;
+  _LinkedListIterator(LinkedList<T> list) : _list = list {
+    if (list.length == 0) _list = null;
   }
 
   bool moveNext() {
     // current is null if the iterator hasn't started iterating, or if the
     // iteration is finished. In the first case, the [_list] field is not null.
-    if (current == null) {
-      if (_list == null) return false;
-      assert(_list.length > 0);
-      current = _list.first;
+    if (_current == null) {
+      var list = _list;
+      if (list == null) return false;
+      assert(list.length > 0);
+      _current = list.first;
       _list = null;
       return true;
     }
-    current = current._next;
-    return current != null;
+    _current = _current!._next;
+    return _current != null;
   }
 }
diff --git a/sdk_nnbd/lib/internal/list.dart b/sdk_nnbd/lib/internal/list.dart
index be15f36..f1d59ff 100644
--- a/sdk_nnbd/lib/internal/list.dart
+++ b/sdk_nnbd/lib/internal/list.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /**
@@ -39,7 +37,7 @@
   }
 
   /** This operation is not supported by a fixed length list. */
-  bool remove(Object element) {
+  bool remove(Object? element) {
     throw new UnsupportedError("Cannot remove from a fixed-length list");
   }
 
@@ -132,7 +130,7 @@
   }
 
   /** This operation is not supported by an unmodifiable list. */
-  bool remove(Object element) {
+  bool remove(Object? element) {
     throw new UnsupportedError("Cannot remove from an unmodifiable list");
   }
 
@@ -147,12 +145,12 @@
   }
 
   /** This operation is not supported by an unmodifiable list. */
-  void sort([Comparator<E> compare]) {
+  void sort([Comparator<E>? compare]) {
     throw new UnsupportedError("Cannot modify an unmodifiable list");
   }
 
   /** This operation is not supported by an unmodifiable list. */
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     throw new UnsupportedError("Cannot modify an unmodifiable list");
   }
 
@@ -187,7 +185,7 @@
   }
 
   /** This operation is not supported by an unmodifiable list. */
-  void fillRange(int start, int end, [E fillValue]) {
+  void fillRange(int start, int end, [E? fillValue]) {
     throw new UnsupportedError("Cannot modify an unmodifiable list");
   }
 }
@@ -227,7 +225,7 @@
 
   ListMapView(this._values);
 
-  E operator [](Object key) => containsKey(key) ? _values[key] : null;
+  E? operator [](Object? key) => containsKey(key) ? _values[key as int] : null;
   int get length => _values.length;
 
   Iterable<E> get values => new SubListIterable<E>(_values, 0, null);
@@ -235,8 +233,8 @@
 
   bool get isEmpty => _values.isEmpty;
   bool get isNotEmpty => _values.isNotEmpty;
-  bool containsValue(Object value) => _values.contains(value);
-  bool containsKey(Object key) => key is int && key >= 0 && key < length;
+  bool containsValue(Object? value) => _values.contains(value);
+  bool containsKey(Object? key) => key is int && key >= 0 && key < length;
 
   void forEach(void f(int key, E value)) {
     int length = _values.length;
diff --git a/sdk_nnbd/lib/internal/patch.dart b/sdk_nnbd/lib/internal/patch.dart
index 1d05fda..3fc9733 100644
--- a/sdk_nnbd/lib/internal/patch.dart
+++ b/sdk_nnbd/lib/internal/patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of "dart:_internal";
 
 class _Patch {
diff --git a/sdk_nnbd/lib/internal/print.dart b/sdk_nnbd/lib/internal/print.dart
index ce5bb2a..2028503 100644
--- a/sdk_nnbd/lib/internal/print.dart
+++ b/sdk_nnbd/lib/internal/print.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /**
@@ -14,6 +12,6 @@
  *
  * This decouples the core library from the async library.
  */
-void Function(String) printToZone = null;
+void Function(String)? printToZone = null;
 
 external void printToConsole(String line);
diff --git a/sdk_nnbd/lib/internal/sort.dart b/sdk_nnbd/lib/internal/sort.dart
index ad79811..d6cca2e 100644
--- a/sdk_nnbd/lib/internal/sort.dart
+++ b/sdk_nnbd/lib/internal/sort.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /**
diff --git a/sdk_nnbd/lib/internal/symbol.dart b/sdk_nnbd/lib/internal/symbol.dart
index d6f05d7..bf48493 100644
--- a/sdk_nnbd/lib/internal/symbol.dart
+++ b/sdk_nnbd/lib/internal/symbol.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._internal;
 
 /**
@@ -111,7 +109,7 @@
   // This is called by dart2js.
   Symbol.validated(String name) : this._name = validatePublicSymbol(name);
 
-  bool operator ==(other) => other is Symbol && _name == other._name;
+  bool operator ==(Object other) => other is Symbol && _name == other._name;
 
   external int get hashCode;
 
diff --git a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
index 558bdaa..a01a537 100644
--- a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
@@ -15,6 +15,8 @@
 
 import 'dart:_foreign_helper' show JS;
 import 'dart:collection' show HashMap;
+import 'dart:async' show Completer;
+import 'dart:_js_helper' show convertDartClosureToJS;
 
 /// WARNING: performance of this method is much worse than other util
 /// methods in this library. Only use this method as a last resort.
@@ -128,3 +130,23 @@
   //         []..addAll(arguments.map(_convertToJS)));
   //     return _wrapToDart(jsObj);
 }
+
+/// Converts a JavaScript Promise to a Dart [Future].
+///
+/// ```dart
+/// @JS()
+/// external Promise<num> get threePromise; // Resolves to 3
+///
+/// final Future<num> threeFuture = promiseToFuture(threePromise);
+///
+/// final three = await threeFuture; // == 3
+/// ```
+Future<T> promiseToFuture<T>(jsPromise) {
+  final completer = Completer<T>();
+
+  final success = convertDartClosureToJS((r) => completer.complete(r), 1);
+  final error = convertDartClosureToJS((e) => completer.completeError(e), 1);
+
+  JS('', '#.then(#, #)', jsPromise, success, error);
+  return completer.future;
+}
diff --git a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
index bdf30e3..f81c43a 100644
--- a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * Scalable Vector Graphics:
  * Two-dimensional vector graphics with support for events and animation.
diff --git a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
index 95a7805..57f93f6 100644
--- a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * High-fidelity audio programming in the browser.
  *
diff --git a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
index b7cf4b8..77e0a9f 100644
--- a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * 3D programming in the browser.
  *
diff --git a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
index d7a857a..106ae4d 100644
--- a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -1,5 +1,4 @@
 // @dart = 2.5
-
 /**
  * An API for storing data in the browser that can be queried with SQL.
  *
diff --git a/tests/compiler/dart2js/inference/data/general.dart b/tests/compiler/dart2js/inference/data/general.dart
index 678911c..beb067d 100644
--- a/tests/compiler/dart2js/inference/data/general.dart
+++ b/tests/compiler/dart2js/inference/data/general.dart
@@ -675,8 +675,7 @@
   A.generative();
 
   /*member: A.==:[exact=JSBool]*/
-  operator ==(/*Union([exact=JSString], [exact=JSUInt31])*/ other) =>
-      42 as dynamic;
+  operator ==(/*[null|subclass=Object]*/ other) => 42 as dynamic;
 
   /*member: A.myField:[exact=JSUInt31]*/
   get myField => 42;
diff --git a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string1_test.dart b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string1_test.dart
index 2e5a44f..40b9f69 100644
--- a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string1_test.dart
+++ b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string1_test.dart
@@ -5,6 +5,7 @@
 // dart2jsOptions=--strong --omit-implicit-checks --lax-runtime-type-to-string
 
 import 'package:expect/expect.dart';
+import 'dart:_foreign_helper' show JS_GET_FLAG;
 
 class Class<T> {
   Class();
@@ -17,7 +18,11 @@
   var toString = '${local1.runtimeType}';
   if ('$Object' == 'Object') {
     // `true` if non-minified.
-    Expect.equals("main_local1", toString);
+    if (JS_GET_FLAG('USE_NEW_RTI')) {
+      Expect.equals("Closure", toString);
+    } else {
+      Expect.equals("main_local1", toString);
+    }
   }
   print(toString);
   local2(0);
diff --git a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string2_test.dart b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string2_test.dart
index dddd5e2..6425113 100644
--- a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string2_test.dart
+++ b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string2_test.dart
@@ -5,6 +5,7 @@
 // dart2jsOptions=--strong --omit-implicit-checks --lax-runtime-type-to-string
 
 import 'package:expect/expect.dart';
+import 'dart:_foreign_helper' show JS_GET_FLAG;
 
 class Class<T> {
   Class();
@@ -17,7 +18,11 @@
   var toString = '${local1.runtimeType}';
   if ('$Object' == 'Object') {
     // `true` if non-minified.
-    Expect.equals("main_local1", toString);
+    if (JS_GET_FLAG('USE_NEW_RTI')) {
+      Expect.equals("Closure", toString);
+    } else {
+      Expect.equals("main_local1", toString);
+    }
   }
   print(toString);
   local2(0);
diff --git a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string7_test.dart b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string7_test.dart
new file mode 100644
index 0000000..6d77543
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string7_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--omit-implicit-checks --lax-runtime-type-to-string
+
+import 'package:expect/expect.dart';
+import 'dart:_foreign_helper' show JS_GET_FLAG;
+
+class Class<T> {
+  Class();
+}
+
+@pragma('dart2js:noInline')
+test<Q>() {
+  Q local1(Q) {}
+  local2(int i) => i;
+
+  var toString = '${local1.runtimeType}';
+  if ('$Object' == 'Object') {
+    // `true` if non-minified.
+    if (JS_GET_FLAG('USE_NEW_RTI')) {
+      Expect.equals("Closure", toString);
+    } else {
+      Expect.equals("test_local1", toString);
+    }
+  }
+  print(toString);
+  local2(0);
+  new Class();
+}
+
+main() {
+  test<int>();
+  test<String>();
+}
diff --git a/tests/compiler/dartdevc_native/assertion_failure_message_test.dart b/tests/compiler/dartdevc_native/assertion_failure_message_test.dart
new file mode 100644
index 0000000..4a7fe7b
--- /dev/null
+++ b/tests/compiler/dartdevc_native/assertion_failure_message_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "utils.dart";
+
+void main() {
+  try {
+    assert(false, "failure message");
+  } on AssertionError catch (error) {
+    var message = error.toString();
+    expectStringContains('Assertion failed:', message);
+    expectStringContains('assertion_failure_message_test.dart:9:12', message);
+    expectStringContains('false', message);
+    expectStringContains('failure message', message);
+  }
+
+  // 失 All offsets and source code extractions should still be correct after
+  // non-UTF8 characters. See: https://github.com/dart-lang/sdk/issues/39271
+  try {
+    assert(false, "after a non-UTF8 character");
+  } on AssertionError catch (error) {
+    var message = error.toString();
+    expectStringContains('Assertion failed:', message);
+    expectStringContains('assertion_failure_message_test.dart:21:12', message);
+    expectStringContains('false', message);
+    expectStringContains('after a non-UTF8 character', message);
+  }
+}
diff --git a/tests/compiler/dartdevc_native/no_such_method_errors_test.dart b/tests/compiler/dartdevc_native/no_such_method_errors_test.dart
index 1298c38..1edcf7e 100644
--- a/tests/compiler/dartdevc_native/no_such_method_errors_test.dart
+++ b/tests/compiler/dartdevc_native/no_such_method_errors_test.dart
@@ -2,14 +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:expect/expect.dart";
-
-_expectInErrorMessage(String expected, String actual) {
-  Expect.isTrue(
-      actual.contains(expected),
-      'Error message should contain "$expected", '
-      'but was ${actual.toString()}.');
-}
+import "utils.dart";
 
 class A {
   int x = 42;
@@ -33,8 +26,8 @@
     instanceOfA();
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'call'", message);
-    _expectInErrorMessage("Receiver: Instance of 'A'", message);
+    expectStringContains("NoSuchMethodError: 'call'", message);
+    expectStringContains("Receiver: Instance of 'A'", message);
   }
 
   dynamic tearOff = instanceOfA.arity1;
@@ -43,8 +36,8 @@
     tearOff(1, 2);
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'bound arity1'", message);
-    _expectInErrorMessage("too many arguments", message);
+    expectStringContains("NoSuchMethodError: 'bound arity1'", message);
+    expectStringContains("too many arguments", message);
   }
 
   // Dynamic call of a class method with too few arguments.
@@ -52,8 +45,8 @@
     tearOff();
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'bound arity1'", message);
-    _expectInErrorMessage("too few arguments", message);
+    expectStringContains("NoSuchMethodError: 'bound arity1'", message);
+    expectStringContains("too few arguments", message);
   }
 
   // Dynamic call of a top level funciton with too many arguments.
@@ -61,8 +54,8 @@
     dynamicFunction(1, 2);
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'arity1'", message);
-    _expectInErrorMessage("too many arguments", message);
+    expectStringContains("NoSuchMethodError: 'arity1'", message);
+    expectStringContains("too many arguments", message);
   }
 
   // Dynamic call of a top level funciton with too few arguments.
@@ -70,8 +63,8 @@
     dynamicFunction();
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'arity1'", message);
-    _expectInErrorMessage("too few arguments", message);
+    expectStringContains("NoSuchMethodError: 'arity1'", message);
+    expectStringContains("too few arguments", message);
   }
 
   // Function.apply() with too many arguments.
@@ -79,8 +72,8 @@
     Function.apply(dynamicFunction, [1, 2]);
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'arity1'", message);
-    _expectInErrorMessage("too many arguments", message);
+    expectStringContains("NoSuchMethodError: 'arity1'", message);
+    expectStringContains("too many arguments", message);
   }
 
   // Function.apply() with too few arguments.
@@ -88,7 +81,7 @@
     Function.apply(dynamicFunction, []);
   } on NoSuchMethodError catch (error) {
     var message = error.toString();
-    _expectInErrorMessage("NoSuchMethodError: 'arity1'", message);
-    _expectInErrorMessage("too few arguments", message);
+    expectStringContains("NoSuchMethodError: 'arity1'", message);
+    expectStringContains("too few arguments", message);
   }
 }
diff --git a/tests/compiler/dartdevc_native/utils.dart b/tests/compiler/dartdevc_native/utils.dart
new file mode 100644
index 0000000..79440f7
--- /dev/null
+++ b/tests/compiler/dartdevc_native/utils.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+/// Expects that [expected] appears as a substring in [actual].
+expectStringContains(String expected, String actual) {
+  Expect.isTrue(actual.contains(expected),
+      'Failure: "$expected" should appear in: "$actual".');
+}
diff --git a/tests/language_2/extension_methods/helpers/also_on_object.dart b/tests/language_2/extension_methods/helpers/also_on_object.dart
new file mode 100644
index 0000000..afe30e34
--- /dev/null
+++ b/tests/language_2/extension_methods/helpers/also_on_object.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// An extension conflicting with the one from "on_object.dart";
+extension AlsoOnObject on Object {
+  String get onObject => "also object";
+}
diff --git a/tests/language_2/extension_methods/helpers/class_no_shadow.dart b/tests/language_2/extension_methods/helpers/class_no_shadow.dart
index cba1e87..31e8195 100644
--- a/tests/language_2/extension_methods/helpers/class_no_shadow.dart
+++ b/tests/language_2/extension_methods/helpers/class_no_shadow.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 
 const String instanceValue = "1";
diff --git a/tests/language_2/extension_methods/helpers/class_shadow.dart b/tests/language_2/extension_methods/helpers/class_shadow.dart
index 73925be..2e603d1a 100644
--- a/tests/language_2/extension_methods/helpers/class_shadow.dart
+++ b/tests/language_2/extension_methods/helpers/class_shadow.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 
 import "class_no_shadow.dart";
diff --git a/tests/language_2/extension_methods/helpers/extension_all.dart b/tests/language_2/extension_methods/helpers/extension_all.dart
index 518948d..80656a7 100644
--- a/tests/language_2/extension_methods/helpers/extension_all.dart
+++ b/tests/language_2/extension_methods/helpers/extension_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 import "class_no_shadow.dart";
 
diff --git a/tests/language_2/extension_methods/helpers/extension_global_instance.dart b/tests/language_2/extension_methods/helpers/extension_global_instance.dart
index fd33bcb..1fbbe7b 100644
--- a/tests/language_2/extension_methods/helpers/extension_global_instance.dart
+++ b/tests/language_2/extension_methods/helpers/extension_global_instance.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 import "class_no_shadow.dart";
 
diff --git a/tests/language_2/extension_methods/helpers/extension_only.dart b/tests/language_2/extension_methods/helpers/extension_only.dart
index da7d1c4..d625af7 100644
--- a/tests/language_2/extension_methods/helpers/extension_only.dart
+++ b/tests/language_2/extension_methods/helpers/extension_only.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 import "class_no_shadow.dart";
 
diff --git a/tests/language_2/extension_methods/helpers/global_scope.dart b/tests/language_2/extension_methods/helpers/global_scope.dart
index 2ba1533..ae6f4fe 100644
--- a/tests/language_2/extension_methods/helpers/global_scope.dart
+++ b/tests/language_2/extension_methods/helpers/global_scope.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=extension-methods
-
 import "package:expect/expect.dart";
 
 const int globalValue = 0;
diff --git a/tests/language_2/extension_methods/helpers/on_int.dart b/tests/language_2/extension_methods/helpers/on_int.dart
new file mode 100644
index 0000000..a835f16
--- /dev/null
+++ b/tests/language_2/extension_methods/helpers/on_int.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension OnInt on int {
+  String get onObject => "int";
+  String get onInt => "int";
+}
diff --git a/tests/language_2/extension_methods/helpers/on_object.dart b/tests/language_2/extension_methods/helpers/on_object.dart
new file mode 100644
index 0000000..dfca4d6
--- /dev/null
+++ b/tests/language_2/extension_methods/helpers/on_object.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension OnObject on Object {
+  String get onObject => "object";
+}
diff --git a/tests/language_2/extension_methods/static_extension_deferred_double_import_test.dart b/tests/language_2/extension_methods/static_extension_deferred_double_import_test.dart
new file mode 100644
index 0000000..0ef1f33
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_deferred_double_import_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_object.dart" deferred as p1 hide OnObject;
+
+// Allow explicit and implicit access to non-deferred import extensions.
+
+void main() async {
+  Object o = 1;
+  Expect.equals("object", OnObject(o).onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_deferred_import_error_test.dart b/tests/language_2/extension_methods/static_extension_deferred_import_error_test.dart
new file mode 100644
index 0000000..3d0c5ba
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_deferred_import_error_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// It is an error to import a deferred library containing extensions without
+// hiding them.
+import "helpers/on_object.dart" deferred as p1;
+// [error line 9, column 1]
+// [cfe] Extension 'OnObject' cannot be imported through a deferred import.
+//     ^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.DEFERRED_IMPORT_OF_EXTENSION
+
+void main() async {}
diff --git a/tests/language_2/extension_methods/static_extension_deferred_import_resolution_error_test.dart b/tests/language_2/extension_methods/static_extension_deferred_import_resolution_error_test.dart
new file mode 100644
index 0000000..59920e7
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_deferred_import_resolution_error_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" deferred as p1 hide OnObject;
+
+void main() {
+  Object o = 1;
+  OnObject(o).onObject;
+//^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.UNDEFINED_FUNCTION
+// [cfe] Method not found: 'OnObject'.
+  o.onObject;
+  //^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'onObject' isn't defined for the class 'Object'.
+}
diff --git a/tests/language_2/extension_methods/static_extension_deferred_import_test.dart b/tests/language_2/extension_methods/static_extension_deferred_import_test.dart
new file mode 100644
index 0000000..829a242
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_deferred_import_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" deferred as p1 hide OnObject;
+
+void main() {}
diff --git a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
index f4cd928..6ca87af 100644
--- a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
+++ b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
@@ -11,13 +11,13 @@
 class C0 {
   int get m1 => 0;
   void set m2(int x) {}
-  int operator[](int index) => 0;
+  int operator [](int index) => 0;
 }
 
 extension E0 on C0 {
   void set m1(int x) {}
   int get m2 => 0;
-  void operator[]=(int index, int value) {}
+  void operator []=(int index, int value) {}
 }
 
 void test0() {
@@ -61,37 +61,31 @@
 
   c0[0];
   c0[0] = 0;
-  //^
+  //^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C0'.
-  // ^^^^^^
-  // [analyzer] unspecified
   E0(c0)[0];
-  // ^^^^^^
-  // [analyzer] unspecified
-  //    ^
+  //    ^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_OPERATOR
   // [cfe] Getter not found: '[]'.
   E0(c0)[0] = 0;
 
   c0[0] += 0;
-  //^
+  //^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C0'.
-  // ^^^^^^
-  // [analyzer] unspecified
   c0[0]++;
-  //^
+  //^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C0'.
-  // ^^^^^^
-  // [analyzer] unspecified
 
   E0(c0)[0] += 0;
-  // ^^^^^^
-  // [analyzer] unspecified
-  //    ^
+  //    ^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_OPERATOR
   // [cfe] The method '[]' isn't defined for the class 'dynamic'.
   E0(c0)[0]++;
-  // ^^^^^^
-  // [analyzer] unspecified
-  //    ^
+  //    ^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_OPERATOR
   // [cfe] The method '[]' isn't defined for the class 'dynamic'.
 }
 
@@ -102,13 +96,13 @@
 extension E1A<T> on C1<T> {
   int get m1 => 0;
   void set m2(int x) {}
-  int operator[](int index) => 0;
+  int operator [](int index) => 0;
 }
 
 extension E1B on C1<Object> {
   void set m1(int x) {}
   int get m2 => 0;
-  void operator[]=(int index, int value) {}
+  void operator []=(int index, int value) {}
 }
 
 void test1() {
@@ -128,22 +122,19 @@
   c1a.m2 = 0;
 
   c1a[0] = 0;
-  // ^
+  // ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C1<int>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1a[0] += 0;
-  // ^
+  // ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C1<int>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1a[0]++;
-  // ^
+  // ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
   // [cfe] The method '[]=' isn't defined for the class 'C1<int>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1a[0];
 
@@ -179,32 +170,32 @@
   // [cfe] The getter 'm2' isn't defined for the class 'C1<Object>'.
 
   c1b[0];
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // ^
   // [cfe] The method '[]' isn't defined for the class 'C1<Object>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1b[0] = 0;
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // ^
   // [cfe] The method '[]=' isn't defined for the class 'C1<Object>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1b[0] += 0;
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // ^
   // [cfe] The method '[]' isn't defined for the class 'C1<Object>'.
   // ^
   // [cfe] The method '[]=' isn't defined for the class 'C1<Object>'.
-  //  ^^
-  // [analyzer] unspecified
 
   c1b[0]++;
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
   // ^
   // [cfe] The method '[]' isn't defined for the class 'C1<Object>'.
   // ^
   // [cfe] The method '[]=' isn't defined for the class 'C1<Object>'.
-  //  ^^
-  // [analyzer] unspecified
 }
 
 // Getter on the extension itself.
@@ -212,15 +203,14 @@
   int get m1 => 0;
   void set m2(int x) {}
   int get mc => 0;
-  void operator[]=(int index, int value) {}
+  void operator []=(int index, int value) {}
 }
 
 extension E2 on C2 {
   void set m1(int x) {}
   int get m2 => 0;
   String get me => "";
-  int operator[](int index) => 0;
-
+  int operator [](int index) => 0;
 
   void test2() {
     // Using `this.member` means using the `on` type.
@@ -239,22 +229,19 @@
 
     this[0] = 0;
     this[0];
-    //  ^
+    //  ^^^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
     // [cfe] The method '[]' isn't defined for the class 'C2'.
-    //   ^^
-    // [analyzer] unspecified
 
     this[0] += 0;
-    //  ^
+    //  ^^^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
     // [cfe] The method '[]' isn't defined for the class 'C2'.
-    //   ^^
-    // [analyzer] unspecified
 
-    this[0] ++;
-    //  ^
+    this[0]++;
+    //  ^^^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
     // [cfe] The method '[]' isn't defined for the class 'C2'.
-    //   ^^
-    // [analyzer] unspecified
 
     // Check that `this.mc` refers to `C2.mc`.
     this.mc.toRadixString(16);
diff --git a/tests/language_2/extension_methods/static_extension_import_hide_error_test.dart b/tests/language_2/extension_methods/static_extension_import_hide_error_test.dart
new file mode 100644
index 0000000..9a93aa0
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_hide_error_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_int.dart" hide OnInt;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  i.onInt;
+  //^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'onInt' isn't defined for the class 'int'.
+  i.onObject;
+  o.onObject;
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_hide_test.dart b/tests/language_2/extension_methods/static_extension_import_hide_test.dart
new file mode 100644
index 0000000..33efb80
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_hide_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_int.dart" hide OnInt;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("object", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_prefixed_hide_error_test.dart b/tests/language_2/extension_methods/static_extension_import_prefixed_hide_error_test.dart
new file mode 100644
index 0000000..3c485e8
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_prefixed_hide_error_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_int.dart" as p1 hide OnInt;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  i.onInt;
+  //^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'onInt' isn't defined for the class 'int'.
+  i.onObject;
+  o.onObject;
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_prefixed_hide_test.dart b/tests/language_2/extension_methods/static_extension_import_prefixed_hide_test.dart
new file mode 100644
index 0000000..eb24f4d
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_prefixed_hide_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_int.dart" as p1 hide OnInt;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("object", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_prefixed_show_test.dart b/tests/language_2/extension_methods/static_extension_import_prefixed_show_test.dart
new file mode 100644
index 0000000..caae31c
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_prefixed_show_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" as p1 show OnObject;
+import "helpers/on_int.dart";
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_prefixed_test.dart b/tests/language_2/extension_methods/static_extension_import_prefixed_test.dart
new file mode 100644
index 0000000..bc64023
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_prefixed_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" as p1;
+import "helpers/on_int.dart";
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_test.dart b/tests/language_2/extension_methods/static_extension_import_test.dart
new file mode 100644
index 0000000..2585595
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_int.dart";
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_import_unprefixed_show_test.dart b/tests/language_2/extension_methods/static_extension_import_unprefixed_show_test.dart
new file mode 100644
index 0000000..5a45148
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_import_unprefixed_show_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" show OnObject;
+import "helpers/on_int.dart";
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_prefix_double_import_test.dart b/tests/language_2/extension_methods/static_extension_prefix_double_import_test.dart
new file mode 100644
index 0000000..3df4552
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_prefix_double_import_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/on_object.dart" as p2;
+
+void main() {
+  Object o = 1;
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_prefix_import_conflict_test.dart b/tests/language_2/extension_methods/static_extension_prefix_import_conflict_test.dart
new file mode 100644
index 0000000..666fbcf7
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_prefix_import_conflict_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart";
+import "helpers/also_on_object.dart" as p2;
+
+void main() {
+  Object o = 1;
+  o.onObject;
+  //^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+  // [cfe] The getter 'onObject' isn't defined for the class 'Object'.
+}
diff --git a/tests/language_2/extension_methods/static_extension_prefix_import_show_test.dart b/tests/language_2/extension_methods/static_extension_prefix_import_show_test.dart
new file mode 100644
index 0000000..8f5cf73
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_prefix_import_show_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" as p1 show OnObject;
+import "helpers/on_int.dart" as p2 show OnInt;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/extension_methods/static_extension_prefix_import_test.dart b/tests/language_2/extension_methods/static_extension_prefix_import_test.dart
new file mode 100644
index 0000000..eba2e94
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_prefix_import_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "helpers/on_object.dart" as p1;
+import "helpers/on_int.dart" as p2;
+
+void main() {
+  int i = 0;
+  Object o = i;
+  Expect.equals("int", i.onInt);
+  Expect.equals("int", i.onObject);
+  Expect.equals("object", o.onObject);
+}
diff --git a/tests/language_2/nnbd/static_errors/use_nnbd_sdk_test.dart b/tests/language_2/nnbd/static_errors/use_nnbd_sdk_test.dart
new file mode 100644
index 0000000..e43cb63
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/use_nnbd_sdk_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import "package:expect/expect.dart";
+
+// SharedOptions=--enable-experiment=non-nullable
+void main() {
+}
+
+/// These tests will all pass only if run with the NNBD migrated SDK.
+/// In not migrated SDK all types are unprefixed, so look non-nullable.
+void f(List<int> list, Map<int, String> map, int a, int? b) {
+  // List: E operator [](int index);
+  list[a]; //# 00: ok
+  list[b]; //# 01: compile-time error
+
+  // Map: V? operator [](Object? key);
+  map[a]; //# 02: ok
+  map[b]; //# 03: ok
+
+  // Map: void operator []=(K key, V value);
+  map[a].length; //# 04: compile-time error
+  map[a]?.length; //# 05: ok
+
+  map[b] = ''; //# 06: compile-time error
+  map[a] = b; //# 07: compile-time error
+}
diff --git a/tests/language_2/nnbd/syntax/cascade_nullcheck_test.dart b/tests/language_2/nnbd/syntax/cascade_nullcheck_test.dart
new file mode 100644
index 0000000..7391fc0
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/cascade_nullcheck_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+import "package:expect/expect.dart";
+
+class C {
+  int? y;
+  D? f() => new D();
+  C? h() => this;
+}
+
+class D {
+  D g() => this;
+  bool? operator [](String s) => true;
+}
+
+void test(C x) {
+  x..f()!.g()['Hi!']!..h()!.y = 2;
+}
+
+main() {
+  test(new C());
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_final_field_test.dart b/tests/language_2/nnbd/syntax/late_modifier_final_field_test.dart
new file mode 100644
index 0000000..91d1865
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_final_field_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+  ++initCalls;
+  return 123;
+}
+
+class Base {
+  late final int fieldWithInit;
+}
+
+// A inherits from Base to bypass the compile time error caused by assigning to
+// a late final field that has an initializer. This allows us to test the
+// runtime exception.
+class A extends Base {
+  late final int fieldWithInit = init();
+}
+
+class B {
+  late final int fieldWithNoInit;
+}
+
+main() {
+  Base a = A();
+  Expect.equals(0, initCalls);
+  Expect.equals(123, a.fieldWithInit);
+  Expect.equals(1, initCalls);
+  Expect.equals(123, a.fieldWithInit);
+  Expect.equals(1, initCalls);
+  Expect.throws(() => {a.fieldWithInit = 456},
+      (error) => error is LateInitializationError);
+  Expect.equals(1, initCalls);
+  Expect.equals(123, a.fieldWithInit);
+  Expect.equals(1, initCalls);
+  initCalls = 0;
+
+  Base a2 = A();
+  Expect.equals(0, initCalls);
+  Expect.throws(() => {a2.fieldWithInit = 456},
+      (error) => error is LateInitializationError);
+  Expect.equals(0, initCalls);
+  Expect.equals(123, a2.fieldWithInit);
+  Expect.equals(1, initCalls);
+
+  B b = B();
+  Expect.throws(
+      () => b.fieldWithNoInit, (error) => error is LateInitializationError);
+  b.fieldWithNoInit = 123;
+  Expect.equals(123, b.fieldWithNoInit);
+  Expect.throws(() => {b.fieldWithNoInit = 456},
+      (error) => error is LateInitializationError);
+  Expect.equals(123, b.fieldWithNoInit);
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_non_final_field_test.dart b/tests/language_2/nnbd/syntax/late_modifier_non_final_field_test.dart
new file mode 100644
index 0000000..804e519
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_non_final_field_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+  ++initCalls;
+  return 123;
+}
+
+class A {
+  late int? fieldWithInit = init();
+  late int fieldWithTrivialInit = 123;
+  late int? fieldWithNullInit = null;
+  late int fieldWithNoInit;
+}
+
+main() {
+  // Late, non-final, with init.
+  var a = A();
+  Expect.equals(0, initCalls);
+  Expect.equals(123, a.fieldWithInit);
+  Expect.equals(123, a.fieldWithTrivialInit);
+  Expect.equals(null, a.fieldWithNullInit);
+  Expect.throws(
+      () => a.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.equals(1, initCalls);
+  Expect.equals(123, a.fieldWithInit);
+  Expect.equals(123, a.fieldWithTrivialInit);
+  Expect.equals(null, a.fieldWithNullInit);
+  Expect.throws(
+      () => a.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.equals(1, initCalls);
+  a.fieldWithInit = 456;
+  a.fieldWithTrivialInit = 456;
+  a.fieldWithNullInit = 456;
+  a.fieldWithNoInit = 456;
+  Expect.equals(1, initCalls);
+  Expect.equals(456, a.fieldWithInit);
+  Expect.equals(456, a.fieldWithTrivialInit);
+  Expect.equals(456, a.fieldWithNullInit);
+  Expect.equals(456, a.fieldWithNoInit);
+  Expect.equals(1, initCalls);
+  initCalls = 0;
+
+  // Late, non-final, with init that's pre-empted by setter.
+  var b = A();
+  Expect.equals(0, initCalls);
+  b.fieldWithInit = 456;
+  Expect.equals(0, initCalls);
+  Expect.equals(456, b.fieldWithInit);
+  Expect.equals(0, initCalls);
+
+  // Late, non-final, with init that's pre-empted by null setter.
+  var c = A();
+  Expect.equals(0, initCalls);
+  c.fieldWithInit = null;
+  Expect.equals(0, initCalls);
+  Expect.equals(null, c.fieldWithInit);
+  Expect.equals(0, initCalls);
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_static_field_test.dart b/tests/language_2/nnbd/syntax/late_modifier_static_field_test.dart
new file mode 100644
index 0000000..ffa8b37
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_static_field_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+  ++initCalls;
+  return 123;
+}
+
+class A {
+  static late int fieldWithInit = init();
+  static late int fieldWithTrivialInit = 123;
+  static late int? fieldWithNullInit = null;
+  static late int fieldWithNoInit;
+}
+
+class B {
+  static late int fieldWithInit = init();
+}
+
+class C {
+  static late int? fieldWithInit = init();
+}
+
+main() {
+  Expect.equals(0, initCalls);
+  Expect.equals(123, A.fieldWithInit);
+  Expect.equals(123, A.fieldWithTrivialInit);
+  Expect.equals(null, A.fieldWithNullInit);
+  Expect.throws(
+      () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.equals(1, initCalls);
+  Expect.equals(123, A.fieldWithInit);
+  Expect.equals(123, A.fieldWithTrivialInit);
+  Expect.equals(null, A.fieldWithNullInit);
+  Expect.throws(
+      () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.equals(1, initCalls);
+  A.fieldWithInit = 456;
+  A.fieldWithTrivialInit = 456;
+  A.fieldWithNullInit = 456;
+  A.fieldWithNoInit = 456;
+  Expect.equals(1, initCalls);
+  Expect.equals(456, A.fieldWithInit);
+  Expect.equals(456, A.fieldWithTrivialInit);
+  Expect.equals(456, A.fieldWithNullInit);
+  Expect.equals(456, A.fieldWithNoInit);
+  Expect.equals(1, initCalls);
+  initCalls = 0;
+
+  // Late, non-final, with init that's pre-empted by setter.
+  Expect.equals(0, initCalls);
+  B.fieldWithInit = 456;
+  Expect.equals(0, initCalls);
+  Expect.equals(456, B.fieldWithInit);
+  Expect.equals(0, initCalls);
+
+  // Late, non-final, with init that's pre-empted by null setter.
+  Expect.equals(0, initCalls);
+  C.fieldWithInit = null;
+  Expect.equals(0, initCalls);
+  Expect.equals(null, C.fieldWithInit);
+  Expect.equals(0, initCalls);
+}
diff --git a/tests/language_2/variance/variance_downwards_inference_test.dart b/tests/language_2/variance/variance_downwards_inference_test.dart
new file mode 100644
index 0000000..7de0e22
--- /dev/null
+++ b/tests/language_2/variance/variance_downwards_inference_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests downwards inference for explicit variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+class A<out T> {
+  final T _x;
+  A(T x):_x = x;
+  T get x => _x;
+  void set x(Object value) {}
+}
+
+class B<in T> {
+  B(List<T> x);
+  void set x(T val) {}
+}
+
+class C<out T, S> {
+  final T _x;
+  C(T x, S y):_x = x;
+  T get x => _x;
+  void set x(Object value) {}
+  void set y(S _value) {}
+}
+
+main() {
+  // int <: T <: Object
+  // Choose int
+  A<Object> a = new A(3)..x+=1;
+
+  // int <: T
+  // num <: T
+  // Choose num
+  B<int> b = new B(<num>[])..x=2.2;
+
+  // int <: T <: Object
+  // Choose int
+  // int <: S <: Object
+  // Choose Object
+  C<Object, Object> c = new C(3, 3)..x+=1..y="hello";
+}
diff --git a/tests/language_2/variance/variance_in_inference_error_test.dart b/tests/language_2/variance/variance_in_inference_error_test.dart
new file mode 100644
index 0000000..35b994d
--- /dev/null
+++ b/tests/language_2/variance/variance_in_inference_error_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference errors for the `in` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferCovContra<T>(Covariant<T> x, Contravariant<T> y) => new Exactly<T>();
+Exactly<T> inferContraContra<T>(Contravariant<T> x, Contravariant<T> y) => new Exactly<T>();
+
+main() {
+  Exactly<Upper> upper;
+
+  var inferredMiddle = inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
+  upper = inferredMiddle;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Middle>' can't be assigned to a variable of type 'Exactly<Upper>'.
+
+  var inferredLower = inferContraContra(Contravariant<Upper>(), Contravariant<Lower>());
+  upper = inferredLower;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Lower>' can't be assigned to a variable of type 'Exactly<Upper>'.
+
+  // int <: T <: String is not a valid constraint.
+  inferCovContra(Covariant<int>(), Contravariant<String>());
+  //                               ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Contravariant<String>' can't be assigned to the parameter type 'Contravariant<int>'.
+
+  // String <: T <: int is not a valid constraint.
+  inferCovContra(Covariant<String>(), Contravariant<int>());
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Contravariant<int>' can't be assigned to the parameter type 'Contravariant<String>'.
+
+  // Middle <: T <: Lower is not a valid constraint
+  inferCovContra(Covariant<Middle>(), Contravariant<Lower>());
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Middle>'.
+
+  // Upper <: T <: Lower is not a valid constraint
+  inferCovContra(Covariant<Upper>(), Contravariant<Lower>());
+  //                                 ^
+  // [analyzer] unspecified
+  // [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Upper>'.
+
+  // Upper <: T <: Middle is not a valid constraint
+  inferCovContra(Covariant<Upper>(), Contravariant<Middle>());
+  //                                 ^
+  // [analyzer] unspecified
+  // [cfe] The constructor returns type 'Contravariant<Middle>' that isn't of expected type 'Contravariant<Upper>'.
+}
diff --git a/tests/language_2/variance/variance_in_inference_test.dart b/tests/language_2/variance/variance_in_inference_test.dart
new file mode 100644
index 0000000..742911d
--- /dev/null
+++ b/tests/language_2/variance/variance_in_inference_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference for the `in` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferCovContra<T>(Covariant<T> x, Contravariant<T> y) => new Exactly<T>();
+Exactly<T> inferContraContra<T>(Contravariant<T> x, Contravariant<T> y) => new Exactly<T>();
+
+main() {
+  Exactly<Middle> middle;
+  Exactly<Lower> lower;
+
+  // Lower <: T
+  // T <: Lower
+  // Choose Lower for Lower <: T <: Lower
+  var inferredLower = inferCovContra(Covariant<Lower>(), Contravariant<Lower>());
+  lower = inferredLower;
+
+  // Lower <: T
+  // T <: Middle
+  // Choose Lower for Lower <: T <: Middle
+  var inferredLower2 = inferCovContra(Covariant<Lower>(), Contravariant<Middle>());
+  lower = inferredLower2;
+
+  // Lower <: T
+  // T <: Upper
+  // Choose Lower for Lower <: T <: Upper
+  var inferredLower3 = inferCovContra(Covariant<Lower>(), Contravariant<Upper>());
+  lower = inferredLower3;
+
+  // T <: Upper
+  // T <: Middle
+  // Choose Middle since it is the greatest lower bound of Upper and Middle.
+  var inferredMiddle = inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
+  middle = inferredMiddle;
+
+  // T <: Upper
+  // T <: Lower
+  // Choose Lower since it is the greatest lower bound of Upper and Lower.
+  var inferredLower4 = inferContraContra(Contravariant<Lower>(), Contravariant<Upper>());
+  lower = inferredLower4;
+
+  // T <: Middle
+  // T <: Lower
+  // Choose Lower since it is the greatest lower bound of Middle and Lower.
+  var inferredLower5 = inferContraContra(Contravariant<Lower>(), Contravariant<Middle>());
+  lower = inferredLower5;
+}
diff --git a/tests/language_2/variance/variance_in_method_error_test.dart b/tests/language_2/variance/variance_in_method_error_test.dart
index af5ef41..98c8033 100644
--- a/tests/language_2/variance/variance_in_method_error_test.dart
+++ b/tests/language_2/variance/variance_in_method_error_test.dart
@@ -294,3 +294,15 @@
     return null;
   }
 }
+
+class C<T> {
+  void method(T x) {}
+}
+
+class D<in T> extends C<void Function(T)> {
+  @override
+  void method(void Function(T) x) {}
+  //                           ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+}
diff --git a/tests/language_2/variance/variance_in_method_test.dart b/tests/language_2/variance/variance_in_method_test.dart
index f209a16..c06264b 100644
--- a/tests/language_2/variance/variance_in_method_test.dart
+++ b/tests/language_2/variance/variance_in_method_test.dart
@@ -110,6 +110,21 @@
   }
 }
 
+class D<T> {
+  T x;
+  T method() => null;
+  void method2(T x) {}
+  void method3(covariant T x) {}
+}
+
+class E<in T> extends D<void Function(T)> {
+  @override
+  void Function(T) method() => (T x) {};
+
+  @override
+  void method3(covariant void Function(T) x) {}
+}
+
 void testClass() {
   A<int> a = new A();
 
@@ -208,8 +223,24 @@
   Expect.type<A<int>>(c.method2());
 }
 
+void testOverrideLegacyMethods() {
+  E<int> e = new E();
+  Expect.isTrue(e.method() is Function);
+  e.method2(contraFunction);
+  e.method3(contraFunction);
+  e.x = contraFunction;
+
+  D<Object> d = e;
+  Expect.throws(() => d.x = "test");
+
+  e = new E<Object>();
+  Expect.throws(() => e.method2(contraFunction));
+  Expect.throws(() => e.method3(contraFunction));
+}
+
 main() {
   testClass();
   testMixin();
   testClassInMethods();
+  testOverrideLegacyMethods();
 }
diff --git a/tests/language_2/variance/variance_in_subtyping_error_test.dart b/tests/language_2/variance/variance_in_subtyping_error_test.dart
index bf51bff..d5697c7 100644
--- a/tests/language_2/variance/variance_in_subtyping_error_test.dart
+++ b/tests/language_2/variance/variance_in_subtyping_error_test.dart
@@ -23,16 +23,17 @@
 class B extends A {
   @override
   Contravariant<Lower> method1() {
-  //                   ^
-  // [analyzer] unspecified
+  //                   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   // [cfe] The return type of the method 'B.method1' is 'Contravariant<Lower>', which does not match the return type, 'Contravariant<Middle>', of the overridden method, 'A.method1'.
     return new Contravariant<Lower>();
   }
 
   @override
   void method2(Contravariant<Upper> x) {}
+  //   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   //                                ^
-  // [analyzer] unspecified
   // [cfe] The parameter 'x' of the method 'B.method2' has type 'Contravariant<Upper>', which does not match the corresponding type, 'Contravariant<Middle>', in the overridden method, 'A.method2'.
 }
 
@@ -40,13 +41,15 @@
 
 class D {
   C<Contravariant<Lower>> method1() {
+  //^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   //                             ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C' in the return type.
     return C<Contravariant<Lower>>();
     //     ^
-    // [analyzer] unspecified
     // [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
+    //       ^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   }
 }
 
@@ -54,22 +57,24 @@
 
 main() {
   C<Contravariant<Lower>> c = new C<Contravariant<Lower>>();
+  //^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   //                      ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
   //                              ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
+  //                                ^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
 
   Iterable<Contravariant<Middle>> iterableMiddle = [new Contravariant<Middle>()];
   List<Contravariant<Lower>> listLower = [new Contravariant<Lower>()];
   iterableMiddle = listLower;
-  //               ^
-  // [analyzer] unspecified
+  //               ^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'List<Contravariant<Lower>>' can't be assigned to a variable of type 'Iterable<Contravariant<Middle>>'.
 
   testCall(listLower);
-  //       ^
-  // [analyzer] unspecified
+  //       ^^^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
   // [cfe] The argument type 'List<Contravariant<Lower>>' can't be assigned to the parameter type 'Iterable<Contravariant<Middle>>'.
 }
diff --git a/tests/language_2/variance/variance_inout_inference_error_test.dart b/tests/language_2/variance/variance_inout_inference_error_test.dart
new file mode 100644
index 0000000..361ec92
--- /dev/null
+++ b/tests/language_2/variance/variance_inout_inference_error_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference errors for the `inout` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferInvInv<T>(Invariant<T> x, Invariant<T> y) => new Exactly<T>();
+Exactly<T> inferInvCov<T>(Invariant<T> x, Covariant<T> y) => new Exactly<T>();
+Exactly<T> inferInvContra<T>(Invariant<T> x, Contravariant<T> y) => new Exactly<T>();
+
+main() {
+  // Middle <: T <: Middle and int <: T <: int are not valid constraints.
+  inferInvInv(Invariant<Middle>(), Invariant<int>());
+  //          ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Object>'.
+  //                               ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Invariant<int>' can't be assigned to the parameter type 'Invariant<Object>'.
+
+  // Middle <: T <: Middle and Upper <: T <: Upper are not valid constraints.
+  inferInvInv(Invariant<Middle>(), Invariant<Upper>());
+  //          ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
+
+  // Middle <: T <: Middle and Lower <: T <: Lower are not valid constraints.
+  inferInvInv(Invariant<Middle>(), Invariant<Lower>());
+  //                               ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Invariant<Lower>' can't be assigned to the parameter type 'Invariant<Middle>'.
+
+  // Upper <: T
+  // Middle <: T <: Middle
+  // Upper <: T <: Middle is not a valid constraint.
+  inferInvCov(Invariant<Middle>(), Covariant<Upper>());
+  //          ^
+  // [analyzer] unspecified
+  // [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
+
+  // T <: Lower
+  // Middle <: T <: Lower
+  // Middle <: T <: Lower is not a valid constraint
+  inferInvContra(Invariant<Middle>(), Contravariant<Lower>());
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Middle>'.
+}
diff --git a/tests/language_2/variance/variance_inout_inference_test.dart b/tests/language_2/variance/variance_inout_inference_test.dart
new file mode 100644
index 0000000..8a5e3c5
--- /dev/null
+++ b/tests/language_2/variance/variance_inout_inference_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference for the `inout` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferInvInv<T>(Invariant<T> x, Invariant<T> y) => new Exactly<T>();
+Exactly<T> inferInvCov<T>(Invariant<T> x, Covariant<T> y) => new Exactly<T>();
+Exactly<T> inferInvContra<T>(Invariant<T> x, Contravariant<T> y) => new Exactly<T>();
+
+main() {
+  Exactly<Middle> middle;
+
+  // Middle <: T <: Middle
+  // Choose Middle
+  var inferredMiddle = inferInvInv(Invariant<Middle>(), Invariant<Middle>());
+  middle = inferredMiddle;
+
+  // Lower <: T
+  // Middle <: T <: Middle
+  // Choose Middle since this merges to Middle <: T <: Middle
+  var inferredMiddle2 = inferInvCov(Invariant<Middle>(), Covariant<Lower>());
+  middle = inferredMiddle2;
+
+  // Middle <: T
+  // Middle <: T <: Middle
+  // Choose Middle since this merges to Middle <: T <: Middle
+  var inferredMiddle3 = inferInvCov(Invariant<Middle>(), Covariant<Middle>());
+  middle = inferredMiddle3;
+
+  // T <: Upper
+  // Middle <: T <: Middle
+  // Choose Middle since this merges to Middle <: T <: Middle
+  var inferredMiddle4 = inferInvContra(Invariant<Middle>(), Contravariant<Upper>());
+  middle = inferredMiddle4;
+
+  // T <: Middle
+  // Middle <: T <: Middle
+  // Choose Middle since this merges to Middle <: T <: Middle
+  var inferredMiddle5 = inferInvContra(Invariant<Middle>(), Contravariant<Middle>());
+  middle = inferredMiddle5;
+}
diff --git a/tests/language_2/variance/variance_inout_method_test.dart b/tests/language_2/variance/variance_inout_method_test.dart
index f533b71..62b1f2e 100644
--- a/tests/language_2/variance/variance_inout_method_test.dart
+++ b/tests/language_2/variance/variance_inout_method_test.dart
@@ -116,6 +116,39 @@
   }
 }
 
+class D<T> {
+  T method() => null;
+  void method2(T x) {}
+  void method3(covariant T x) {}
+}
+
+class E<inout T> extends D<T> {
+  @override
+  T method() => null;
+
+  @override
+  void method2(T x) {}
+
+  @override
+  void method3(covariant T x) {}
+}
+
+abstract class F<T> {
+  int method(T x);
+}
+
+class G<inout T> {
+  final void Function(T) f;
+  G(this.f);
+  int method(T x) {
+    f(x);
+  }
+}
+
+class H<inout T> extends G<T> implements F<T> {
+  H(void Function(T) f) : super(f);
+}
+
 void testClass() {
   A<int> a = new A();
 
@@ -228,8 +261,23 @@
   Expect.type<A<int>>(c.method3());
 }
 
+void testOverrideLegacyMethods() {
+  E<int> e = new E();
+  Expect.isNull(e.method());
+  e.method2(3);
+  e.method3(3);
+
+  D<Object> d = e;
+  Expect.throws(() => d.method2("test"));
+  Expect.throws(() => d.method3("test"));
+
+  F<Object> f = new H<String>((String s) {});
+  Expect.throws(() => f.method(3));
+}
+
 main() {
   testClass();
   testMixin();
   testClassInMethods();
+  testOverrideLegacyMethods();
 }
diff --git a/tests/language_2/variance/variance_inout_subtyping_error_test.dart b/tests/language_2/variance/variance_inout_subtyping_error_test.dart
index 0ca248a..d06f336 100644
--- a/tests/language_2/variance/variance_inout_subtyping_error_test.dart
+++ b/tests/language_2/variance/variance_inout_subtyping_error_test.dart
@@ -40,16 +40,17 @@
 class C extends A {
   @override
   Invariant<Lower> method1() {
-  //               ^
-  // [analyzer] unspecified
+  //               ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   // [cfe] The return type of the method 'C.method1' is 'Invariant<Lower>', which does not match the return type, 'Invariant<Middle>', of the overridden method, 'A.method1'.
     return new Invariant<Lower>();
   }
 
   @override
   void method2(Invariant<Upper> x) {}
+  //   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   //                            ^
-  // [analyzer] unspecified
   // [cfe] The parameter 'x' of the method 'C.method2' has type 'Invariant<Upper>', which does not match the corresponding type, 'Invariant<Middle>', in the overridden method, 'A.method2'.
 }
 
@@ -69,13 +70,15 @@
   }
 
   D<Invariant<Lower>> method2() {
+  //^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   //                         ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Invariant<Lower>' doesn't conform to the bound 'Invariant<Middle>' of the type variable 'T' on 'D' in the return type.
     return D<Invariant<Lower>>();
     //     ^
-    // [analyzer] unspecified
     // [cfe] Type argument 'Invariant<Lower>' doesn't conform to the bound 'Invariant<Middle>' of the type variable 'T' on 'D'.
+    //       ^^^^^^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   }
 }
 
@@ -92,12 +95,14 @@
   //                                 ^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   D<Invariant<Lower>> dLower = new D<Invariant<Lower>>();
+  //^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
   //                  ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Invariant<Lower>' doesn't conform to the bound 'Invariant<Middle>' of the type variable 'T' on 'D'.
   //                               ^
-  // [analyzer] unspecified
   // [cfe] Type argument 'Invariant<Lower>' doesn't conform to the bound 'Invariant<Middle>' of the type variable 'T' on 'D'.
+  //                                 ^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
 
   Iterable<Invariant<Lower>> iterableLower = [new Invariant<Lower>()];
   List<Invariant<Middle>> listMiddle = [new Invariant<Middle>()];
@@ -109,8 +114,8 @@
   Iterable<Invariant<Middle>> iterableMiddle = [new Invariant<Middle>()];
   List<Invariant<Lower>> listLower = [new Invariant<Lower>()];
   iterableMiddle = listLower;
-  //               ^
-  // [analyzer] unspecified
+  //               ^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'List<Invariant<Lower>>' can't be assigned to a variable of type 'Iterable<Invariant<Middle>>'.
 
   testCall<Lower>(listMiddle);
@@ -119,7 +124,7 @@
   // [cfe] The argument type 'List<Invariant<Middle>>' can't be assigned to the parameter type 'Iterable<Invariant<Lower>>'.
 
   testCall<Middle>(listLower);
-  //               ^
-  // [analyzer] unspecified
+  //               ^^^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
   // [cfe] The argument type 'List<Invariant<Lower>>' can't be assigned to the parameter type 'Iterable<Invariant<Middle>>'.
 }
diff --git a/tests/language_2/variance/variance_out_inference_error_test.dart b/tests/language_2/variance/variance_out_inference_error_test.dart
new file mode 100644
index 0000000..cc2f448
--- /dev/null
+++ b/tests/language_2/variance/variance_out_inference_error_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference errors for the `out` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferCovCov<T>(Covariant<T> x, Covariant<T> y) => new Exactly<T>();
+
+main() {
+  Exactly<Lower> lower;
+
+  var inferredMiddle = inferCovCov(Covariant<Lower>(), Covariant<Middle>());
+  lower = inferredMiddle;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Middle>' can't be assigned to a variable of type 'Exactly<Lower>'.
+
+  var inferredUpper = inferCovCov(Covariant<Lower>(), Covariant<Upper>());
+  lower = inferredUpper;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Upper>' can't be assigned to a variable of type 'Exactly<Lower>'.
+}
diff --git a/tests/language_2/variance/variance_out_inference_test.dart b/tests/language_2/variance/variance_out_inference_test.dart
new file mode 100644
index 0000000..8ba2f49
--- /dev/null
+++ b/tests/language_2/variance/variance_out_inference_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests local inference for the `out` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+Exactly<T> inferCovCov<T>(Covariant<T> x, Covariant<T> y) => new Exactly<T>();
+
+main() {
+  Exactly<Upper> upper;
+
+  // Upper <: T
+  // Upper <: T
+  // Choose Upper
+  var inferredUpper = inferCovCov(Covariant<Upper>(), Covariant<Upper>());
+  upper = inferredUpper;
+
+  // Upper <: T
+  // Middle <: T
+  // Choose Upper since it is the lowest upper bound of Upper and Middle.
+  var inferredUpper2 = inferCovCov(Covariant<Upper>(), Covariant<Middle>());
+  upper = inferredUpper2;
+
+  // Upper <: T
+  // Lower <: T
+  // Choose Upper since it is the lowest upper bound of Upper and Lower.
+  var inferredUpper3 = inferCovCov(Covariant<Upper>(), Covariant<Lower>());
+  upper = inferredUpper3;
+}
diff --git a/tests/language_2/variance/variance_out_method_error_test.dart b/tests/language_2/variance/variance_out_method_error_test.dart
index fc4264b..905763a 100644
--- a/tests/language_2/variance/variance_out_method_error_test.dart
+++ b/tests/language_2/variance/variance_out_method_error_test.dart
@@ -298,3 +298,15 @@
     return null;
   }
 }
+
+class C<T> {
+  void method(T x) {}
+}
+
+class D<out T> extends C<T> {
+  @override
+  void method(T x) {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+}
diff --git a/tests/language_2/variance/variance_out_method_test.dart b/tests/language_2/variance/variance_out_method_test.dart
index 64bde43..7e0da23 100644
--- a/tests/language_2/variance/variance_out_method_test.dart
+++ b/tests/language_2/variance/variance_out_method_test.dart
@@ -104,6 +104,20 @@
   }
 }
 
+class D<T> {
+  T method() => null;
+  void method2(T x) {}
+  void method3(covariant T x) {}
+}
+
+class E<out T> extends D<T> {
+  @override
+  T method() => null;
+
+  @override
+  void method3(covariant T x) {}
+}
+
 void testClass() {
   A<int> a = new A();
 
@@ -200,8 +214,20 @@
   Expect.type<A<int>>(c.method2());
 }
 
+void testOverrideLegacyMethods() {
+  E<int> e = new E();
+  Expect.isNull(e.method());
+  e.method2(3);
+  e.method3(3);
+
+  D<Object> d = e;
+  Expect.throws(() => d.method2("test"));
+  Expect.throws(() => d.method3("test"));
+}
+
 main() {
   testClass();
   testMixin();
   testClassInMethods();
+  testOverrideLegacyMethods();
 }
diff --git a/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart b/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart
index cd6e13b..2c69097 100644
--- a/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart
+++ b/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart
@@ -27,76 +27,76 @@
   var contraLowerActual =
       exactly(condition ? Contravariant<Upper>() : Contravariant<Lower>());
   Exactly<Contravariant<Upper>> contraUpperExpected = contraLowerActual;
-  //                                                  ^
-  // [analyzer] unspecified
+  //                                                  ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Contravariant<Lower>>' can't be assigned to a variable of type 'Exactly<Contravariant<Upper>>'.
 
   var contraMiddleActual =
       exactly(condition ? Contravariant<Upper>() : Contravariant<Middle>());
   contraUpperExpected = contraMiddleActual;
-  //                    ^
-  // [analyzer] unspecified
+  //                    ^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Contravariant<Middle>>' can't be assigned to a variable of type 'Exactly<Contravariant<Upper>>'.
 
   var covMiddleActual =
       exactly(condition ? Covariant<Middle>() : Covariant<Lower>());
   Exactly<Covariant<Lower>> covLowerExpected = covMiddleActual;
-  //                                           ^
-  // [analyzer] unspecified
+  //                                           ^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Covariant<Middle>>' can't be assigned to a variable of type 'Exactly<Covariant<Lower>>'.
 
   var covUpperActual =
       exactly(condition ? Covariant<Upper>() : Covariant<Lower>());
   covLowerExpected = covUpperActual;
-  //                 ^
-  // [analyzer] unspecified
+  //                 ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Covariant<Upper>>' can't be assigned to a variable of type 'Exactly<Covariant<Lower>>'.
 
   var invObjectActual =
       exactly(condition ? Invariant<Upper>() : Invariant<Middle>());
   Exactly<Invariant<Middle>> invMiddleExpected = invObjectActual;
-  //                                             ^
-  // [analyzer] unspecified
+  //                                             ^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Invariant<Middle>>'.
   Exactly<Invariant<Upper>> invUpperExpected = invObjectActual;
-  //                                           ^
-  // [analyzer] unspecified
+  //                                           ^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Invariant<Upper>>'.
 
   var legacyCovMiddleActual =
       exactly(condition ? LegacyCovariant<Middle>() : LegacyCovariant<Lower>());
   Exactly<LegacyCovariant<Lower>> legacyCovLowerExpected =
       legacyCovMiddleActual;
-  //  ^
-  // [analyzer] unspecified
+  //  ^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<LegacyCovariant<Middle>>' can't be assigned to a variable of type 'Exactly<LegacyCovariant<Lower>>'.
 
   var legacyCovUpperActual =
       exactly(condition ? LegacyCovariant<Upper>() : LegacyCovariant<Lower>());
   legacyCovLowerExpected = legacyCovUpperActual;
-  //                       ^
-  // [analyzer] unspecified
+  //                       ^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<LegacyCovariant<Upper>>' can't be assigned to a variable of type 'Exactly<LegacyCovariant<Lower>>'.
 
   var multiActual = exactly(condition
       ? Multi<Middle, Middle, Middle>()
       : Multi<Lower, Middle, Lower>());
   Exactly<Multi<Lower, Middle, Lower>> multiExpected = multiActual;
-  //                                                   ^
-  // [analyzer] unspecified
+  //                                                   ^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Multi<Middle, Middle, Lower>>' can't be assigned to a variable of type 'Exactly<Multi<Lower, Middle, Lower>>'.
 
   var multiActual2 = exactly(
       condition ? Multi<Middle, int, Middle>() : Multi<Lower, Middle, Lower>());
   Exactly<Multi<Middle, Object, Lower>> multiObjectExpected = multiActual2;
-  //                                                          ^
-  // [analyzer] unspecified
+  //                                                          ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Multi<Middle, Object, Lower>>'.
 
   var multiActual3 = exactly(
       condition ? Multi<int, Middle, Middle>() : Multi<Lower, Middle, Lower>());
   Exactly<Object> multiObjectExpected2 = multiActual3;
-  //                                     ^
-  // [analyzer] unspecified
+  //                                     ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   // [cfe] A value of type 'Exactly<Multi<Object, Middle, Lower>>' can't be assigned to a variable of type 'Exactly<Object>'.
 }
diff --git a/tests/language_2/vm/regress_39283_test.dart b/tests/language_2/vm/regress_39283_test.dart
new file mode 100644
index 0000000..0638fb8
--- /dev/null
+++ b/tests/language_2/vm/regress_39283_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {
+  dynamic foo(a) {
+    baz() {
+      Expect.fail('Should not be reachable');
+    }
+
+    return baz;
+  }
+}
+
+main() {
+  Expect.throws(() {
+    dynamic x = A().foo(1);
+    x<List>();
+  }, (e) => e is NoSuchMethodError);
+}
diff --git a/tests/lib_2/html/js_util_test.dart b/tests/lib_2/html/js_util_test.dart
index 78ea380..1a4ebe6 100644
--- a/tests/lib_2/html/js_util_test.dart
+++ b/tests/lib_2/html/js_util_test.dart
@@ -12,7 +12,8 @@
 
 import 'package:js/js.dart';
 import 'package:js/js_util.dart' as js_util;
-import 'package:expect/minitest.dart';
+import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
 
 _injectJs() {
   final script = new ScriptElement();
@@ -55,6 +56,12 @@
     return false;
 }
 
+var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
+var resolvedPromise = new Promise(resolve => resolve('resolved'));
+function getResolvedPromise() {
+  return resolvedPromise;
+}
+
 """;
   document.body.append(script);
 }
@@ -103,6 +110,18 @@
   external set JS$class(v);
 }
 
+@JS()
+abstract class Promise<T> {}
+
+@JS()
+external Promise get resolvedPromise;
+
+@JS()
+external Promise get rejectedPromise;
+
+@JS()
+external Promise getResolvedPromise();
+
 @JS("Object.prototype.hasOwnProperty")
 external get _hasOwnProperty;
 
@@ -340,4 +359,25 @@
       expect(f.a, equals(42));
     });
   });
+
+  group('promiseToFuture', () {
+    test('resolved promise', () async {
+      final String result = await js_util.promiseToFuture(resolvedPromise);
+      expect(result, equals('resolved'));
+    });
+
+    test('rejected promise', () async {
+      try {
+        final String result = await promiseToFuture(rejectedPromise);
+        fail('expected Future to throw an error');
+      } catch (error) {
+        expect(error, equals('rejected'));
+      }
+    });
+
+    test('function that returns a resolved promise', () async {
+      final String result = await promiseToFuture(getResolvedPromise());
+      expect(result, equals('resolved'));
+    });
+  });
 }
diff --git a/tests/standalone_2/io/http_headers_test.dart b/tests/standalone_2/io/http_headers_test.dart
index 3b2f9cb..3a2cbb3 100644
--- a/tests/standalone_2/io/http_headers_test.dart
+++ b/tests/standalone_2/io/http_headers_test.dart
@@ -563,6 +563,21 @@
   Expect.isFalse(headers.chunkedTransferEncoding);
 }
 
+void testFolding() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  headers.add("a", "b");
+  headers.add("a", "c");
+  headers.add("a", "d");
+  // no folding by default
+  Expect.isTrue(headers.toString().contains('b, c, d'));
+  // Header name should be case insensitive
+  headers.noFolding('A');
+  var str = headers.toString();
+  Expect.isTrue(str.contains(': b'));
+  Expect.isTrue(str.contains(': c'));
+  Expect.isTrue(str.contains(': d'));
+}
+
 main() {
   testMultiValue();
   testDate();
@@ -581,4 +596,5 @@
   testInvalidFieldName();
   testInvalidFieldValue();
   testClear();
+  testFolding();
 }
diff --git a/tests/standalone_2/io/shared_socket_test.dart b/tests/standalone_2/io/shared_socket_test.dart
new file mode 100644
index 0000000..939695d
--- /dev/null
+++ b/tests/standalone_2/io/shared_socket_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:http/http.dart' as http;
+
+void main() async {
+  final workers = List<ServerWorker>.generate(4, (i) => ServerWorker(i));
+  workers.forEach((w) => w.start());
+  await Future.delayed(Duration(seconds: 1));
+  // spawn client isolate
+  final clientisolate = await Isolate.spawn(client, 0);
+  // Wait for 20 secs. It used to crash within 10 seconds.
+  await Future.delayed(Duration(seconds: 20));
+
+  workers.forEach((w) {
+    w.respawn = false;
+    w.terminate();
+  });
+  print('kill client isolates');
+  clientisolate.kill();
+}
+
+class ServerWorker {
+  final int workerid;
+  Isolate _isolate;
+  bool respawn = true;
+
+  ServerWorker(this.workerid);
+
+  Future<void> start() async {
+    final onExit = ReceivePort();
+    onExit.listen((_) {
+      onExit.close();
+      // Respawn another isolate
+      if (respawn) start();
+    });
+    _isolate = await Isolate.spawn(_main, workerid,
+        errorsAreFatal: true, onExit: onExit.sendPort);
+    if (workerid == 0) terminate();
+  }
+
+  void terminate() {
+    Future.delayed(Duration(seconds: 1), () {
+      print('terminate ${workerid}');
+      if (_isolate != null) {
+        _isolate.kill();
+        _isolate = null;
+      }
+    });
+  }
+
+  static _main(int workerid) async {
+    bool shared = true;
+    final server = await HttpServer.bind('::1', 1234, shared: shared);
+    server.listen((HttpRequest request) {
+      print('from worker ${workerid}');
+      final response = request.response;
+      response.statusCode = HttpStatus.ok;
+      response.write('server worker ${workerid}');
+      response.close();
+    });
+  }
+}
+
+Future<String> get(String url) async {
+  while (true) {
+    try {
+      await http.get(url);
+      return '';
+    } catch (err) {}
+  }
+}
+
+void client(int i) async {
+  while (true) {
+    final futures = <Future>[];
+    final numAtOnce = 16; // enough to keep the server busy
+    for (int i = 0; i < numAtOnce; ++i) {
+      futures.add(get('http://localhost:1234').then((_) {}));
+    }
+    await Future.wait(futures);
+  }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 97be2aa..200c0df 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 7
 PATCH 0
-PRERELEASE 0
+PRERELEASE 1
 PRERELEASE_PATCH 0
-ABI_VERSION 21
-OLDEST_SUPPORTED_ABI_VERSION 19
+ABI_VERSION 23
+OLDEST_SUPPORTED_ABI_VERSION 23
diff --git a/tools/bots/aot_smoke_tests.dart b/tools/bots/aot_smoke_tests.dart
index 0e912cd..b9a035e 100755
--- a/tools/bots/aot_smoke_tests.dart
+++ b/tools/bots/aot_smoke_tests.dart
@@ -10,9 +10,7 @@
 // run the resulting AOT blob with the AOT runtime.
 
 import 'dart:io';
-import 'dart:convert';
 
-import 'package:args/args.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/tools/copy_dart.py b/tools/copy_dart.py
index 2bfb582..059b85b 100755
--- a/tools/copy_dart.py
+++ b/tools/copy_dart.py
@@ -120,6 +120,9 @@
 
             # Create file containing all imports, and inlining all sources
             with open(outpath, 'w') as f:
+                prefix = os.environ.get('DART_HTML_PREFIX')
+                if prefix:
+                    f.write(prefix + '\n')
                 if library.name:
                     if library.comment:
                         f.write('%s' % (''.join(library.comment)))
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 3e1368e..b255a8e 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -191,15 +191,16 @@
     monitored.FinishMonitoring(dart2js_output_dir, _logger)
 
 
-def GenerateSingleFile(library_path, output_dir, generated_output_dir=None):
+def GenerateSingleFile(library_path, output_dir, generated_output_dir=None, prefix=None):
     library_dir = os.path.dirname(library_path)
     library_filename = os.path.basename(library_path)
     copy_dart_script = os.path.relpath('../../copy_dart.py', library_dir)
     output_dir = os.path.relpath(output_dir, library_dir)
     if not os.path.exists(library_dir):
         os.makedirs(library_dir)
+    prefix_arg = 'export DART_HTML_PREFIX="' + prefix + '";' if prefix else ""
     command = ' '.join([
-        'cd', library_dir, ';', copy_dart_script, output_dir, library_filename
+        prefix_arg, 'cd', library_dir, ';', copy_dart_script, output_dir, library_filename
     ])
     subprocess.call([command], shell=True)
     prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
@@ -340,11 +341,18 @@
         _logger.info('Generating dart2js single files.')
 
         for library_name in HTML_LIBRARY_NAMES:
+            source = os.path.join(dart2js_output_dir,
+                                  '%s_dart2js.dart' % library_name)
             GenerateSingleFile(
-                os.path.join(dart2js_output_dir,
-                             '%s_dart2js.dart' % library_name),
-                os.path.join('..', '..', '..', 'sdk', 'lib', library_name,
-                             'dart2js'))
+                source,
+                os.path.join('..', '..', '..', 'sdk', 'lib', library_name, 'dart2js'))
+            # TODO(Issue 38701): We won't need two copies once the NNBD SDK is
+            # unforked.
+            GenerateSingleFile(
+                source,
+                os.path.join('..', '..', '..', 'sdk_nnbd', 'lib', library_name, 'dart2js'),
+                None,
+                '// @dart = 2.5')
 
     print '\nGenerating single file %s seconds' % round(
         time.time() - file_generation_start_time, 2)
diff --git a/tools/gn.py b/tools/gn.py
index c98246a..81da03d 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -246,11 +246,13 @@
     gn_args['is_msan'] = args.msan
     gn_args['is_tsan'] = args.tsan
     gn_args['is_ubsan'] = args.ubsan
+    gn_args['include_dart2native'] = True
 
     if not args.platform_sdk and not gn_args['target_cpu'].startswith('arm'):
         gn_args['dart_platform_sdk'] = args.platform_sdk
     gn_args['dart_stripped_binary'] = 'exe.stripped/dart'
-    gn_args['dartaotruntime_stripped_binary'] = 'exe.stripped/dartaotruntime'
+    gn_args[
+        'dart_precompiled_runtime_stripped_binary'] = 'exe.stripped/dart_precompiled_runtime'
     gn_args['gen_snapshot_stripped_binary'] = 'exe.stripped/gen_snapshot'
 
     # Setup the user-defined sysroot.
diff --git a/tools/make_version.py b/tools/make_version.py
index 184699d..70f2900 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -5,6 +5,8 @@
 #
 # This python script creates a version string in a C++ file.
 
+from __future__ import print_function
+
 import hashlib
 import os
 import sys
@@ -14,7 +16,7 @@
 
 
 def debugLog(message):
-    print >> sys.stderr, message
+    print(message, file=sys.stderr)
     sys.stderr.flush()
 
 
@@ -55,16 +57,15 @@
         else:
             git_hash = utils.GetShortGitHash()
             version_string = ("%s.%s-%s" % (latest, custom_for_pub, git_hash))
-        # TODO(athom): remove the custom 2.5.0 logic post release.
-        # For 2.5.0, we want flutter to claim Dart is 2.5.0 even before it is
-        # decided what exactly 2.5.0 will be. Dart & Flutter stable releases
-        # will be synced, so that what will be released as Dart 2.5.0 will also
+        # TODO(athom): remove the custom 2.7.0 logic post release.
+        # For 2.7.0, we want flutter to claim Dart is 2.7.0 even before it is
+        # decided what exactly 2.7.0 will be. Dart & Flutter stable releases
+        # will be synced, so that what will be released as Dart 2.7.0 will also
         # be what will be packaged with Flutter.
         version = utils.ReadVersionFile()
         custom_version_string = "%s.%s.%s" % (version.major, version.minor, version.patch)
-        if custom_version_string == "2.5.0" and custom_for_pub == "flutter":
-            version_string = "2.5.0"
-
+        if custom_version_string == "2.7.0" and custom_for_pub == "flutter":
+            version_string = "2.7.0"
 
     else:
         version_string = utils.GetSemanticSDKVersion(no_git_hash=no_git_hash)
@@ -78,7 +79,7 @@
     for vmfilename in VM_SNAPSHOT_FILES:
         vmfilepath = os.path.join(utils.DART_DIR, 'runtime', 'vm', vmfilename)
         with open(vmfilepath) as vmfile:
-            vmhash.update(vmfile.read())
+            vmhash.update(vmfile.read().encode('utf-8'))
     return vmhash.hexdigest()
 
 
@@ -98,7 +99,7 @@
     version_time = utils.GetGitTimestamp()
     if no_git_hash or version_time == None:
         version_time = "Unknown timestamp"
-    version_cc_text = version_cc_text.replace("{{COMMIT_TIME}}", version_time)
+    version_cc_text = version_cc_text.replace("{{COMMIT_TIME}}", version_time.decode("utf-8"))
     abi_version = utils.GetAbiVersion(version_file)
     version_cc_text = version_cc_text.replace("{{ABI_VERSION}}", abi_version)
     oldest_supported_abi_version = utils.GetOldestSupportedAbiVersion(
diff --git a/tools/test.dart b/tools/test.dart
index 1e1b405..5a47fb3 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -6,7 +6,6 @@
 // Run tests like on the given builder and/or named configuration.
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
 
@@ -136,16 +135,22 @@
       orElse: () => "master");
 }
 
+class ResolvedConfigurations {
+  final Set<String> configurationNames;
+  final Set<String> builders;
+  ResolvedConfigurations(this.configurationNames, this.builders);
+}
+
 /// Finds the named configuration to test according to the test matrix
 /// information and the command line options.
-bool resolveNamedConfiguration(
+ResolvedConfigurations resolveNamedConfigurations(
     List<String> branches,
     List<dynamic> buildersConfigurations,
     String requestedBranch,
-    String requestedNamedConfiguration,
-    String requestedBuilder,
-    Set<String> outputNamedConfiguration,
-    Set<String> outputBuilders) {
+    List<String> requestedNamedConfigurations,
+    String requestedBuilder) {
+  Set<String> namedConfigurations = {};
+  Set<String> builders = {};
   bool foundBuilder = false;
   for (final builderConfiguration in buildersConfigurations) {
     for (final builder in builderConfiguration["builders"]) {
@@ -160,7 +165,7 @@
         stderr.writeln("error: Builder $requestedBuilder is on branch $branch "
             "rather than $requestedBranch");
         stderr.writeln("error: To compare with that branch, use: -B $branch");
-        return false;
+        return null;
       }
       foundBuilder = true;
       final steps = (builderConfiguration["steps"] as List).cast<Map>();
@@ -172,50 +177,50 @@
         final arguments = step["arguments"]
             .map((argument) => expandVariables(argument, builder))
             .toList();
-        final namedConfiguration = arguments
+        final String namedConfiguration = arguments
             .firstWhere((argument) => (argument as String).startsWith("-n"))
             .substring(2);
-        if (requestedNamedConfiguration == null ||
-            requestedNamedConfiguration == namedConfiguration) {
-          outputNamedConfiguration.add(namedConfiguration);
-          outputBuilders.add(builder);
+        if (namedConfiguration.contains(",")) {
+          throw "Multiple named configurations in builder configurations: "
+              "are currently not supported: '$arguments'";
+        }
+        if (requestedNamedConfigurations.isEmpty ||
+            requestedNamedConfigurations.contains(namedConfiguration)) {
+          namedConfigurations.add(namedConfiguration);
+          builders.add(builder);
         }
       }
     }
   }
   if (requestedBuilder != null && !foundBuilder) {
     stderr.writeln("error: Builder $requestedBuilder doesn't exist");
-    return false;
+    return null;
   }
   if (requestedBuilder != null &&
-      requestedNamedConfiguration == null &&
-      outputNamedConfiguration.isEmpty) {
+      requestedNamedConfigurations == null &&
+      namedConfigurations.isEmpty) {
     stderr.writeln("error: Builder $requestedBuilder isn't testing any named "
         "configurations");
-    return false;
+    return null;
   }
   if (requestedBuilder != null &&
-      requestedNamedConfiguration != null &&
-      outputNamedConfiguration.isEmpty) {
+      requestedNamedConfigurations != null &&
+      namedConfigurations.isEmpty) {
     stderr.writeln("error: The builder $requestedBuilder isn't testing the "
-        "named configuration $requestedNamedConfiguration");
-    return false;
+        "named configuration $requestedNamedConfigurations");
+    return null;
   }
-  if (requestedNamedConfiguration != null && outputBuilders.isEmpty) {
+  if (requestedNamedConfigurations != null && builders.isEmpty) {
     stderr.writeln("error: The named configuration "
-        "$requestedNamedConfiguration isn't tested on any builders");
-    return false;
+        "$requestedNamedConfigurations isn't tested on any builders");
+    return null;
   }
-  return true;
+
+  return ResolvedConfigurations(namedConfigurations, builders);
 }
 
 /// Locates the merge base between head and the [branch] on the given [remote].
-/// If a particular [commit] was requested, use that.
-Future<String> findMergeBase(
-    String commit, String remote, String branch) async {
-  if (commit != null) {
-    return commit;
-  }
+Future<String> findMergeBase(String remote, String branch) async {
   final arguments = ["merge-base", "$remote/$branch", "HEAD"];
   final result =
       await Process.run("git", arguments, runInShell: Platform.isWindows);
@@ -313,6 +318,42 @@
   }
 }
 
+void overrideConfiguration(Map<String, Map<String, dynamic>> results,
+    String configuration, String newConfiguration) {
+  results.forEach((String key, Map<String, dynamic> result) {
+    if (result["configuration"] == configuration) {
+      result["configuration"] = newConfiguration;
+    }
+  });
+}
+
+void printUsage(ArgParser parser, {String error, bool printOptions: false}) {
+  if (error != null) {
+    print("$error\n");
+    exitCode = 1;
+  }
+  print("""
+Usage: test.dart -b [BUILDER] -n [CONFIGURATION] [OPTION]... [--]
+                 [TEST.PY OPTION]... [SELECTOR]...
+
+Run tests and compare with the results on the given builder. Either the -n or
+the -b option, or both, must be used. Any options following -- and non-option
+arguments will be forwarded to test.py invocations. The specified named
+configuration's results will be downloaded from the specified builder. If only a
+named configuration is specified, the results are downloaded from the
+appropriate builders. If only a builder is specified, the default named
+configuration is used if the builder only has a single named configuration.
+Otherwise the available named configurations are listed.
+
+See the documentation at https://goto.google.com/dart-status-file-free-workflow
+""");
+  if (printOptions) {
+    print(parser.usage);
+  } else {
+    print("Run test.dart --help to see all options.");
+  }
+}
+
 void main(List<String> args) async {
   final parser = new ArgParser();
   parser.addOption("builder",
@@ -330,9 +371,9 @@
           "detected by --deflake will remain hidden");
   parser.addFlag("list-configurations",
       help: "Output list of configurations.", negatable: false);
-  parser.addOption("named-configuration",
+  parser.addMultiOption("named-configuration",
       abbr: "n",
-      help: "The named test configuration that supplies the\nvalues for all "
+      help: "The named test configuration(s) that supplies the\nvalues for all "
           "test options, specifying how tests\nshould be run.");
   parser.addOption("local-configuration",
       abbr: "N",
@@ -346,27 +387,16 @@
       defaultsTo: "origin");
   parser.addFlag("help", help: "Show the program usage.", negatable: false);
 
-  final options = parser.parse(args);
-  if (options["help"] ||
-      (options["builder"] == null &&
-          options["named-configuration"] == null &&
-          !options["list-configurations"])) {
-    print("""
-Usage: test.dart -b [BUILDER] -n [CONFIGURATION] [OPTION]... [--]
-                 [TEST.PY OPTION]... [SELECTOR]...
+  ArgResults options;
+  try {
+    options = parser.parse(args);
+  } on FormatException catch (exception) {
+    printUsage(parser, error: exception.message);
+    return;
+  }
 
-Run tests and compare with the results on the given builder. Either the -n or
-the -b option, or both, must be used. Any options following -- and non-option
-arguments will be forwarded to test.py invocations. The specified named
-configuration's results will be downloaded from the specified builder. If only a
-named configuration is specified, the results are downloaded from the
-appropriate builders. If only a builder is specified, the default named
-configuration is used if the builder only has a single named configuration.
-Otherwise the available named configurations are listed.
-
-See the documentation at https://goto.google.com/dart-status-file-free-workflow
-
-${parser.usage}""");
+  if (options["help"]) {
+    printUsage(parser, printOptions: true);
     return;
   }
 
@@ -378,6 +408,25 @@
     return;
   }
 
+  final requestedBuilder = options["builder"];
+  final namedConfigurations =
+      (options["named-configuration"] as List).cast<String>();
+  final localConfiguration = options["local-configuration"] as String;
+
+  if (requestedBuilder == null && namedConfigurations.isEmpty) {
+    printUsage(parser,
+        error: "Please specify either a configuration (-n) or "
+            "a builder (-b)");
+    return;
+  }
+
+  if (localConfiguration != null && namedConfigurations.length > 1) {
+    printUsage(parser,
+        error: "Local configuration (-N) can only be used with a"
+            " single named configuration (-n)");
+    return;
+  }
+
   // Locate gsutil.py.
   gsutilPy =
       Platform.script.resolve("../third_party/gsutil/gsutil.py").toFilePath();
@@ -394,47 +443,34 @@
 
   // Determine what named configuration to run and which builders to download
   // existing results from.
-  final namedConfigurations = new SplayTreeSet<String>();
-  final builders = new SplayTreeSet<String>();
-  if (!resolveNamedConfiguration(
+  ResolvedConfigurations configurations = resolveNamedConfigurations(
       branches,
       buildersConfigurations,
       options["branch"],
-      options["named-configuration"],
-      options["builder"],
       namedConfigurations,
-      builders)) {
+      requestedBuilder);
+  if (configurations == null) {
+    // No valid configuration could be found. The error has already been
+    // reported by [resolveConfiguration].
     exitCode = 1;
     return;
   }
-  if (namedConfigurations.length > 1) {
-    final builder = builders.single;
-    stderr.writeln(
-        "error: The builder $builder is testing multiple named configurations");
-    stderr.writeln(
-        "error: Please select the desired named configuration using -n:");
-    for (final namedConfiguration in namedConfigurations) {
-      stderr.writeln("  -n $namedConfiguration");
-    }
-    exitCode = 1;
-    return;
-  }
-  final namedConfiguration = namedConfigurations.single;
-  final localConfiguration =
-      options["local-configuration"] as String ?? namedConfiguration;
-  for (final builder in builders) {
-    if (localConfiguration != namedConfiguration) {
+
+  for (final builder in configurations.builders) {
+    if (localConfiguration != null) {
       print("Testing the named configuration $localConfiguration "
-          "compared with builder $builder's configuration $namedConfiguration");
+          "compared with builder $builder's configuration "
+          "${namedConfigurations.single}");
     } else {
-      print("Testing the named configuration $localConfiguration "
+      print("Testing the named configuration(s) "
+          "${namedConfigurations.join(",")} "
           "compared with builder $builder");
     }
   }
 
-  // Find out where the current HEAD branched.
-  final commit = await findMergeBase(
-      options["commit"], options["remote"], options["branch"]);
+  // Use given commit or find out where the current HEAD branched.
+  final commit = options["commit"] ??
+      await findMergeBase(options["remote"], options["branch"]);
   print("Base commit is $commit");
 
   // Store the downloaded results and our test results in a temporary directory.
@@ -443,9 +479,13 @@
     final mergedResults = <String, Map<String, dynamic>>{};
     final mergedFlaky = <String, Map<String, dynamic>>{};
 
+    bool needsConfigurationOverride = localConfiguration != null &&
+        localConfiguration != namedConfigurations.single;
+    bool needsMerge = configurations.builders.length > 1;
+
     // Use the buildbucket API to search for builds of the right commit.
-    final inexactBuilds = new SplayTreeMap<String, String>();
-    for (final builder in builders) {
+    final inexactBuilds = <String, String>{};
+    for (final builder in configurations.builders) {
       // Download the previous results and flakiness info from cloud storage.
       print("Finding build on builder $builder to compare with...");
       final buildSearchResult =
@@ -463,64 +503,63 @@
         await cpGsutil(buildFileCloudPath(builder, buildNumber, "flaky.json"),
             "${outDirectory.path}/flaky.json");
       }
-      print("Downloaded baseline results from builder $builder");
       // Merge the results for the builders.
-      if (builders.length > 1) {
-        mergedResults
-            .addAll(await loadResultsMap("${outDirectory.path}/previous.json"));
+      if (needsMerge || needsConfigurationOverride) {
+        var results =
+            await loadResultsMap("${outDirectory.path}/previous.json");
+        if (needsConfigurationOverride) {
+          overrideConfiguration(
+              results, namedConfigurations.single, localConfiguration);
+        }
+        mergedResults.addAll(results);
         if (!options["report-flakes"]) {
-          mergedFlaky
-              .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+          var flakyTests =
+              await loadResultsMap("${outDirectory.path}/flaky.json");
+          if (needsConfigurationOverride) {
+            overrideConfiguration(
+                flakyTests, namedConfigurations.single, localConfiguration);
+          }
+          mergedFlaky.addAll(flakyTests);
         }
       }
     }
 
     // Write out the merged results for the builders.
-    if (builders.length > 1) {
+    if (needsMerge || needsConfigurationOverride) {
       await new File("${outDirectory.path}/previous.json").writeAsString(
           mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
     }
 
     // Ensure that there is a flaky.json even if it wasn't downloaded.
-    if (builders.length > 1 || options["report-flakes"]) {
+    if (needsMerge || needsConfigurationOverride || options["report-flakes"]) {
       await new File("${outDirectory.path}/flaky.json").writeAsString(
           mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
     }
 
-    // Override the named configuration in the baseline data if needed.
-    if (namedConfiguration != localConfiguration) {
-      for (final path in [
-        "${outDirectory.path}/previous.json",
-        "${outDirectory.path}/flaky.json"
-      ]) {
-        final results = await loadResultsMap(path);
-        final records = results.values
-            .where((r) => r["configuration"] == namedConfiguration)
-            .toList()
-              ..forEach((r) => r["configuration"] = localConfiguration);
-        await new File(path).writeAsString(
-            records.map((data) => jsonEncode(data) + "\n").join(""));
-      }
-    }
+    final configurationsToRun = localConfiguration != null
+        ? <String>[localConfiguration]
+        : namedConfigurations;
 
     // Run the tests.
-    final arguments = [
-      "--named-configuration=$localConfiguration",
-      "--output-directory=${outDirectory.path}",
-      "--clean-exit",
-      "--silent-failures",
-      "--write-results",
-      "--write-logs",
-      ...options.rest,
-    ];
     print("".padLeft(80, "="));
     print("Running tests");
     print("".padLeft(80, "="));
-    await runProcessInheritStdio("python", ["tools/test.py", ...arguments],
+    await runProcessInheritStdio(
+        "python",
+        [
+          "tools/test.py",
+          "--named-configuration=${configurationsToRun.join(",")}",
+          "--output-directory=${outDirectory.path}",
+          "--clean-exit",
+          "--silent-failures",
+          "--write-results",
+          "--write-logs",
+          ...options.rest,
+        ],
         runInShell: Platform.isWindows);
 
     if (options["deflake"]) {
-      await deflake(outDirectory, localConfiguration, options.rest);
+      await deflake(outDirectory, configurationsToRun, options.rest);
     }
 
     // Write out the final comparison.
@@ -546,16 +585,19 @@
     }
     if (inexactBuilds.isNotEmpty) {
       print("");
-      inexactBuilds.forEach((String builder, String inexactCommit) => print(
-          "Warning: Results may be inexact because commit ${inexactCommit} "
-          "was used as the baseline for $builder instead of $commit"));
+      final builders = inexactBuilds.keys.toList()..sort();
+      for (var builder in builders) {
+        final inexactCommit = inexactBuilds[builder];
+        print("Warning: Results may be inexact because commit ${inexactCommit} "
+            "was used as the baseline for $builder instead of $commit");
+      }
     }
   } finally {
     await outDirectory.delete(recursive: true);
   }
 }
 
-void deflake(Directory outDirectory, String localConfiguration,
+void deflake(Directory outDirectory, List<String> configurations,
     List<String> testPyArgs) async {
   // Find the list of tests to deflake.
   final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
@@ -580,7 +622,7 @@
     final deflakeDirectory = new Directory("${outDirectory.path}/$i");
     await deflakeDirectory.create();
     final deflakeArguments = <String>[
-      "--named-configuration=$localConfiguration",
+      "--named-configuration=${configurations.join(",")}",
       "--output-directory=${deflakeDirectory.path}",
       "--clean-exit",
       "--silent-failures",